⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uri.c

📁 libmms开发库源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* GNet - Networking library * Copyright (C) 2000-2003  David Helder, David Bolcsfoldi, Eric Williams * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA  02111-1307, USA. *//* FIXME: #include "gnet-private.h" */#include <glib.h>#include <string.h>#include <malloc.h>#include <ctype.h>#include "uri.h"#include <string.h>static void   field_unescape (char *str);static char* field_escape (char* str, unsigned char mask);#define USERINFO_ESCAPE_MASK	0x01#define PATH_ESCAPE_MASK	0x02#define QUERY_ESCAPE_MASK	0x04#define FRAGMENT_ESCAPE_MASK	0x08/* #define FALSE 0 *//* #define TRUE  (!FALSE) */static unsigned char neednt_escape_table[] = {	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 	0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x0f, 	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 	0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x00, 0x0c, 	0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 	0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x00, 0x00, 0x0f, 	0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 	0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};/*Perl code to generate above table:#!/usr/bin/perl$ok = "abcdefghijklmnopqrstuvwxyz" .       "ABCDEFGHIJKLMNOPQRSTUVWXYZ" .      "0123456789" .      "-_.!~*'()";$userinfo_ok = ';:&=+\$,';$path_ok     = ':\@&=+\$,;/';$query_ok    = ';/?:\@&=+\$,';$fragment_ok = ';/?:\@&=+\$,';for ($i = 0; $i < 32; $i++){    print "  ";    for ($j = 0; $j < 8; $j++)    {	$num = 0;	$letter = chr(($i * 8) + $j);	$num |= 0b0001  if (index($userinfo_ok, $letter) != -1);	$num |= 0b0010  if (index($path_ok,     $letter) != -1);	$num |= 0b0100  if (index($query_ok,    $letter) != -1);	$num |= 0b1000  if (index($fragment_ok, $letter) != -1);	$num |= 0b1111  if (index($ok,          $letter) != -1);	printf "0x%02x, ", $num;    }    print "\n";}*//* our own ISSPACE.  ANSI isspace is local dependent */#define ISSPACE(C) (((C) >= 9 && (C) <= 13) || (C) == ' ')static int split_user_passwd(const char* in, char** user, char** passwd){  char *tmp = strdup(in);  if(!tmp)    return 0;  *passwd = strchr(tmp, ':');  if(!(*passwd))  {    free(tmp);    return 0;  }  *((*passwd)++) = '\0'; // don't you love C? :)  *user = strdup(tmp);  if(!*user)    return 0;  *passwd = strdup(*passwd);  if(!*passwd)    return 0;  free(tmp);  return 1;}/** *  gnet_uri_new *  @uri: URI string * *  Creates a #GURI from a string.  Empty fields are set to NULL.  The *  parser does not validate the URI -- it will accept some malformed *  URI.  URIs are usually in the form *  scheme://userinfo@hostname:port/path?query#fragment * *  URIs created from user input are typically unescaped.  URIs *  created from machine input (e.g. received over the internet) are *  typically escaped. *   *  Returns: a new #GURI, or NULL if there was a failure. * **/GURI* gnet_uri_new (const char* uri){  GURI* guri = NULL;  const char* p;  const char* temp;  g_return_val_if_fail (uri, NULL);  /* Skip initial whitespace */  p = uri;  while (*p && ISSPACE((int)*p))    ++p;  if (!*p)	/* Error if it's just a string of space */    return NULL;  guri = g_new0 (GURI, 1);  /* Scheme */  temp = p;  while (*p && *p != ':' && *p != '/' && *p != '?' && *p != '#')    ++p;  if (*p == ':')    {      guri->scheme = g_strndup (temp, p - temp);      ++p;    }  else	/* This char is NUL, /, ?, or # */    p = temp;  /* Authority */  if (*p == '/' && p[1] == '/')    {      char *userinfo;      p += 2;      /* Userinfo */      temp = p;      while (*p && *p != '@' && *p != '/' ) /* Look for @ or / */	++p;      if (*p == '@') /* Found userinfo */	{	  userinfo = g_strndup (temp, p - temp);	  if(!split_user_passwd(userinfo, &guri->user, &guri->passwd))	  {	    free(userinfo);	    goto error;	  }	  free(userinfo);	  ++p;	}      else	p = temp;      /* Hostname */      /* Check for IPv6 canonical hostname in brackets */      if (*p == '[')	{	  p++;  /* Skip [ */	  temp = p;	  while (*p && *p != ']') ++p;	  if ((p - temp) == 0)	    goto error;	  guri->hostname = g_strndup (temp, p - temp);	  if (*p)	    p++;	/* Skip ] (if there) */	}      else	{	  temp = p;	  while (*p && *p != '/' && *p != '?' && *p != '#' && *p != ':') ++p;	  if ((p - temp) == 0) 	    goto error;	  guri->hostname = g_strndup (temp, p - temp);	}      /* Port */      if (*p == ':')	{	  for (++p; isdigit((int)*p); ++p)	    guri->port = guri->port * 10 + (*p - '0');	}    }  /* Path (we are liberal and won't check if it starts with /) */  temp = p;  while (*p && *p != '?' && *p != '#')    ++p;  if (p != temp)    guri->path = g_strndup(temp, p - temp);  /* Query */  if (*p == '?')    {      temp = p + 1;      while (*p && *p != '#')        ++p;      guri->query = g_strndup (temp, p - temp);    }  /* Fragment */  if (*p == '#')    {      ++p;      guri->fragment = g_strdup (p);    }  return guri; error:  gnet_uri_delete (guri);  return NULL;}/** *  gnet_uri_new_fields *  @scheme: scheme *  @hostname: host name *  @port: port *  @path: path * *  Creates a #GURI from the fields.  This function uses the most *  common fields.  Use gnet_uri_new_fields_all() to specify all *  fields. * *  Returns: a new #GURI. * **/GURI*     gnet_uri_new_fields (const char* scheme, const char* hostname, 		     const gint port, const char* path){  GURI* uri = NULL;  uri = g_new0 (GURI, 1);  if (scheme)		uri->scheme = g_strdup (scheme);  if (hostname)		uri->hostname = g_strdup (hostname);  uri->port = port;  if (path)		uri->path = g_strdup (path);  return uri;}/** *  gnet_uri_new_fields_all *  @scheme: scheme *  @userinfo: user info *  @hostname: host name *  @port: port *  @path: path *  @query: query *  @fragment: fragment * *  Creates a #GURI from all fields. * *  Returns: a new #GURI. * **/GURI*gnet_uri_new_fields_all (const char* scheme, const char* user, 			 const char* passwd, const char* hostname,			 const gint port, const char* path, 			 const char* query, const char* fragment){  GURI* uri = NULL;  uri = g_new0 (GURI, 1);  if (scheme)		uri->scheme   = g_strdup (scheme);  if (user)		uri->user     = g_strdup (user);  if (passwd)		uri->passwd   = g_strdup (passwd);  if (hostname)		uri->hostname = g_strdup (hostname);  uri->port = port;  if (path)		uri->path     = g_strdup (path);  if (query)		uri->query    = g_strdup (query);  if (fragment)		uri->fragment = g_strdup (fragment);  return uri;}/** *  gnet_uri_clone: *  @uri: a #GURI *  *  Copies a #GURI. * *  Returns: a copy of @uri. * **/GURI*     gnet_uri_clone (const GURI* uri){  GURI* uri2;  g_return_val_if_fail (uri, NULL);  uri2 = g_new0 (GURI, 1);  uri2->scheme   = g_strdup (uri->scheme);  uri2->user     = g_strdup (uri->user);  uri2->passwd   = g_strdup (uri->passwd);  uri2->hostname = g_strdup (uri->hostname);  uri2->port     = uri->port;  uri2->path 	 = g_strdup (uri->path);  uri2->query    = g_strdup (uri->query);  uri2->fragment = g_strdup (uri->fragment);  return uri2;}/**  *  gnet_uri_delete: *  @uri: a #GURI * *  Deletes a #GURI. * **/voidgnet_uri_delete (GURI* uri){  if (uri)    {      g_free (uri->scheme);      g_free (uri->user);      g_free (uri->passwd);      g_free (uri->hostname);      g_free (uri->path);      g_free (uri->query);      g_free (uri->fragment);      g_free (uri);    }}#define SAFESTRCMP(A,B) (((A)&&(B))?(strcmp((A),(B))):((A)||(B)))/** *  gnet_uri_equal *  @p1: a #GURI *  @p2: another #GURI * *  Compares two #GURI's for equality. * *  Returns: TRUE if they are equal; FALSE otherwise. * **/intgnet_uri_equal (gconstpointer p1, gconstpointer p2){  const GURI* uri1 = (const GURI*) p1;  const GURI* uri2 = (const GURI*) p2;  g_return_val_if_fail (uri1, FALSE);  g_return_val_if_fail (uri2, FALSE);  if (uri1->port == uri2->port &&      !SAFESTRCMP(uri1->scheme, uri2->scheme) &&      !SAFESTRCMP(uri1->user, uri2->user) &&      !SAFESTRCMP(uri1->passwd, uri2->passwd) &&      !SAFESTRCMP(uri1->hostname, uri2->hostname) &&      !SAFESTRCMP(uri1->path, uri2->path) &&      !SAFESTRCMP(uri1->query, uri2->query) &&      !SAFESTRCMP(uri1->fragment, uri2->fragment))    return TRUE;  return FALSE;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -