Logo Search packages:      
Sourcecode: uget version File versions  Download package

ug_url.c

/*
 *
 *   Copyright (C) 2005-2009 by Raymond Huang
 *   plushuang at users.sourceforge.net
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *  ---
 *
 *  In addition, as a special exception, the copyright holders give
 *  permission to link the code of portions of this program with the
 *  OpenSSL library under certain conditions as described in each
 *  individual source file, and distribute linked combinations
 *  including the two.
 *  You must obey the GNU Lesser General Public License in all respects
 *  for all of the code used other than OpenSSL.  If you modify
 *  file(s) with this exception, you may extend this exception to your
 *  version of the file(s), but you are not obligated to do so.  If you
 *  do not wish to do so, delete this exception statement from your
 *  version.  If you delete this exception statement from all source
 *  files in the program, then also delete it here.
 *
 */

#include <string.h>
#include <ug_url.h>

// UgUrlPart -----------------------------------------------------------

static void ug_url_part_other (UgUrlPart* upart, const char* str, int len);

UgUrlPart* ug_url_part_new (const char* url, int len)
{
      UgUrlPart* upart = g_malloc (sizeof (UgUrlPart));

      ug_url_part (upart, url, len);
      return upart;
}

void ug_url_part_free (UgUrlPart* upart)
{
      g_free (upart);
}

int  ug_url_part (UgUrlPart* upart, const char* str, int len)
{
      char  chr;
      int   index, index2;
      int   continue_flag;

      // initialize
      memset (upart, 0, sizeof (UgUrlPart));
      if (len == -1)
            len = (int) strlen (str);

      // scheme
      for (index=0; index<=len; index++) {
            if (index==len) {
                  // Maybe a relative URI
                  ug_url_part_other (upart, str, len);
                  return FALSE;
            }

            chr = str[index];
            if ( (chr>='a' && chr<='z') || (chr>='A' && chr<='Z') || (chr >= '0' && chr <= '9') ||
                  chr == '%' || chr=='+' || chr=='-' || chr == '.')
                  continue;
            if (chr == ':' && index!=0 && len - index >= 3 && str[index+1]=='/' && str[index+2]=='/') {
                  upart->url        = str;
                  upart->url_len    = len;
                  upart->url_scheme_len   = index;
                  index += 3;
                  break;
            }
            else {
                  // Maybe a relative URI
                  ug_url_part_other (upart, str, len);
                  return FALSE;
            }
      }

      // user:password and host:port
      for (index2=index, continue_flag=TRUE; continue_flag; ++index) {
            if (index == len) {
                  if (index2 == len)
                        break;
                  chr = '/';    // this will break loop
            }
            else
                  chr = str[index];

            switch (chr) {
            case '/':
                  continue_flag = FALSE;    // break loop
            case '@':
                  if (upart->host) {
                        upart->port     = str + index2;
                        upart->port_len = index - index2;
                        break;
                  }
            case ':':
                  upart->host     = str + index2;
                  upart->host_len = index - index2;
                  index2 = index+1;
                  break;
            }

            if (chr == '@' && upart->user == NULL) {
            // swap host:port and user:password
                  upart->user         = upart->host;
                  upart->user_len     = upart->host_len;
                  upart->password     = upart->port;
                  upart->password_len = upart->port_len;

                  upart->host     = NULL;
                  upart->host_len = 0;
                  upart->port     = NULL;
                  upart->port_len = 0;
                  index2 = index+1;
            }
      }

      upart->url_location_len = index;
      if (index < len)
            ug_url_part_other (upart, str + index, len - index);
      upart->url_location_len += upart->folder_len;

      return (upart->host_len);
}

void ug_url_part_other (UgUrlPart* upart, const char* str, int len)
{
      int  index;
      char chr;

      for (index = 0;  ;  index++) {
            if (index == len) {
                  ug_path_part_full ((UgPathPart*)upart, str, index, '/');
                  return;
            }

            chr = str[index];
            if (chr == '?' || chr == '#') {
                  ug_path_part_full ((UgPathPart*)upart, str, index, '/');
                  break;
            }
      }

      // query and fragment
      for (;  index < len;  index++) {
            chr = str[index];

            if (chr == '?' && upart->query == NULL) {
                  upart->query     = str + index + 1;
                  upart->query_len = len - index - 1;
            }
            else if (chr == '#') {
                  upart->fragment     = str + index + 1;
                  upart->fragment_len = len - index - 1;
                  if (upart->query)
                        upart->query_len -= upart->fragment_len + 1;
                  return;
            }
      }
}

char* ug_url_unescape_to_utf8 (const char* str, int str_len)
{
      char* result;
      char* result_utf8;

      if (str_len == -1)
            str_len = strlen (str);
      result = g_uri_unescape_segment (str, str+str_len, NULL);

      // check encoding
      if (g_utf8_validate (result, -1, NULL) == FALSE) {
            result_utf8 = g_locale_to_utf8 (result, -1, NULL, NULL, NULL);
            g_free (result);
            // if result is not locale encoding, don't unescape it.
            if (result_utf8 == NULL)
                  result_utf8 = g_locale_to_utf8 (str, str_len, NULL, NULL, NULL);
            // duplicate string if convert fail.
            if (result_utf8 == NULL)
                  result_utf8 = g_strndup (str, str_len);
            return result_utf8;
      }
      return result;
}


Generated by  Doxygen 1.6.0   Back to index