📄 url.c
字号:
} else if (type == URLUNKNOWN) /* or a directory */ u->proto = type = URLFTP; else /* or just a misformed port number */ return URLBADPORT; } else if (type == URLUNKNOWN) u->proto = type = URLHTTP; if (!u->port) { int ind; for (ind = 0; ind < ARRAY_SIZE(sup_protos); ind++) if (sup_protos[ind].ind == type) break; if (ind == ARRAY_SIZE(sup_protos)) return URLUNKNOWN; u->port = sup_protos[ind].port; } /* Some delimiter troubles... */ if (url[i] == '/' && url[i - 1] != ':') ++i; if (type == URLHTTP) while (url[i] && url[i] == '/') ++i; u->path = (char *) kmalloc(strlen(url + i) + 8); strcpy(u->path, url + i); if (type == URLFTP) { u->ftp_type = process_ftp_type(u->path); /* #### We don't handle type `d' correctly yet. */ if (!u->ftp_type || toupper(u->ftp_type) == 'D') u->ftp_type = 'I'; } /* Parse the username and password (if existing). */ parse_uname(url, &u->user, &u->passwd); /* Decode the strings, as per RFC 1738. */ decode_string(u->host); // decode_string(u->path); if (u->user) decode_string(u->user); if (u->passwd) decode_string(u->passwd); /* Parse the directory. */ parse_dir(u->path, &u->dir, &u->file); /* Simplify the directory. */ path_simplify(u->dir); /* Remove the leading `/' in HTTP. */ if (type == URLHTTP && *u->dir == '/') strcpy(u->dir, u->dir + 1); /* Strip trailing `/'. */ l = strlen(u->dir); if (l > 1 && u->dir[l - 1] == '/') u->dir[l - 1] = '\0'; /* Re-create the path: */ abs_ftp = (u->proto == URLFTP && *u->dir == '/'); /* sprintf (u->path, "%s%s%s%s", abs_ftp ? "%2F": "/", abs_ftp ? (u->dir + 1) : u->dir, *u->dir ? "/" : "", u->file); */ strcpy(u->path, abs_ftp ? "%2F" : "/"); strcat(u->path, abs_ftp ? (u->dir + 1) : u->dir); strcat(u->path, *u->dir ? "/" : ""); strcat(u->path, u->file); ENCODE(u->path); /* Create the clean URL. */ u->url = str_url(u, 0); return URLOK;}/****************************************************************************** This function constructs and returns a malloced copy of the relative link from two pieces of information: local name of the referring file (s1) and local name of the referred file (s2). So, if s1 is "jagor.srce.hr/index.html" and s2 is "jagor.srce.hr/images/news.gif", new name should be "images/news.gif". Alternately, if the s1 is "fly.cc.fer.hr/ioccc/index.html", and s2 is "fly.cc.fer.hr/images/fly.gif", new name should be "../images/fly.gif". Caveats: s1 should not begin with '/', unless s2 begins with '/' too. s1 should not contain things like ".." and such -- construct_relative("fly/ioccc/../index.html", "fly/images/fly.gif") will fail. (workaround is to call path_simplify on s1).******************************************************************************/char *construct_relative(const char *s1, const char *s2){ int i, cnt, sepdirs1; char *res; if (*s2 == '/') return kstrdup(s2); /* s1 should *not* be absolute, if s2 wasn't. */ assert(*s1 != '/'); i = cnt = 0; /* Skip the directories common to both strings. */ while (1) { for (; s1[i] && s2[i] && s1[i] == s2[i] && s1[i] != '/' && s2[i] != '/'; i++); if (s1[i] == '/' && s2[i] == '/') cnt = ++i; else break; } for (sepdirs1 = 0; s1[i]; i++) if (s1[i] == '/') ++sepdirs1; /* Now, construct the file as of: - ../ repeated sepdirs1 time - all the non-mutual directories of s2. */ res = kmalloc(3 * sepdirs1 + strlen(s2 + cnt) + 1); for (i = 0; i < sepdirs1; i++) memcpy(res + 3 * i, "../", 3); strcpy(res + 3 * i, s2 + cnt); return res;}/****************************************************************************** Add a URL to the list.******************************************************************************/urlpos *add_url(urlpos * l, const char *url, const char *file){ urlpos *t, *b; t = kmalloc(sizeof(urlpos)); memset(t, 0, sizeof(*t)); t->url = kstrdup(url); t->local_name = kstrdup(file); if (!l) return t; b = l; while (l->next) l = l->next; l->next = t; return b;}/*This will copy a url structure to another */void url_cpy(urlinfo * src, urlinfo * dest){}/* Find the last occurrence of character C in the range [b, e), or NULL, if none are present. This is almost completely equivalent to { *e = '\0'; return strrchr(b); }, except that it doesn't change the contents of the string. */const char *find_last_char(const char *b, const char *e, char c){ for (; e > b; e--) if (*e == c) return e; return NULL;}/* Resolve the result of "linking" a base URI (BASE) to a link-specified URI (LINK). Either of the URIs may be absolute or relative, complete with the host name, or path only. This tries to behave "reasonably" in all foreseeable cases. It employs little specific knowledge about protocols or URL-specific stuff -- it just works on strings. The parameters LINKLENGTH is useful if LINK is not zero-terminated. See uri_merge for a gentler interface to this functionality. #### This function should handle `./' and `../' so that the evil path_simplify can go. */char *uri_merge_1(const char *base, const char *link, int linklength, int no_proto){ char *constr; if (no_proto) { const char *end = base + urlpath_length(base); if (*link != '/') { /* 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". */ int need_explicit_slash = 0; int span; const char *start_insert; const char *last_slash = find_last_char(base, end, '/'); if (!last_slash) { /* No slash found at all. Append LINK to what we have, but we'll need a slash as a separator. Example: if base == "foo" and link == "qux/xyzzy", then we cannot just append link to base, because we'd get "fooqux/xyzzy", whereas what we want is "foo/qux/xyzzy". To make sure the / gets inserted, we set need_explicit_slash to 1. We also set start_insert to end + 1, so that the length calculations work out correctly for one more (slash) character. Accessing that character is fine, since it will be the delimiter, '\0' or '?'. */ /* example: "foo?..." */ /* ^ ('?' gets changed to '/') */ start_insert = end + 1; need_explicit_slash = 1; } else if (last_slash && last_slash != base && *(last_slash - 1) == '/') { /* example: http://host" */ /* ^ */ start_insert = end + 1; need_explicit_slash = 1; } else { /* example: "whatever/foo/bar" */ /* ^ */ start_insert = last_slash + 1; } span = start_insert - base; constr = (char *) kmalloc(span + linklength + 1); if (span) memcpy(constr, base, span); if (need_explicit_slash) constr[span - 1] = '/'; if (linklength) memcpy(constr + span, link, linklength); constr[span + linklength] = '\0'; } else /* *link == `/' */ { /* LINK is an absolute path: we need to replace everything after (and including) the FIRST slash with LINK. So, if BASE is "http://host/whatever/foo/bar", and LINK is "/qux/xyzzy", our result should be "http://host/qux/xyzzy". */ int span; const char *slash; const char *start_insert = NULL; /* for gcc to shut up. */ const char *pos = base; int seen_slash_slash = 0; /* 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 = 1; 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; constr = (char *) kmalloc(span + linklength + 1); if (span) memcpy(constr, base, span); if (linklength) memcpy(constr + span, link, linklength); constr[span + linklength] = '\0'; } } else /* !no_proto */ { constr = strdupdelim(link, link + linklength); } return constr;}/* Merge BASE with LINK and return the resulting URI. This is an interface to uri_merge_1 that assumes that LINK is a zero-terminated string. */char *uri_merge(const char *base, const char *link){ return uri_merge_1(base, link, strlen(link), !has_proto(link));}/****************************************************************************** Perform a "deep" free of the urlinfo structure. The structure should have been created with newurl, but need not have been used. If free_pointer is non-0, free the pointer itself.******************************************************************************/void proz_free_url(urlinfo * u, boolean complete){ assert(u != NULL); if (u->url) kfree(u->url); if (u->host) kfree(u->host); if (u->path) kfree(u->path); if (u->file) kfree(u->file); if (u->dir) kfree(u->dir); if (u->user) kfree(u->user); if (u->passwd) kfree(u->passwd); if (u->referer) kfree(u->referer); if (complete) kfree(u);}urlinfo *proz_copy_url(urlinfo * u){ urlinfo *dest_url; dest_url = (urlinfo *) kmalloc(sizeof(urlinfo)); memset(dest_url, 0, sizeof(urlinfo)); if (u->url) dest_url->url = kstrdup(u->url); dest_url->proto = u->proto; dest_url->port = u->port; if (u->host) dest_url->host = kstrdup(u->host); if (u->path) dest_url->path = kstrdup(u->path); if (u->dir) dest_url->dir = kstrdup(u->dir); if (u->file) dest_url->file = kstrdup(u->file); if (u->user) dest_url->user = kstrdup(u->user); if (u->passwd) dest_url->passwd = kstrdup(u->passwd); if (u->referer) dest_url->referer = kstrdup(u->referer); return dest_url;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -