📄 htparse.c
字号:
} } }#endif /* CLEAN_URLS */ } } /* * Trim any blanks from the result so far - there's no excuse for blanks * in a hostname. Also update the tail here. */ tail = LYRemoveBlanks(result); /* ** If host in given or related was ended directly with a '?' (no ** slash), fake the search part into absolute. This is the only ** case search is returned from scan. A host must have been present. ** this restores the '?' at which the host part had been truncated in ** scan, we have to do this after host part handling is done. - kw */ if (given.search && *(given.search - 1) == '\0') { given.absolute = given.search - 1; given.absolute[0] = '?'; } else if (related.search && !related.absolute && *(related.search - 1) == '\0') { related.absolute = related.search - 1; related.absolute[0] = '?'; } /* ** If different hosts, inherit no path. */ if (given.host && related.host) if (strcmp(given.host, related.host) != 0) { related.absolute = NULL; related.relative = NULL; related.anchor = NULL; } /* ** Handle the path. */ if (wanted & (PARSE_PATH | PARSE_STRICTPATH | PARSE_QUERY)) { int want_detail = (wanted & (PARSE_STRICTPATH | PARSE_QUERY)); if (acc_method && !given.absolute && given.relative) { /* * Treat all given nntp or snews paths, or given paths for news * URLs with a host, as absolute. */ switch (*acc_method) { case 'N': case 'n': if (!strcasecomp(acc_method, "nntp") || (!strcasecomp(acc_method, "news") && !strncasecomp(result, "news://", 7))) { given.absolute = given.relative; given.relative = NULL; } break; case 'S': case 's': if (!strcasecomp(acc_method, "snews")) { given.absolute = given.relative; given.relative = NULL; } break; } } if (given.absolute) { /* All is given */ if (wanted & PARSE_PUNCTUATION) *tail++ = '/'; strcpy(tail, given.absolute); CTRACE((tfp, "HTParse: (ABS)\n")); } else if (related.absolute) { /* Adopt path not name */ *tail++ = '/'; strcpy(tail, related.absolute); if (given.relative) { p = strchr(tail, '?'); /* Search part? */ if (p == NULL) p = (tail + strlen(tail) - 1); for (; *p != '/'; p--) ; /* last / */ p[1] = '\0'; /* Remove filename */ strcat(p, given.relative); /* Add given one */ HTSimplify (result); } CTRACE((tfp, "HTParse: (Related-ABS)\n")); } else if (given.relative) { strcpy(tail, given.relative); /* what we've got */ CTRACE((tfp, "HTParse: (REL)\n")); } else if (related.relative) { strcpy(tail, related.relative); CTRACE((tfp, "HTParse: (Related-REL)\n")); } else { /* No inheritance */ if (!isLYNXCGI(aName) && !isLYNXEXEC(aName) && !isLYNXPROG(aName)) { *tail++ = '/'; *tail = '\0'; } if (!strcmp(result, "news:/")) result[5] = '*'; CTRACE((tfp, "HTParse: (No inheritance)\n")); } if (want_detail) { p = strchr(tail, '?'); /* Search part? */ if (p) { if (PARSE_STRICTPATH) { *p = '\0'; } else { if (!(wanted & PARSE_PUNCTUATION)) p++; do { *tail++ = *p; } while (*p++); } } else { if (wanted & PARSE_QUERY) *tail = '\0'; } } } /* ** Handle the fragment (anchor). Never inherit. */ if (wanted & PARSE_ANCHOR) { if (given.anchor && *given.anchor) { tail += strlen(tail); if (wanted & PARSE_PUNCTUATION) *tail++ = '#'; strcpy(tail, given.anchor); } } /* * If there are any blanks remaining in the string, escape them as needed. * See the discussion in LYLegitimizeHREF() for example. */ if ((p = strchr(result, ' ')) != 0) { switch (is_url(result)) { case UNKNOWN_URL_TYPE: CTRACE((tfp, "HTParse: ignore:`%s'\n", result)); break; case LYNXEXEC_URL_TYPE: case LYNXPROG_URL_TYPE: case LYNXCGI_URL_TYPE: case LYNXPRINT_URL_TYPE: case LYNXHIST_URL_TYPE: case LYNXDOWNLOAD_URL_TYPE: case LYNXKEYMAP_URL_TYPE: case LYNXIMGMAP_URL_TYPE: case LYNXCOOKIE_URL_TYPE: case LYNXDIRED_URL_TYPE: case LYNXOPTIONS_URL_TYPE: case LYNXCFG_URL_TYPE: case LYNXCOMPILE_OPTS_URL_TYPE: case LYNXMESSAGES_URL_TYPE: CTRACE((tfp, "HTParse: spaces:`%s'\n", result)); break; case NOT_A_URL_TYPE: default: CTRACE((tfp, "HTParse: encode:`%s'\n", result)); do { char *q = p + strlen(p) + 2; while (q != p + 1) { q[0] = q[-2]; --q; } p[0] = '%'; p[1] = '2'; p[2] = '0'; } while ((p = strchr(result, ' ')) != 0); break; } } CTRACE((tfp, "HTParse: result:`%s'\n", result)); StrAllocCopy(return_value, result); LYalloca_free(result); /* FIXME: could be optimized using HTParse() internals */ if (*relatedName && ((wanted & PARSE_ALL_WITHOUT_ANCHOR) == PARSE_ALL_WITHOUT_ANCHOR)) { /* * Check whether to fill in localhost. - FM */ LYFillLocalFileURL(&return_value, relatedName); CTRACE((tfp, "pass LYFillLocalFile:`%s'\n", return_value)); } return return_value; /* exactly the right length */}/* HTParseAnchor(), fast HTParse() specialization** ----------------------------------------------**** On exit,** returns A pointer within input string (probably to its end '\0')*/PUBLIC CONST char * HTParseAnchor ARGS1( CONST char *, aName){ CONST char* p = aName; for ( ; *p && *p != '#'; p++) ; if (*p == '#') { /* the safe way based on HTParse() - * keeping in mind scan() peculiarities on schemes: */ struct struct_parts given; char* name = (char*)LYalloca((p - aName) + strlen(p) + 1); if (name == NULL) { outofmem(__FILE__, "HTParseAnchor"); } strcpy(name, aName); scan(name, &given); LYalloca_free(name); p++; /*next to '#'*/ if (given.anchor == NULL) { for ( ; *p; p++) /*scroll to end '\0'*/ ; } } return p;}/* Simplify a filename. HTSimplify()** --------------------**** A unix-style file is allowed to contain the sequence xxx/../ which may** be replaced by "" , and the sequence "/./" which may be replaced by "/".** Simplification helps us recognize duplicate filenames.**** Thus, /etc/junk/../fred becomes /etc/fred** /etc/junk/./fred becomes /etc/junk/fred**** but we should NOT change** http://fred.xxx.edu/../..**** or ../../albert.html*/PUBLIC void HTSimplify ARGS1( char *, filename){ char *p; char *q, *q1; if (filename == NULL) return; if (!(filename[0] && filename[1]) || filename[0] == '?' || filename[1] == '?' || filename[2] == '?') return; if (strchr(filename, '/') != NULL) { for (p = (filename + 2); *p; p++) { if (*p == '?') { /* ** We're still treating a ?searchpart as part of ** the path in HTParse() and scan(), but if we ** encounter a '?' here, assume it's the delimiter ** and break. We also could check for a parameter ** delimiter (';') here, but the current Fielding ** draft (wisely or ill-advisedly :) says that it ** should be ignored and collapsing be allowed in ** it's value). The only defined parameter at ** present is ;type=[A, I, or D] for ftp URLs, so ** if there's a "/..", "/../", "/./", or terminal ** '.' following the ';', it must be due to the ** ';' being an unescaped path character and not ** actually a parameter delimiter. - FM */ break; } if (*p == '/') { if ((p[1] == '.') && (p[2] == '.') && (p[3] == '/' || p[3] == '?' || p[3] == '\0')) { /* ** Handle "../", "..?" or "..". */ for (q = (p - 1); (q >= filename) && (*q != '/'); q--) /* ** Back up to previous slash or beginning of string. */ ; if ((q[0] == '/') && (strncmp(q, "/../", 4) && strncmp(q, "/..?", 4)) && !((q - 1) > filename && q[-1] == '/')) { /* ** Not at beginning of string or in a ** host field, so remove the "/xxx/..". */ q1 = (p + 3); p = q; while (*q1 != '\0') *p++ = *q1++; *p = '\0'; /* terminate */ /* ** Start again with previous slash. */ p = (q - 1); } } else if (p[1] == '.' && p[2] == '/') { /* ** Handle "./" by removing both characters. */ q = p; q1 = (p + 2); while (*q1 != '\0') *q++ = *q1++; *q = '\0'; /* terminate */ p--; } else if (p[1] == '.' && p[2] == '?') { /* ** Handle ".?" by removing the dot. */ q = (p + 1); q1 = (p + 2); while (*q1 != '\0') *q++ = *q1++; *q = '\0'; /* terminate */ p--; } else if (p[1] == '.' && p[2] == '\0') { /* ** Handle terminal "." by removing the character. */ p[1] = '\0'; } } } if (p >= filename + 2 && *p == '?' && *(p-1) == '.') { if (*(p-2) == '/') { /* ** Handle "/.?" by removing the dot. */ q = p - 1; q1 = p; while (*q1 != '\0') *q++ = *q1++; *q = '\0'; } else if (*(p-2) == '.' && p >= filename + 4 && *(p-3) == '/' && (*(p-4) != '/' || (p > filename + 4 && *(p-5) != ':'))) { /* ** Handle "xxx/..?" */ for (q = (p - 4); (q > filename) && (*q != '/'); q--) /* ** Back up to previous slash or beginning of string. */ ; if (*q == '/') { if (q > filename && *(q-1) == '/' && !(q > filename + 1 && *(q-1) != ':')) return; q++; } if (strncmp(q, "../", 3) && strncmp(q, "./", 2)) { /* ** Not after "//" at beginning of string or ** after "://", and xxx is not ".." or ".", ** so remove the "xxx/..". */ q1 = p; p = q; while (*q1 != '\0') *p++ = *q1++; *p = '\0'; /* terminate */ } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -