const char *mget_iri_get_escaped_file(const MGET_IRI *iri, mget_buffer_t *buf) { if (iri->path) { char *fname; if ((fname = strrchr(iri->path, '/'))) mget_iri_escape_path(fname + 1, buf); else mget_iri_escape_path(iri->path, buf); } if ((buf->length == 0 || buf->data[buf->length - 1] == '/') && default_page) mget_buffer_memcat(buf, default_page, default_page_length); if (iri->query) { mget_buffer_memcat(buf, "?", 1); mget_iri_escape_query(iri->query, buf); } // if (iri->fragment) { // buffer_memcat(buf, "#", 1); // iri_escape(iri->fragment, buf); // } return buf->data; }
char *mget_iri_get_path(const mget_iri_t *iri, mget_buffer_t *buf, const char *encoding) { if (buf->length) mget_buffer_memcat(buf, "/", 1); if (iri->path) { if (mget_strcasecmp_ascii(encoding, "utf-8")) { char *fname; if ((fname = mget_utf8_to_str(iri->path, encoding))) { mget_buffer_strcat(buf, fname); xfree(fname); } else { // conversion failed, keep original string mget_buffer_strcat(buf, iri->path); } } else { mget_buffer_strcat(buf, iri->path); } } if ((buf->length == 0 || buf->data[buf->length - 1] == '/') && default_page) mget_buffer_memcat(buf, default_page, default_page_length); return buf->data; }
const char *mget_iri_get_escaped_path(const MGET_IRI *iri, mget_buffer_t *buf) { if (buf->length) mget_buffer_memcat(buf, "/", 1); if (iri->path) mget_iri_escape_path(iri->path, buf); if ((buf->length == 0 || buf->data[buf->length - 1] == '/') && default_page) mget_buffer_memcat(buf, default_page, default_page_length); return buf->data; }
char *mget_iri_get_query_as_filename(const mget_iri_t *iri, mget_buffer_t *buf, const char *encoding) { if (iri->query) { const char *query; int allocated = 0; mget_buffer_memcat(buf, "?", 1); if (mget_strcasecmp_ascii(encoding, "utf-8")) { if ((query = mget_utf8_to_str(iri->query, encoding))) allocated = 1; } else { query = iri->query; } if (query) { int slashes = 0; const char *src = query; // count slashes in query string while ((src = strchr(src, '/'))) { slashes++; src++; } if (slashes) { // escape slashes to use query as part of a filename const char *begin; for (src = begin = query; *src; src++) { if (*src == '/') { if (begin != src) mget_buffer_memcat(buf, begin, src - begin); begin = src + 1; mget_buffer_memcat(buf, "%2F", 3); } } if (begin != src) mget_buffer_memcat(buf, begin, src - begin); } else { mget_buffer_strcat(buf, query); } } if (allocated) xfree(query); } return buf->data; }
char *mget_iri_get_filename(const mget_iri_t *iri, mget_buffer_t *buf, const char *encoding) { if (iri->path) { char *fname, *p; if (mget_strcasecmp_ascii(encoding, "utf-8")) { if ((p = strrchr(iri->path, '/'))) { if (!(fname = mget_utf8_to_str(p + 1, encoding))) mget_buffer_strcat(buf, p + 1); // conversion failed, keep original string } else { if (!(fname = mget_utf8_to_str(iri->path, encoding))) mget_buffer_strcat(buf, iri->path); // conversion failed, keep original string } if (fname) { // conversion succeeded mget_buffer_strcat(buf, fname); xfree(fname); } } else { if ((fname = strrchr(iri->path, '/'))) mget_buffer_strcat(buf, fname + 1); else mget_buffer_strcat(buf, iri->path); } } if ((buf->length == 0 || buf->data[buf->length - 1] == '/') && default_page) mget_buffer_memcat(buf, default_page, default_page_length); return mget_iri_get_query_as_filename(iri, buf, encoding); }
char *mget_iri_get_filename(const mget_iri_t *iri, mget_buffer_t *buf, const char *encoding) { if (iri->path) { char *fname; if (mget_strcasecmp_ascii(encoding, "utf-8")) { if ((fname = strrchr(iri->path, '/'))) fname = mget_utf8_to_str(fname + 1, encoding); else fname = mget_utf8_to_str(iri->path, encoding); if (fname) { mget_buffer_strcat(buf, fname); xfree(fname); } } else { if ((fname = strrchr(iri->path, '/'))) mget_buffer_strcat(buf, fname + 1); else mget_buffer_strcat(buf, iri->path); } } if ((buf->length == 0 || buf->data[buf->length - 1] == '/') && default_page) mget_buffer_memcat(buf, default_page, default_page_length); return mget_iri_get_query_as_filename(iri, buf, encoding); }
const char *mget_iri_get_escaped_resource(const mget_iri_t *iri, mget_buffer_t *buf) { if (iri->path) mget_iri_escape_path(iri->path, buf); if (iri->query) { mget_buffer_memcat(buf, "?", 1); mget_iri_escape_query(iri->query, buf); } if (iri->fragment) { mget_buffer_memcat(buf, "#", 1); mget_iri_escape(iri->fragment, buf); } return buf->data; }
const char *mget_iri_escape_path(const char *src, mget_buffer_t *buf) { const char *begin; for (begin = src; *src; src++) { if (!mget_iri_isunreserved_path(*src)) { if (begin != src) mget_buffer_memcat(buf, begin, src - begin); begin = src + 1; mget_buffer_printf_append2(buf, "%%%02X", (unsigned char)*src); } } if (begin != src) mget_buffer_memcat(buf, begin, src - begin); return buf->data; }
char *mget_read_file(const char *fname, size_t *size) { int fd; ssize_t nread; char *buf = NULL; if (!fname) return NULL; if (strcmp(fname,"-")) { if ((fd = open(fname, O_RDONLY)) != -1) { struct stat st; if (fstat(fd, &st) == 0) { off_t total = 0; buf = xmalloc(st.st_size + 1); while (total < st.st_size && (nread = read(fd, buf + total, st.st_size - total)) > 0) { total += nread; } buf[total] = 0; if (size) *size = total; if (total != st.st_size) error_printf(_("WARNING: Size of %s changed from %lld to %lld while reading. This may lead to unwanted results !\n"), fname, (long long)st.st_size, (long long)total); } else error_printf(_("Failed to fstat %s\n"), fname); close(fd); } else error_printf(_("Failed to open %s\n"), fname); } else { // read data from STDIN. char tmp[4096]; mget_buffer_t buffer; mget_buffer_init(&buffer, NULL, 4096); while ((nread = read(STDIN_FILENO, tmp, sizeof(tmp))) > 0) { mget_buffer_memcat(&buffer, tmp, nread); } if (size) *size = buffer.length; buf = buffer.data; buffer.data = NULL; mget_buffer_deinit(&buffer); } return buf; }
const char *mget_iri_get_escaped_fragment(const MGET_IRI *iri, mget_buffer_t *buf) { if (iri->fragment) { mget_buffer_memcat(buf, "#", 1); return mget_iri_escape(iri->fragment, buf); } return buf->data; }
const char *mget_iri_get_escaped_query(const MGET_IRI *iri, mget_buffer_t *buf) { if (iri->query) { mget_buffer_memcat(buf, "?", 1); return mget_iri_escape_query(iri->query, buf); } return buf->data; }
const char *mget_iri_escape_query(const char *src, mget_buffer_t *buf) { const char *begin; for (begin = src; *src; src++) { if (!mget_iri_isunreserved(*src) && *src != '=') { if (begin != src) mget_buffer_memcat(buf, begin, src - begin); begin = src + 1; if (*src == ' ') mget_buffer_memcat(buf, "+", 1); else mget_buffer_printf_append2(buf, "%%%02X", (unsigned char)*src); } } if (begin != src) mget_buffer_memcat(buf, begin, src - begin); return buf->data; }
void mget_css_parse_file( const char *fname, void(*callback_uri)(void *user_ctx, const char *url, size_t len, size_t pos), void(*callback_encoding)(void *user_ctx, const char *url, size_t len), void *user_ctx) { int fd; if (strcmp(fname,"-")) { if ((fd = open(fname, O_RDONLY)) != -1) { struct stat st; if (fstat(fd, &st) == 0) { #ifdef HAVE_MMAP size_t nread = st.st_size; char *buf = mmap(NULL, nread + 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); #else char *buf=xmalloc(st.st_size+1); size_t nread=read(fd,buf,st.st_size); #endif if (nread > 0) { buf[nread] = 0; // PROT_WRITE allows this write, MAP_PRIVATE prevents changes in underlying file system mget_css_parse_buffer(buf, callback_uri, callback_encoding, user_ctx); } #ifdef HAVE_MMAP munmap(buf, nread); #else xfree(buf); #endif } close(fd); } else error_printf(_("Failed to open %s\n"), fname); } else { // read data from STDIN. // maybe should use yy_scan_bytes instead of buffering into memory. char tmp[4096]; ssize_t nbytes; mget_buffer_t *buf = mget_buffer_alloc(4096); while ((nbytes = read(STDIN_FILENO, tmp, sizeof(tmp))) > 0) { mget_buffer_memcat(buf, tmp, nbytes); } if (buf->length) mget_css_parse_buffer(buf->data, callback_uri, callback_encoding, user_ctx); mget_buffer_free(&buf); } }
static void _test_buffer(mget_buffer_t *buf, const char *name) { char test[256]; int it; for (it = 0; it < (int)sizeof(test)-1; it++) { test[it] = 'a' + it % 26; test[it + 1] = 0; mget_buffer_strcpy(buf, test); mget_buffer_strcat(buf, test); if (!strncmp(buf->data, test, it + 1) && !strncmp(buf->data + it + 1, test, it + 1)) { ok++; } else { failed++; info_printf("test_buffer.1 '%s': [%d] got %s (expected %s%s)\n", name, it, buf->data, test, test); } mget_buffer_memcpy(buf, test, it + 1); mget_buffer_memcat(buf, test, it + 1); if (!strncmp(buf->data, test, it + 1) && !strncmp(buf->data + it + 1, test, it + 1)) { ok++; } else { failed++; info_printf("test_buffer.2 '%s': [%d] got %s (expected %s%s)\n", name, it, buf->data, test, test); } mget_buffer_printf(buf, "%s%s", test, test); if (!strncmp(buf->data, test, it + 1) && !strncmp(buf->data + it + 1, test, it + 1)) { ok++; } else { failed++; info_printf("test_buffer.3 '%s': [%d] got %s (expected %s%s)\n", name, it, buf->data, test, test); } mget_buffer_printf(buf, "%s", test); mget_buffer_printf_append(buf, "%s", test); if (!strncmp(buf->data, test, it + 1) && !strncmp(buf->data + it + 1, test, it + 1)) { ok++; } else { failed++; info_printf("test_buffer.4 '%s': [%d] got %s (expected %s%s)\n", name, it, buf->data, test, test); } } }
size_t mget_buffer_bufcat(mget_buffer_t *buf, mget_buffer_t *src) { return mget_buffer_memcat(buf, src->data, src->length); }
size_t mget_buffer_memcpy(mget_buffer_t *buf, const void *data, size_t length) { buf->length = 0; return mget_buffer_memcat(buf, data, length); }
static void test_buffer(void) { char sbuf[16]; mget_buffer_t buf, *bufp; // testing buffer on stack, using initial stack memory // without resizing mget_buffer_init(&buf, sbuf, sizeof(sbuf)); mget_buffer_deinit(&buf); // testing buffer on stack, using initial stack memory // with resizing mget_buffer_init(&buf, sbuf, sizeof(sbuf)); _test_buffer(&buf, "Test 1"); mget_buffer_deinit(&buf); // testing buffer on stack, using initial heap memory // without resizing mget_buffer_init(&buf, NULL, 16); mget_buffer_deinit(&buf); // testing buffer on stack, using initial heap memory // with resizing mget_buffer_init(&buf, NULL, 16); _test_buffer(&buf, "Test 2"); mget_buffer_deinit(&buf); // testing buffer on heap, using initial stack memory // without resizing bufp = mget_buffer_init(NULL, sbuf, sizeof(sbuf)); mget_buffer_deinit(bufp); bufp = mget_buffer_init(NULL, sbuf, sizeof(sbuf)); mget_buffer_free(&bufp); // testing buffer on heap, using initial stack memory // with resizing bufp = mget_buffer_init(NULL, sbuf, sizeof(sbuf)); _test_buffer(bufp, "Test 3"); mget_buffer_deinit(bufp); bufp = mget_buffer_init(NULL, sbuf, sizeof(sbuf)); _test_buffer(bufp, "Test 4"); mget_buffer_free(&bufp); // testing buffer on heap, using initial heap memory // without resizing bufp = mget_buffer_alloc(16); mget_buffer_free(&bufp); // testing buffer on heap, using initial heap memory // with resizing bufp = mget_buffer_alloc(16); _test_buffer(bufp, "Test 5"); mget_buffer_free(&bufp); // check that appending works mget_buffer_init(&buf, sbuf, sizeof(sbuf)); mget_buffer_strcpy(&buf, "A"); mget_buffer_strcat(&buf, "B"); mget_buffer_memcat(&buf, "C", 1); mget_buffer_memset_append(&buf, 'D', 1); mget_buffer_printf_append2(&buf, "%s", "E"); if (!strcmp(buf.data, "ABCDE")) ok++; else { failed++; info_printf("test_buffer.append: got %s (expected %s)\n", buf.data, "ABCDE"); } mget_buffer_deinit(&buf); // test mget_buffer_trim() mget_buffer_init(&buf, sbuf, sizeof(sbuf)); for (int mid_ws = 0; mid_ws <= 2; mid_ws++) { char expected[16]; snprintf(expected, sizeof(expected), "x%.*sy", mid_ws, " "); for (int lead_ws = 0; lead_ws <= 2; lead_ws++) { for (int trail_ws = 0; trail_ws <= 2; trail_ws++) { mget_buffer_printf2(&buf, "%.*sx%.*sy%.*s", lead_ws, " ", mid_ws, " ", trail_ws, " "); mget_buffer_trim(&buf); if (!strcmp(buf.data, expected)) ok++; else { failed++; info_printf("test_buffer_trim: got '%s' (expected '%s') (%d, %d, %d)\n", buf.data, expected, lead_ws, mid_ws, trail_ws); } } } } mget_buffer_deinit(&buf); }
//char *iri_relative_to_absolute(IRI *iri, const char *tag, const char *val, size_t len, char *dst, size_t dst_size) const char *mget_iri_relative_to_abs(mget_iri_t *base, const char *val, size_t len, mget_buffer_t *buf) { debug_printf("*url = %.*s\n", (int)len, val); if (*val == '/') { if (base) { char path[len + 1]; strlcpy(path, val, len + 1); if (len >= 2 && val[1] == '/') { char *p; // absolute URI without scheme: //authority/path... if ((p = strchr(path + 2, '/'))) _normalize_path(p + 1); mget_buffer_strcpy(buf, base->scheme); mget_buffer_strcat(buf, ":"); mget_buffer_strcat(buf, path); debug_printf("*1 %s\n", buf->data); } else { // absolute path _normalize_path(path); mget_buffer_strcpy(buf, mget_iri_get_connection_part(base)); mget_buffer_strcat(buf, "/"); mget_buffer_strcat(buf, path); debug_printf("*2 %s\n", buf->data); } } else return NULL; } else { // see if URI begins with a scheme: if (memchr(val, ':', len)) { // absolute URI if (buf) { mget_buffer_memcpy(buf, val, len); debug_printf("*3 %s\n", buf->data); } else { debug_printf("*3 %s\n", val); return val; } } else if (base) { // relative path const char *lastsep = base->path ? strrchr(base->path, '/') : NULL; mget_buffer_strcpy(buf, mget_iri_get_connection_part(base)); mget_buffer_strcat(buf, "/"); size_t tmp_len = buf->length; if (lastsep) mget_buffer_memcat(buf, base->path, lastsep - base->path + 1); if (len) mget_buffer_memcat(buf, val, len); buf->length = _normalize_path(buf->data + tmp_len) + tmp_len; debug_printf("*4 %s %zu\n", buf->data, buf->length); } else if (val[len] == 0) { return val; } else return NULL; } return buf->data; }