static unsigned char * strip_proxy_protocol(unsigned char *proxy, unsigned char *strip1, unsigned char *strip2) { assert(proxy && *proxy); if (!c_strncasecmp((const char *)proxy, (const char *)strip1, strlen((const char *)strip1))) proxy += strlen((const char *)strip1); else if (strip2 && !c_strncasecmp((const char *)proxy, (const char *)strip2, strlen((const char *)strip2))) proxy += strlen((const char *)strip2); return proxy; }
void html_object(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5) { unsigned char *type, *url; /* This is just some dirty wrapper. We emulate various things through * this, which is anyway in the spirit of <object> element, unifying * <img> and <iframe> etc. */ url = get_url_val(a, (unsigned char *)"data", html_context->doc_cp); if (!url) url = get_url_val(a, (unsigned char *)"codebase", html_context->doc_cp); if (!url) return; type = get_attr_val(a, (unsigned char *)"type", html_context->doc_cp); if (!type) { mem_free(url); return; } if (!c_strncasecmp((const char *)type, "text/", 5)) { /* We will just emulate <iframe>. */ html_iframe_do(a, url, html_context); html_skip(html_context, a); } else if (!c_strncasecmp((const char *)type, "image/", 6)) { /* <img> emulation. */ /* TODO: Use the enclosed text as 'alt' attribute. */ html_img_do(a, url, html_context); } else { unsigned char *name; name = get_attr_val(a, (unsigned char *)"standby", html_context->doc_cp); html_focusable(html_context, a); if (name && *name) { put_link_line((unsigned char *)"Object: ", name, url, html_context->options->framename, html_context); } else { put_link_line((unsigned char *)"Object: ", type, url, html_context->options->framename, html_context); } mem_free_if(name); } mem_free(type); mem_free(url); }
void html_embed(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5) { unsigned char *type, *extension; unsigned char *object_src; /* This is just some dirty wrapper. We emulate various things through * this, which is anyway in the spirit of <object> element, unifying * <img> and <iframe> etc. */ object_src = get_url_val(a, (unsigned char *)"src", html_context->doc_cp); if (!object_src || !*object_src) { mem_free_set(&object_src, NULL); return; } /* If there is no extension we want to get the default mime/type * anyway? */ extension = (unsigned char *)strrchr((char *)object_src, '.'); if (!extension) extension = object_src; type = get_extension_content_type(extension); if (type && !c_strncasecmp((const char *)type, "image/", 6)) { html_img_do(a, object_src, html_context); } else { /* We will just emulate <iframe>. */ html_iframe_do(a, object_src, html_context); } mem_free_if(type); mem_free_set(&object_src, NULL); }
int end_with_known_tld(const unsigned char *s, int slen) { int i; static const unsigned char *const tld[] = { "com", "edu", "net", "org", "gov", "mil", "int", "biz", "arpa", "aero", "coop", "club", "info", "museum", "expert", "name", "pro", NULL }; if (!slen) return -1; if (slen < 0) slen = strlen(s); for (i = 0; tld[i]; i++) { int tldlen = strlen(tld[i]); int pos = slen - tldlen; if (pos >= 0 && !c_strncasecmp(&s[pos], tld[i], tldlen)) return pos; } return -1; }
/* Returns true if ENCODING, which must be in one of the forms described at the top of encoding-guesser.h, is one that performs encoding autodetection, false otherwise. */ bool encoding_guess_encoding_is_auto (const char *encoding) { return (encoding == NULL || (!c_strncasecmp (encoding, "auto", 4) && (encoding[4] == ',' || encoding[4] == '\0'))); }
bool csync_is_windows_reserved_word(const char* filename) { size_t win_reserve_words_len = sizeof(win_reserved_words) / sizeof(char*); size_t j; for (j = 0; j < win_reserve_words_len; j++) { int len_reserved_word = strlen(win_reserved_words[j]); int len_filename = strlen(filename); if (len_filename == 2 && filename[1] == ':') { if (filename[0] >= 'a' && filename[0] <= 'z') { return true; } if (filename[0] >= 'A' && filename[0] <= 'Z') { return true; } } if (c_strncasecmp(filename, win_reserved_words[j], len_reserved_word) == 0) { if (len_filename == len_reserved_word) { return true; } if ((len_filename > len_reserved_word) && (filename[len_reserved_word] == '.')) { return true; } } } return false; }
unsigned check_cmd_help(const char *line) { unsigned int i; unsigned len = (line!=NULL)?strlen(line):0; unsigned status = 0, tlen; while (len > 0 && (line[len - 1] == '?' || whitespace(line[len - 1]))) len--; for (i = 0;; i++) { if (commands[i].name == NULL) break; tlen = len; if (tlen > commands[i].name_size) { tlen = commands[i].name_size; } if (c_strncasecmp(commands[i].name, line, tlen) == 0) { status = 1; if (commands[i].arg) printf(" %12s %s\t%16s\n", commands[i].name, commands[i].arg, commands[i].doc); else printf(" %16s\t%16s\n", commands[i].name, commands[i].doc); } } return status; }
int is_in_domain(unsigned char *domain, unsigned char *server, int server_len) { int domain_len = strlen(domain); int len; if (domain_len > server_len) return 0; if (domain_len == server_len) return !c_strncasecmp(domain, server, server_len); len = server_len - domain_len; if (server[len - 1] != '.') return 0; return !c_strncasecmp(domain, server + len, domain_len); }
/* Returns the encoding specified by ENCODING, which must be in one of the forms described at the top of encoding-guesser.h. The returned string might be ENCODING itself or a suffix of it, or it might be a statically allocated string. */ const char * encoding_guess_parse_encoding (const char *encoding) { if (encoding == NULL || !c_strcasecmp (encoding, "auto") || !c_strcasecmp (encoding, "auto,locale") || !c_strcasecmp (encoding, "locale")) return locale_charset (); else if (!c_strncasecmp (encoding, "auto,", 5)) return encoding + 5; else return encoding; }
char* search_for_ip(unsigned idx, const char* match, int match_size) { unsigned i; if (idx >= ip_entries_size) return NULL; for (i=idx;i<ip_entries_size;i++) { if (match_size <= ip_entries[i].ip_size) { if (c_strncasecmp(match, ip_entries[i].ip, match_size) == 0) return strdup(ip_entries[i].ip); } } return NULL; }
void html_script(struct html_context *html_context, unsigned char *a, unsigned char *html, unsigned char *eof, unsigned char **end) { #ifdef CONFIG_ECMASCRIPT /* TODO: <noscript> processing. Well, same considerations apply as to * CSS property display: none processing. */ /* TODO: Charsets for external scripts. */ unsigned char *type, *language, *src; int in_comment = 0; #endif html_skip(html_context, a); #ifdef CONFIG_ECMASCRIPT /* We try to process nested <script> if we didn't process the parent * one. That's why's all the fuzz. */ /* Ref: * http://www.ietf.org/internet-drafts/draft-hoehrmann-script-types-03.txt */ type = get_attr_val(a, (unsigned char *)"type", html_context->doc_cp); if (type) { unsigned char *pos = type; if (!c_strncasecmp((const char *)type, "text/", 5)) { pos += 5; } else if (!c_strncasecmp((const char *)type, "application/", 12)) { pos += 12; } else { mem_free(type); not_processed: /* Permit nested scripts and retreat. */ html_top->invisible++; return; } if (!c_strncasecmp((const char *)pos, "javascript", 10)) { int len = strlen((const char *)pos); if (len > 10 && !isdigit(pos[10])) { mem_free(type); goto not_processed; } } else if (c_strcasecmp((const char *)pos, "ecmascript") && c_strcasecmp((const char *)pos, "jscript") && c_strcasecmp((const char *)pos, "livescript") && c_strcasecmp((const char *)pos, "x-javascript") && c_strcasecmp((const char *)pos, "x-ecmascript")) { mem_free(type); goto not_processed; } mem_free(type); } /* Check that the script content is ecmascript. The value of the * language attribute can be JavaScript with optional version digits * postfixed (like: ``JavaScript1.1''). * That attribute is deprecated in favor of type by HTML 4.01 */ language = get_attr_val(a, (unsigned char *)"language", html_context->doc_cp); if (language) { int languagelen = strlen((const char *)language); if (languagelen < 10 || (languagelen > 10 && !isdigit(language[10])) || c_strncasecmp((const char *)language, "javascript", 10)) { mem_free(language); html_top->invisible++; return; //goto not_processed; } mem_free(language); } if (html_context->part->document && (src = get_attr_val(a, (unsigned char *)"src", html_context->doc_cp))) { /* External reference. */ unsigned char *import_url; struct uri *uri; if (!get_opt_bool((const unsigned char *)"ecmascript.enable", NULL)) { mem_free(src); html_top->invisible++; return; //goto not_processed; } /* HTML <head> urls should already be fine but we can.t detect them. */ import_url = join_urls(html_context->base_href, src); mem_free(src); if (!import_url) goto imported; uri = get_uri(import_url, URI_BASE); if (!uri) goto imported; /* Request the imported script as part of the document ... */ html_context->special_f(html_context, SP_SCRIPT, uri); done_uri(uri); /* Create URL reference onload snippet. */ insert_in_string(&import_url, 0, (const unsigned char *)"^", 1); add_to_string_list(&html_context->part->document->onload_snippets, import_url, -1); imported: /* Retreat. Do not permit nested scripts, tho'. */ if (import_url) mem_free(import_url); return; } /* Positive, grab the rest and interpret it. */ /* First position to the real script start. */ while (html < eof && *html <= ' ') html++; if (eof - html > 4 && !strncmp((const char *)html, "<!--", 4)) { in_comment = 1; /* We either skip to the end of line or to -->. */ for (; *html != '\n' && *html != '\r' && eof - html >= 3; html++) { if (!strncmp((const char *)html, "-->", 3)) { /* This means the document is probably broken. * We will now try to process the rest of * <script> contents, which is however likely * to be empty. Should we try to process the * comment too? Currently it seems safer but * less tolerant to broken pages, if there are * any like this. */ html += 3; in_comment = 0; break; } } } *end = html; /* Now look ahead for the script end. The <script> contents is raw * CDATA, so we just look for the ending tag and need not care for * any quote marks counting etc - YET, we are more tolerant and permit * </script> stuff inside of the script if the whole <script> element * contents is wrapped in a comment. See i.e. Mozilla bug 26857 for fun * reading regarding this. */ for (; *end < eof; (*end)++) { unsigned char *name; int namelen; if (in_comment) { /* TODO: If we ever get some standards-quirk mode * distinction, this should be disabled in the * standards mode (and we should just look for CDATA * end, which is "</"). --pasky */ if (eof - *end >= 3 && !strncmp((const char *)*end, "-->", 3)) { /* Next iteration will jump passed the ending '>' */ (*end) += 2; in_comment = 0; } continue; /* XXX: Scan for another comment? That's admittelly * already stretching things a little bit to an * extreme ;-). */ } if (**end != '<') continue; /* We want to land before the closing element, that's why we * don't pass @end also as the appropriate parse_element() * argument. */ if (parse_element(*end, eof, &name, &namelen, NULL, NULL)) continue; if (c_strlcasecmp(name, namelen, (const unsigned char *)"/script", 7)) continue; /* We have won! */ break; } if (*end >= eof) { /* Either the document is not completely loaded yet or it's * broken. At any rate, run away screaming. */ *end = eof; /* Just for sanity. */ return; } if (html_context->part->document && *html != '^') { add_to_string_list(&html_context->part->document->onload_snippets, html, *end - html); } #endif }
static inline void scan_css_token(struct scanner *scanner, struct scanner_token *token) { const unsigned char *string = scanner->position; unsigned char first_char = *string; enum css_token_type type = CSS_TOKEN_GARBAGE; int real_length = -1; assert(first_char); token->string = string++; if (is_css_char_token(first_char)) { type = first_char; } else if (is_css_digit(first_char) || first_char == '.') { scan_css(scanner, string, CSS_CHAR_DIGIT); /* First scan the full number token */ if (*string == '.') { string++; if (is_css_digit(*string)) { type = CSS_TOKEN_NUMBER; scan_css(scanner, string, CSS_CHAR_DIGIT); } } /* Check what kind of number we have */ if (*string == '%') { if (first_char != '.') type = CSS_TOKEN_PERCENTAGE; string++; } else if (!is_css_ident_start(*string)) { type = CSS_TOKEN_NUMBER; } else { const unsigned char *ident = string; scan_css(scanner, string, CSS_CHAR_IDENT); type = map_scanner_string(scanner, ident, string, CSS_TOKEN_DIMENSION); } } else if (is_css_ident_start(first_char)) { scan_css(scanner, string, CSS_CHAR_IDENT); if (*string == '(') { const unsigned char *function_end = string + 1; /* Make sure that we have an ending ')' */ skip_css(scanner, function_end, ')'); if (*function_end == ')') { type = map_scanner_string(scanner, token->string, string, CSS_TOKEN_FUNCTION); /* If it is not a known function just skip the * how arg stuff so we don't end up generating * a lot of useless tokens. */ if (type == CSS_TOKEN_FUNCTION) { string = function_end; } else if (type == CSS_TOKEN_URL) { /* Extracting the URL first removes any * leading or ending whitespace and * then see if the url is given in a * string. If that is the case the * string delimiters are also trimmed. * This is not totally correct because * we should of course handle escape * sequences .. but that will have to * be fixed later. */ const unsigned char *from = string + 1; const unsigned char *to = function_end - 1; scan_css(scanner, from, CSS_CHAR_WHITESPACE); scan_back_css(scanner, to, CSS_CHAR_WHITESPACE); if (isquote(*from)) from++; if (isquote(*to)) to--; token->string = from; /* Given "url( )", @to and @from will * cross when they scan forwards and * backwards, respectively, for a non- * whitespace character, and @to - @from * will be negative. If there is * anything between the parentheses, * @to and @from will not cross and @to * - @from will not become negative. */ real_length = int_max(0, to - from + 1); string = function_end; } assert(type != CSS_TOKEN_RGB || *string == '('); assert(type != CSS_TOKEN_URL || *string == ')'); assert(type != CSS_TOKEN_FUNCTION || *string == ')'); } string++; } else { type = CSS_TOKEN_IDENT; } } else if (!is_css_token_start(first_char)) { /* TODO: Better composing of error tokens. For now we just * split them down into char tokens */ } else if (first_char == '#') { /* Check whether it is hexcolor or hash token */ if (is_css_hexdigit(*string)) { int hexdigits; scan_css(scanner, string, CSS_CHAR_HEX_DIGIT); /* Check that the hexdigit sequence is either 3 or 6 * chars and it isn't just start of some non-hex ident * string. */ hexdigits = string - token->string - 1; if ((hexdigits == 3 || hexdigits == 6) && !is_css_ident(*string)) { type = CSS_TOKEN_HEX_COLOR; } else { scan_css(scanner, string, CSS_CHAR_IDENT); type = CSS_TOKEN_HASH; } } else if (is_css_ident(*string)) { /* Not *_ident_start() because hashes are #<name>. */ scan_css(scanner, string, CSS_CHAR_IDENT); type = CSS_TOKEN_HASH; } } else if (first_char == '@') { /* Compose token containing @<ident> */ if (is_css_ident_start(*string)) { const unsigned char *ident = string; /* Scan both ident start and ident */ scan_css(scanner, string, CSS_CHAR_IDENT); type = map_scanner_string(scanner, ident, string, CSS_TOKEN_AT_KEYWORD); } } else if (first_char == '*') { if (*string == '=') { type = CSS_TOKEN_SELECT_CONTAINS; string++; } else { type = CSS_TOKEN_IDENT; } } else if (first_char == '^') { if (*string == '=') { type = CSS_TOKEN_SELECT_BEGIN; string++; } } else if (first_char == '$') { if (*string == '=') { type = CSS_TOKEN_SELECT_END; string++; } } else if (first_char == '|') { if (*string == '=') { type = CSS_TOKEN_SELECT_HYPHEN_LIST; string++; } } else if (first_char == '!') { scan_css(scanner, string, CSS_CHAR_WHITESPACE); if (!c_strncasecmp(string, "important", 9)) { type = CSS_TOKEN_IMPORTANT; string += 9; } } else if (isquote(first_char)) { /* TODO: Escaped delimiters --jonas */ int size = scanner->end - string; unsigned char *string_end = memchr(string, first_char, size); if (string_end) { /* We don't want the delimiters in the token */ token->string++; real_length = string_end - token->string; string = string_end + 1; type = CSS_TOKEN_STRING; } } else if (first_char == '<' || first_char == '-') { /* Try to navigate SGML tagsoup */ if (*string == '/') { /* Some kind of SGML tag end ... better bail out screaming */ type = CSS_TOKEN_NONE; } else { const unsigned char *sgml = string; /* Skip anything looking like SGML "<!--" and "-->" * comments + <![CDATA[ and ]]> notations. */ scan_css(scanner, sgml, CSS_CHAR_SGML_MARKUP); if (sgml - string >= 2 && ((first_char == '<' && *string == '!') || (first_char == '-' && sgml[-1] == '>'))) { type = CSS_TOKEN_SKIP; string = sgml; } } } else if (first_char == '/') { /* Comments */ if (*string == '*') { type = CSS_TOKEN_SKIP; for (string++; string < scanner->end; string++) if (*string == '*' && string[1] == '/') { string += 2; break; } } } else { INTERNAL("Someone forgot to put code for recognizing tokens " "which start with '%c'.", first_char); } token->type = type; token->length = real_length > 0 ? real_length : string - token->string; token->precedence = get_css_precedence(type); scanner->position = string; }
static char *command_generator(const char *text, int state) { static int list_index, len; static int entries_idx; unsigned name_size; char *name, *arg; char *ret; /* If this is a new word to complete, initialize now. This includes saving the length of TEXT for efficiency, and initializing the index variable to 0. */ if (!state) { list_index = 0; entries_idx = 0; len = strlen(text); } /* Return the next name which partially matches from the command list. */ while ((name = commands[list_index].name)) { name_size = commands[list_index].name_size; arg = commands[list_index].arg; list_index++; if (cmd_start > name_size) { /* check for user or ID options */ if (rl_line_buffer != NULL && c_strncasecmp(rl_line_buffer, name, name_size) == 0 && /* make sure only one argument is appended */ rl_line_buffer[name_size] != 0 && strchr(&rl_line_buffer[name_size + 1], ' ') == NULL) { if (arg != NULL) { ret = NULL; if (strcmp(arg, "[NAME]") == 0) ret = search_for_user(entries_idx, text, len); else if (strcmp(arg, "[ID]") == 0) ret = search_for_id(entries_idx, text, len); else if (strcmp(arg, "[IP]") == 0) ret = search_for_ip(entries_idx, text, len); if (ret != NULL) { entries_idx++; } list_index--; /* restart at the same cmd */ return ret; } } continue; } if (cmd_start > 0 && name[cmd_start - 1] != ' ') continue; if (rl_line_buffer != NULL && c_strncasecmp(rl_line_buffer, name, cmd_start) != 0) continue; name += cmd_start; if (c_strncasecmp(name, text, len) == 0) { return (strdup(name)); } } return NULL; }
/* checks whether an input command of type " list users" maches * the given cmd (e.g., "list users"). If yes it executes func() and returns true. */ static unsigned check_cmd(const char *cmd, const char *input, CONN_TYPE * conn, int need_preconn, cmd_func func, int *status, cmd_params_st *params) { char *t, *p; unsigned len, tlen; unsigned i, j, ret = 0; char prev; while (whitespace(*input)) input++; len = strlen(input); t = talloc_size(conn, len + 1); if (t == NULL) return 0; prev = 0; p = t; for (i = j = 0; i < len; i++) { if (!whitespace(prev) || !whitespace(input[i])) { *p = input[i]; prev = input[i]; p++; } } *p = 0; tlen = p - t; len = strlen(cmd); if (len == 0) goto cleanup; if (tlen >= len && c_strncasecmp(cmd, t, len) == 0 && cmd[len] == 0) { /* match */ p = t + len; while (whitespace(*p)) p++; if (need_preconn != 0) { if (conn_prehandle(conn) < 0) { *status = 1; } else { *status = func(conn, p, params); } } else { *status = func(conn, p, params); } ret = 1; if (need_preconn != 0) conn_posthandle(conn); } cleanup: talloc_free(t); return ret; }
/* ToUnicode(). May realloc() utf8in. Will free utf8in unconditionally. */ static int idna_to_unicode_internal (char *utf8in, uint32_t * out, size_t * outlen, int flags) { int rc; char tmpout[64]; size_t utf8len = strlen (utf8in) + 1; size_t addlen = 0; /* * ToUnicode consists of the following steps: * * 1. If the sequence contains any code points outside the ASCII range * (0..7F) then proceed to step 2, otherwise skip to step 3. */ { size_t i; int inasciirange; inasciirange = 1; for (i = 0; utf8in[i]; i++) if (utf8in[i] & ~0x7F) inasciirange = 0; if (inasciirange) goto step3; } /* * 2. Perform the steps specified in [NAMEPREP] and fail if there is an * error. (If step 3 of ToASCII is also performed here, it will not * affect the overall behavior of ToUnicode, but it is not * necessary.) The AllowUnassigned flag is used in [NAMEPREP]. */ do { char *newp = realloc (utf8in, utf8len + addlen); if (newp == NULL) { free (utf8in); return IDNA_MALLOC_ERROR; } utf8in = newp; if (flags & IDNA_ALLOW_UNASSIGNED) rc = stringprep_nameprep (utf8in, utf8len + addlen); else rc = stringprep_nameprep_no_unassigned (utf8in, utf8len + addlen); addlen += 1; } while (rc == STRINGPREP_TOO_SMALL_BUFFER); if (rc != STRINGPREP_OK) { free (utf8in); return IDNA_STRINGPREP_ERROR; } /* 3. Verify that the sequence begins with the ACE prefix, and save a * copy of the sequence. * ... The ToASCII and ToUnicode operations MUST recognize the ACE prefix in a case-insensitive manner. */ step3: if (c_strncasecmp (utf8in, IDNA_ACE_PREFIX, strlen (IDNA_ACE_PREFIX)) != 0) { free (utf8in); return IDNA_NO_ACE_PREFIX; } /* 4. Remove the ACE prefix. */ memmove (utf8in, &utf8in[strlen (IDNA_ACE_PREFIX)], strlen (utf8in) - strlen (IDNA_ACE_PREFIX) + 1); /* 5. Decode the sequence using the decoding algorithm in [PUNYCODE] * and fail if there is an error. Save a copy of the result of * this step. */ (*outlen)--; /* reserve one for the zero */ rc = punycode_decode (strlen (utf8in), utf8in, outlen, out, NULL); if (rc != PUNYCODE_SUCCESS) { free (utf8in); return IDNA_PUNYCODE_ERROR; } out[*outlen] = 0; /* add zero */ /* 6. Apply ToASCII. */ rc = idna_to_ascii_4i (out, *outlen, tmpout, flags); if (rc != IDNA_SUCCESS) { free (utf8in); return rc; } /* 7. Verify that the result of step 6 matches the saved copy from * step 3, using a case-insensitive ASCII comparison. */ if (c_strcasecmp (utf8in, tmpout + strlen (IDNA_ACE_PREFIX)) != 0) { free (utf8in); return IDNA_ROUNDTRIP_VERIFY_ERROR; } /* 8. Return the saved copy from step 5. */ free (utf8in); return IDNA_SUCCESS; }
int main (int argc, char *argv[]) { if (argc > 1) { /* configure should already have checked that the locale is supported. */ if (setlocale (LC_ALL, "") == NULL) return 1; } ASSERT (c_strncasecmp ("paragraph", "Paragraph", 1000000) == 0); ASSERT (c_strncasecmp ("paragraph", "Paragraph", 9) == 0); ASSERT (c_strncasecmp ("paragrapH", "parAgRaph", 1000000) == 0); ASSERT (c_strncasecmp ("paragrapH", "parAgRaph", 9) == 0); ASSERT (c_strncasecmp ("paragraph", "paraLyzed", 10) < 0); ASSERT (c_strncasecmp ("paragraph", "paraLyzed", 9) < 0); ASSERT (c_strncasecmp ("paragraph", "paraLyzed", 5) < 0); ASSERT (c_strncasecmp ("paragraph", "paraLyzed", 4) == 0); ASSERT (c_strncasecmp ("paraLyzed", "paragraph", 10) > 0); ASSERT (c_strncasecmp ("paraLyzed", "paragraph", 9) > 0); ASSERT (c_strncasecmp ("paraLyzed", "paragraph", 5) > 0); ASSERT (c_strncasecmp ("paraLyzed", "paragraph", 4) == 0); ASSERT (c_strncasecmp ("para", "paragraph", 10) < 0); ASSERT (c_strncasecmp ("para", "paragraph", 9) < 0); ASSERT (c_strncasecmp ("para", "paragraph", 5) < 0); ASSERT (c_strncasecmp ("para", "paragraph", 4) == 0); ASSERT (c_strncasecmp ("paragraph", "para", 10) > 0); ASSERT (c_strncasecmp ("paragraph", "para", 9) > 0); ASSERT (c_strncasecmp ("paragraph", "para", 5) > 0); ASSERT (c_strncasecmp ("paragraph", "para", 4) == 0); /* The following tests shows how c_strncasecmp() is different from strncasecmp(). */ ASSERT (c_strncasecmp ("\311mily", "\351mile", 4) < 0); ASSERT (c_strncasecmp ("\351mile", "\311mily", 4) > 0); /* The following tests shows how c_strncasecmp() is different from mbsncasecmp(). */ ASSERT (c_strncasecmp ("\303\266zg\303\274r", "\303\226ZG\303\234R", 99) > 0); /* özgür */ ASSERT (c_strncasecmp ("\303\226ZG\303\234R", "\303\266zg\303\274r", 99) < 0); /* özgür */ /* This test shows how strings of different size cannot compare equal. */ ASSERT (c_strncasecmp ("turkish", "TURK\304\260SH", 7) < 0); ASSERT (c_strncasecmp ("TURK\304\260SH", "turkish", 7) > 0); return 0; }
/* Extract the value of name part of the value of attribute content. * Ie. @name = "charset" and @str = "text/html; charset=iso-8859-1" * will store in *@ret an allocated string containing "iso-8859-1". * It supposes that separator is ';' and ignore first element in the * list. (ie. '1' is ignored in "1; URL=xxx") * The return value is one of: * * - HEADER_PARAM_FOUND: the parameter was found, copied, and stored in *@ret. * - HEADER_PARAM_NOT_FOUND: the parameter is not there. *@ret is now NULL. * - HEADER_PARAM_OUT_OF_MEMORY: error. *@ret is now NULL. * * If @ret is NULL, then this function doesn't actually access *@ret, * and cannot fail with HEADER_PARAM_OUT_OF_MEMORY. Some callers may * rely on this. */ enum parse_header_param parse_header_param(unsigned char *str, unsigned char *name, unsigned char **ret, int content_disposition) { unsigned char *p = str; int namelen, plen = 0; if (ret) *ret = NULL; /* default in case of early return */ assert(str && name && *name); if_assert_failed return HEADER_PARAM_NOT_FOUND; /* Returns now if string @str is empty. */ if (!*p) return HEADER_PARAM_NOT_FOUND; namelen = strlen(name); if (!content_disposition) { a: p = strchr((const char *)p, ';'); if (!p) return HEADER_PARAM_NOT_FOUND; } while (*p && (*p == ';' || *p <= ' ')) p++; if (strlen(p) < namelen) return HEADER_PARAM_NOT_FOUND; if (c_strncasecmp(p, name, namelen)) goto a; p += namelen; while (*p && (*p <= ' ' || *p == '=')) p++; if (!*p) { if (ret) { *ret = stracpy(""); if (!*ret) return HEADER_PARAM_OUT_OF_MEMORY; } return HEADER_PARAM_FOUND; } while ((p[plen] > ' ' || LWS(p[plen])) && p[plen] != ';') plen++; /* Trim ending spaces */ while (plen > 0 && LWS(p[plen - 1])) plen--; /* XXX: Drop enclosing single quotes if there's some. * * Some websites like newsnow.co.uk are using single quotes around url * in URL field in meta tag content attribute like this: * <meta http-equiv="Refresh" content="0; URL='http://www.site.com/path/xxx.htm'"> * * This is an attempt to handle that, but it may break something else. * We drop all pair of enclosing quotes found (eg. '''url''' => url). * Please report any issue related to this. --Zas */ while (plen > 1 && *p == '\'' && p[plen - 1] == '\'') { p++; plen -= 2; } if (ret) { *ret = memacpy(p, plen); if (!*ret) return HEADER_PARAM_OUT_OF_MEMORY; } return HEADER_PARAM_FOUND; }
enum uri_errno parse_uri(struct uri *uri, unsigned char *uristring) { unsigned char *prefix_end, *host_end; #ifdef CONFIG_IPV6 unsigned char *lbracket, *rbracket; #endif assertm(uristring != NULL, "No uri to parse."); memset(uri, 0, sizeof(*uri)); /* Nothing to do for an empty url. */ if_assert_failed return 0; if (!*uristring) return URI_ERRNO_EMPTY; uri->string = uristring; uri->protocollen = get_protocol_length(uristring); /* Invalid */ if (!uri->protocollen) return URI_ERRNO_INVALID_PROTOCOL; /* Figure out whether the protocol is known */ uri->protocol = get_protocol(struri(uri), uri->protocollen); prefix_end = uristring + uri->protocollen; /* ':' */ /* Check if there's a digit after the protocol name. */ if (isdigit(*prefix_end)) { uri->ip_family = uristring[uri->protocollen] - '0'; prefix_end++; } if (*prefix_end != ':') return URI_ERRNO_INVALID_PROTOCOL; prefix_end++; /* Skip slashes */ if (prefix_end[0] == '/' && prefix_end[1] == '/') { if (prefix_end[2] == '/' && get_protocol_need_slash_after_host(uri->protocol)) return URI_ERRNO_TOO_MANY_SLASHES; prefix_end += 2; } else if (get_protocol_need_slashes(uri->protocol)) { return URI_ERRNO_NO_SLASHES; } if (get_protocol_free_syntax(uri->protocol)) { uri->data = prefix_end; uri->datalen = strlen(prefix_end); return URI_ERRNO_OK; } else if (uri->protocol == PROTOCOL_FILE) { int datalen = strcspn(prefix_end, "#" POST_CHAR_S); unsigned char *frag_or_post = prefix_end + datalen; /* Extract the fragment part. */ if (datalen >= 0) { if (*frag_or_post == '#') { uri->fragment = frag_or_post + 1; uri->fragmentlen = strcspn(uri->fragment, POST_CHAR_S); frag_or_post = uri->fragment + uri->fragmentlen; } if (*frag_or_post == POST_CHAR) { uri->post = frag_or_post + 1; } } else { datalen = strlen(prefix_end); } /* A bit of a special case, but using the "normal" host * parsing seems a bit scary at this point. (see bug 107). */ if (datalen > 9 && !c_strncasecmp(prefix_end, "localhost/", 10)) { prefix_end += 9; datalen -= 9; } uri->data = prefix_end; uri->datalen = datalen; return URI_ERRNO_OK; } /* Isolate host */ #ifdef CONFIG_IPV6 /* Get brackets enclosing IPv6 address */ lbracket = strchr((const char *)prefix_end, '['); if (lbracket) { rbracket = strchr((const char *)lbracket, ']'); /* [address] is handled only inside of hostname part (surprisingly). */ if (rbracket && rbracket < prefix_end + strcspn(prefix_end, "/")) uri->ipv6 = 1; else lbracket = rbracket = NULL; } else { rbracket = NULL; } #endif /* Possibly skip auth part */ host_end = prefix_end + strcspn(prefix_end, "@"); if (prefix_end + strcspn(prefix_end, "/") > host_end && *host_end) { /* we have auth info here */ unsigned char *user_end; /* Allow '@' in the password component */ while (strcspn(host_end + 1, "@") < strcspn(host_end + 1, "/?")) host_end = host_end + 1 + strcspn(host_end + 1, "@"); user_end = strchr((const char *)prefix_end, ':'); if (!user_end || user_end > host_end) { uri->user = prefix_end; uri->userlen = host_end - prefix_end; } else { uri->user = prefix_end; uri->userlen = user_end - prefix_end; uri->password = user_end + 1; uri->passwordlen = host_end - user_end - 1; } prefix_end = host_end + 1; } #ifdef CONFIG_IPV6 if (uri->ipv6) host_end = rbracket + strcspn(rbracket, ":/?"); else #endif host_end = prefix_end + strcspn(prefix_end, ":/?"); #ifdef CONFIG_IPV6 if (uri->ipv6) { int addrlen = rbracket - lbracket - 1; /* Check for valid length. * addrlen >= sizeof(hostbuf) is theorically impossible * but i keep the test in case of... Safer, imho --Zas */ assertm(addrlen >= 0 && addrlen < NI_MAXHOST, "parse_uri(): addrlen value is bad (%d) for URL '%s'. " "Problems are likely to be encountered. Please report " "this, it is a security bug!", addrlen, uristring); if_assert_failed return URI_ERRNO_IPV6_SECURITY; uri->host = lbracket + 1; uri->hostlen = addrlen; } else