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

📄 url.c

📁 Wget很好的处理了http和ftp的下载,很值得学习的经典代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      /* We're looking for the first slash, but want to ignore         double slash. */    again:      slash = memchr (pos, '/', end - pos);      if (slash && !seen_slash_slash)        if (*(slash + 1) == '/')          {            pos = slash + 2;            seen_slash_slash = true;            goto again;          }      /* At this point, SLASH is the location of the first / after         "//", or the first slash altogether.  START_INSERT is the         pointer to the location where LINK will be inserted.  When         examining the last two examples, keep in mind that LINK         begins with '/'. */      if (!slash && !seen_slash_slash)        /* example: "foo" */        /*           ^    */        start_insert = base;      else if (!slash && seen_slash_slash)        /* example: "http://foo" */        /*                     ^ */        start_insert = end;      else if (slash && !seen_slash_slash)        /* example: "foo/bar" */        /*           ^        */        start_insert = base;      else if (slash && seen_slash_slash)        /* example: "http://something/" */        /*                           ^  */        start_insert = slash;      span = start_insert - base;      merge = xmalloc (span + linklength + 1);      if (span)        memcpy (merge, base, span);      memcpy (merge + span, link, linklength);      merge[span + linklength] = '\0';    }  else    {      /* LINK is a relative URL: we need to replace everything         after last slash (possibly empty) with LINK.         So, if BASE is "whatever/foo/bar", and LINK is "qux/xyzzy",         our result should be "whatever/foo/qux/xyzzy".  */      bool need_explicit_slash = false;      int span;      const char *start_insert;      const char *last_slash = find_last_char (base, end, '/');      if (!last_slash)        {          /* No slash found at all.  Replace what we have with LINK. */          start_insert = base;        }      else if (last_slash && last_slash >= base + 2               && last_slash[-2] == ':' && last_slash[-1] == '/')        {          /* example: http://host"  */          /*                      ^ */          start_insert = end + 1;          need_explicit_slash = true;        }      else        {          /* example: "whatever/foo/bar" */          /*                        ^    */          start_insert = last_slash + 1;        }      span = start_insert - base;      merge = xmalloc (span + linklength + 1);      if (span)        memcpy (merge, base, span);      if (need_explicit_slash)        merge[span - 1] = '/';      memcpy (merge + span, link, linklength);      merge[span + linklength] = '\0';    }  return merge;}#define APPEND(p, s) do {                       \  int len = strlen (s);                         \  memcpy (p, s, len);                           \  p += len;                                     \} while (0)/* Use this instead of password when the actual password is supposed   to be hidden.  We intentionally use a generic string without giving   away the number of characters in the password, like previous   versions did.  */#define HIDDEN_PASSWORD "*password*"/* Recreate the URL string from the data in URL.   If HIDE is true (as it is when we're calling this on a URL we plan   to print, but not when calling it to canonicalize a URL for use   within the program), password will be hidden.  Unsafe characters in   the URL will be quoted.  */char *url_string (const struct url *url, enum url_auth_mode auth_mode){  int size;  char *result, *p;  char *quoted_host, *quoted_user = NULL, *quoted_passwd = NULL;  int scheme_port = supported_schemes[url->scheme].default_port;  const char *scheme_str = supported_schemes[url->scheme].leading_string;  int fplen = full_path_length (url);  bool brackets_around_host;  assert (scheme_str != NULL);  /* Make sure the user name and password are quoted. */  if (url->user)    {      if (auth_mode != URL_AUTH_HIDE)        {          quoted_user = url_escape_allow_passthrough (url->user);          if (url->passwd)            {              if (auth_mode == URL_AUTH_HIDE_PASSWD)                quoted_passwd = HIDDEN_PASSWORD;              else                quoted_passwd = url_escape_allow_passthrough (url->passwd);            }        }    }  /* In the unlikely event that the host name contains non-printable     characters, quote it for displaying to the user.  */  quoted_host = url_escape_allow_passthrough (url->host);  /* Undo the quoting of colons that URL escaping performs.  IPv6     addresses may legally contain colons, and in that case must be     placed in square brackets.  */  if (quoted_host != url->host)    unescape_single_char (quoted_host, ':');  brackets_around_host = strchr (quoted_host, ':') != NULL;  size = (strlen (scheme_str)          + strlen (quoted_host)          + (brackets_around_host ? 2 : 0)          + fplen          + 1);  if (url->port != scheme_port)    size += 1 + numdigit (url->port);  if (quoted_user)    {      size += 1 + strlen (quoted_user);      if (quoted_passwd)        size += 1 + strlen (quoted_passwd);    }  p = result = xmalloc (size);  APPEND (p, scheme_str);  if (quoted_user)    {      APPEND (p, quoted_user);      if (quoted_passwd)        {          *p++ = ':';          APPEND (p, quoted_passwd);        }      *p++ = '@';    }  if (brackets_around_host)    *p++ = '[';  APPEND (p, quoted_host);  if (brackets_around_host)    *p++ = ']';  if (url->port != scheme_port)    {      *p++ = ':';      p = number_to_string (p, url->port);    }  full_path_write (url, p);  p += fplen;  *p++ = '\0';  assert (p - result == size);  if (quoted_user && quoted_user != url->user)    xfree (quoted_user);  if (quoted_passwd && auth_mode == URL_AUTH_SHOW      && quoted_passwd != url->passwd)    xfree (quoted_passwd);  if (quoted_host != url->host)    xfree (quoted_host);  return result;}/* Return true if scheme a is similar to scheme b.    Schemes are similar if they are equal.  If SSL is supported, schemes   are also similar if one is http (SCHEME_HTTP) and the other is https   (SCHEME_HTTPS).  */boolschemes_are_similar_p (enum url_scheme a, enum url_scheme b){  if (a == b)    return true;#ifdef HAVE_SSL  if ((a == SCHEME_HTTP && b == SCHEME_HTTPS)      || (a == SCHEME_HTTPS && b == SCHEME_HTTP))    return true;#endif  return false;}static intgetchar_from_escaped_string (const char *str, char *c){    const char *p = str;  assert (str && *str);  assert (c);    if (p[0] == '%')    {      if (!ISXDIGIT(p[1]) || !ISXDIGIT(p[2]))        {          *c = '%';          return 1;        }      else        {          if (p[2] == 0)            return 0; /* error: invalid string */          *c = X2DIGITS_TO_NUM (p[1], p[2]);          if (URL_RESERVED_CHAR(*c))            {              *c = '%';              return 1;            }          else            return 3;        }    }  else    {      *c = p[0];    }  return 1;}boolare_urls_equal (const char *u1, const char *u2){  const char *p, *q;  int pp, qq;  char ch1, ch2;  assert(u1 && u2);  p = u1;  q = u2;  while (*p && *q         && (pp = getchar_from_escaped_string (p, &ch1))         && (qq = getchar_from_escaped_string (q, &ch2))         && (TOLOWER(ch1) == TOLOWER(ch2)))    {      p += pp;      q += qq;    }    return (*p == 0 && *q == 0 ? true : false);}#if 0/* Debugging and testing support for path_simplify. *//* Debug: run path_simplify on PATH and return the result in a new   string.  Useful for calling from the debugger.  */static char *ps (char *path){  char *copy = xstrdup (path);  path_simplify (copy);  return copy;}static voidrun_test (char *test, char *expected_result, bool expected_change){  char *test_copy = xstrdup (test);  bool modified = path_simplify (test_copy);  if (0 != strcmp (test_copy, expected_result))    {      printf ("Failed path_simplify(\"%s\"): expected \"%s\", got \"%s\".\n",              test, expected_result, test_copy);    }  if (modified != expected_change)    {      if (expected_change)        printf ("Expected modification with path_simplify(\"%s\").\n",                test);      else        printf ("Expected no modification with path_simplify(\"%s\").\n",                test);    }  xfree (test_copy);}static voidtest_path_simplify (void){  static struct {    char *test, *result;    bool should_modify;  } tests[] = {    { "",                       "",             false },    { ".",                      "",             true },    { "./",                     "",             true },    { "..",                     "",             true },    { "../",                    "",             true },    { "foo",                    "foo",          false },    { "foo/bar",                "foo/bar",      false },    { "foo///bar",              "foo///bar",    false },    { "foo/.",                  "foo/",         true },    { "foo/./",                 "foo/",         true },    { "foo./",                  "foo./",        false },    { "foo/../bar",             "bar",          true },    { "foo/../bar/",            "bar/",         true },    { "foo/bar/..",             "foo/",         true },    { "foo/bar/../x",           "foo/x",        true },    { "foo/bar/../x/",          "foo/x/",       true },    { "foo/..",                 "",             true },    { "foo/../..",              "",             true },    { "foo/../../..",           "",             true },    { "foo/../../bar/../../baz", "baz",         true },    { "a/b/../../c",            "c",            true },    { "./a/../b",               "b",            true }  };  int i;  for (i = 0; i < countof (tests); i++)    {      char *test = tests[i].test;      char *expected_result = tests[i].result;      bool  expected_change = tests[i].should_modify;      run_test (test, expected_result, expected_change);    }}#endif#ifdef TESTINGconst char *test_append_uri_pathel(){  int i;  struct {    char *original_url;    char *input;    bool escaped;    char *expected_result;  } test_array[] = {    { "http://www.yoyodyne.com/path/", "somepage.html", false, "http://www.yoyodyne.com/path/somepage.html" },  };    for (i = 0; i < sizeof(test_array)/sizeof(test_array[0]); ++i)     {      struct growable dest;      const char *p = test_array[i].input;            memset (&dest, 0, sizeof (dest));            append_string (test_array[i].original_url, &dest);      append_uri_pathel (p, p + strlen(p), test_array[i].escaped, &dest);      append_char ('\0', &dest);      mu_assert ("test_append_uri_pathel: wrong result",                  strcmp (dest.base, test_array[i].expected_result) == 0);    }  return NULL;}const char*test_are_urls_equal(){  int i;  struct {    char *url1;    char *url2;    bool expected_result;  } test_array[] = {    { "http://www.adomain.com/apath/", "http://www.adomain.com/apath/",       true },    { "http://www.adomain.com/apath/", "http://www.adomain.com/anotherpath/", false },    { "http://www.adomain.com/apath/", "http://www.anotherdomain.com/path/",  false },    { "http://www.adomain.com/~path/", "http://www.adomain.com/%7epath/",     true },    { "http://www.adomain.com/longer-path/", "http://www.adomain.com/path/",  false },    { "http://www.adomain.com/path%2f", "http://www.adomain.com/path/",       false },  };    for (i = 0; i < sizeof(test_array)/sizeof(test_array[0]); ++i)     {      mu_assert ("test_are_urls_equal: wrong result",                  are_urls_equal (test_array[i].url1, test_array[i].url2) == test_array[i].expected_result);    }  return NULL;}#endif /* TESTING *//* * vim: et ts=2 sw=2 */

⌨️ 快捷键说明

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