diff options
author | portix <portix@gmx.net> | 2014-02-25 12:25:12 +0100 |
---|---|---|
committer | portix <portix@gmx.net> | 2014-02-25 12:25:12 +0100 |
commit | 40ecd77dc6b63a6e2ebb5505dac93aa505b2e864 (patch) | |
tree | a5e4aefbb8aa2b3447272971c0e5733987f6f18f | |
parent | 18c3d8eb49cba7b1d25d79092134393a23053537 (diff) | |
download | dwb-40ecd77dc6b63a6e2ebb5505dac93aa505b2e864.zip |
dwbem: install archive files
-rw-r--r-- | dwbem/Makefile | 2 | ||||
-rw-r--r-- | dwbem/dwbem.c | 54 | ||||
-rw-r--r-- | exar/Makefile | 4 | ||||
-rw-r--r-- | exar/exar.c | 191 | ||||
-rw-r--r-- | exar/exar.h | 41 | ||||
-rw-r--r-- | exar/main.c | 10 |
6 files changed, 249 insertions, 53 deletions
diff --git a/dwbem/Makefile b/dwbem/Makefile index ef0b5860..d67a767f 100644 --- a/dwbem/Makefile +++ b/dwbem/Makefile @@ -15,7 +15,7 @@ SYSTEM_EXTENSION_DIR=$(PREFIX)/share/dwb/extensions CFLAGS := $(CFLAGS) CFLAGS += -std=c99 -CFLAGS += -Wall -g +CFLAGS += -Wall -g -O0 CFLAGS += -Wextra -Werror=format-security CFLAGS += $(shell pkg-config --cflags $(LIBS)) CFLAGS += -DSYSTEM_EXTENSION_DIR=\"$(SYSTEM_EXTENSION_DIR)\" diff --git a/dwbem/dwbem.c b/dwbem/dwbem.c index 374240ca..08a887c4 100644 --- a/dwbem/dwbem.c +++ b/dwbem/dwbem.c @@ -47,8 +47,10 @@ #include <exar.h> -#define API_BASE "https://api.bitbucket.org/1.0/repositories/portix/dwb_extensions/src/tip/src/?format=yaml" -#define REPO_BASE "https://bitbucket.org/portix/dwb_extensions" +//#define API_BASE "https://api.bitbucket.org/1.0/repositories/portix/dwb_extensions/src/tip/src/?format=yaml" +#define API_BASE "https://api.bitbucket.org/1.0/repositories/portix/dwbemtest/src/tip/src/?format=yaml" +//#define REPO_BASE "https://bitbucket.org/portix/dwb_extensions" +#define REPO_BASE "https://bitbucket.org/portix/dwbemtest" #define REPO_TREE "/raw/tip/src" #define SKIP(line, c) do{ \ @@ -252,11 +254,17 @@ get_data(const char *name, const char *data, const char *template, int flags) format = "(?<=^|\n)//<%s%s|//>%s%s\\s*(?=\n|$)"; regex = g_strdup_printf(format, nname, template, nname, template); - if (flags & F_MATCH_CONTENT) + if (flags & F_MATCH_CONTENT) { new_data = data; + } else { - g_file_get_contents(data, &content, NULL, NULL); + if (exar_check_version(data) == 0) { + content = (char*)exar_search_extract(data, "main.js", NULL); + } + else { + g_file_get_contents(data, &content, NULL, NULL); + } new_data = content; } if (new_data != NULL) @@ -690,6 +698,7 @@ install_extension(const char *name, int flags) char buffer[512]; char meta[128]; char *content = NULL; + const char *tmp = NULL; if (grep(m_meta_data, name, meta, sizeof(meta)) == -1) die(1, "extension %s not found", name); @@ -698,7 +707,16 @@ install_extension(const char *name, int flags) if (g_file_test(buffer, G_FILE_TEST_EXISTS)) { notify("Using %s", buffer); - if (g_file_get_contents(buffer, &content, NULL, NULL) ) + if (exar_check_version(buffer) == 0) { + content = (char*) exar_search_extract(buffer, "main.js", NULL); + if (add_to_loader(name, content, flags) == 0) + { + update_installed(name, meta); + ret = 0; + } + g_free(content); + } + else if (g_file_get_contents(buffer, &content, NULL, NULL) ) { if (add_to_loader(name, content, flags) == 0) { @@ -722,11 +740,21 @@ install_extension(const char *name, int flags) snprintf(buffer, sizeof(buffer), "%s/%s", m_user_dir, name); if (set_content(buffer, msg->response_body->data, msg->response_body->length)) { - if (add_to_loader(name, msg->response_body->data, flags) == 0) + if (exar_check_version(buffer) == 0) { + content = (char *)exar_search_extract(buffer, "main.js", NULL); + tmp = content; + } + else { + tmp = msg->response_body->data; + } + if (add_to_loader(name, tmp, flags) == 0) { update_installed(name, meta); ret = 0; } + if (content != NULL) { + g_free(content); + } } else print_error("Saving %s failed", name); @@ -1109,8 +1137,18 @@ cl_info(const char *name, int flags) path = g_strconcat(REPO_BASE REPO_TREE, "/", name, NULL); msg = soup_message_new("GET", path); int status = soup_session_send_message(session, msg); - if (status == 200) - data = get_data(NULL, msg->response_body->data, "INFO", F_MATCH_MULTILINE | F_MATCH_CONTENT); + if (status == 200) { + if (exar_check_version_from_data(msg->response_body->data, msg->response_body->length) == 0) { + char *mainfile = (char *)exar_search_extract_from_data((unsigned char *)msg->response_body->data, "main.js", NULL); + if (mainfile != NULL) { + data = get_data(NULL, mainfile, "INFO", F_MATCH_MULTILINE | F_MATCH_CONTENT); + g_free(mainfile); + } + } + else { + data = get_data(NULL, msg->response_body->data, "INFO", F_MATCH_MULTILINE | F_MATCH_CONTENT); + } + } unwind: if (data != NULL) { diff --git a/exar/Makefile b/exar/Makefile index f6717ef4..4f8e99da 100644 --- a/exar/Makefile +++ b/exar/Makefile @@ -1,6 +1,6 @@ ORIG_CFLAGS := $(CFLAGS) -CFLAGS := -Wall -pedantic -Werror -Wextra -std=c99 -Os +CFLAGS := -Wall -pedantic -Werror -Wextra -std=c99 -O0 -g CFLAGS += $(ORIG_CFLAGS) DCFLAGS += -g -O0 -Wall -pedantic -Werror -Wextra -std=c99 @@ -25,7 +25,7 @@ debug: make CFLAGS="$(DCFLAGS)" cgdb: - make CFLAGS="$(DCFLAGS)" + make CFLAGS="$(DCFLAGS)" exar cgdb exar clean: diff --git a/exar/exar.c b/exar/exar.c index 298c0631..725d35dd 100644 --- a/exar/exar.c +++ b/exar/exar.c @@ -112,23 +112,13 @@ get_offset(char *buffer, size_t n, const char *path, int *end) return offset; } static int -check_version(FILE *f, int verbose) -{ - unsigned char version[SZ_VERSION] = {0}; +version_cmp(const unsigned char *data, int verbose) { unsigned char orig_version[SZ_VERSION] = {0}; - LOG(2, "Reading version header\n"); - if (fread(version, 1, SZ_VERSION, f) != SZ_VERSION) - { - if (feof(f)) - return EE_EOF; - else - { - if (verbose) - fprintf(stderr, "Not an exar file?\n"); - return EE_ERROR; - } - } + unsigned char version[SZ_VERSION] = {0}; + + memcpy(version, data, sizeof(version)); memcpy(orig_version, EXAR_VERSION, sizeof(orig_version)); + LOG(2, "Checking filetype\n"); if (strncmp((char*)version, EXAR_VERSION_BASE, 5)) { @@ -137,7 +127,7 @@ check_version(FILE *f, int verbose) return EE_ERROR; } - LOG(2, "Found version %s\n", version); + LOG(2, "Found version %s\n", data); if (memcmp(version, orig_version, SZ_VERSION)) { if (verbose) @@ -146,6 +136,24 @@ check_version(FILE *f, int verbose) } return EE_OK; } +static int +check_version(FILE *f, int verbose) +{ + unsigned char version[SZ_VERSION] = {0}; + LOG(2, "Reading version header\n"); + if (fread(version, 1, SZ_VERSION, f) != SZ_VERSION) + { + if (feof(f)) + return EE_EOF; + else + { + if (verbose) + fprintf(stderr, "Not an exar file?\n"); + return EE_ERROR; + } + } + return version_cmp(version, verbose); +} /* * Opens archive and checks version, mode is either read or read-write * */ @@ -172,11 +180,35 @@ close_file(FILE *f, const char *archive) } static int +check_header(struct exar_header_s *head, const char *size) { + char *endptr; + off_t fs; + if (head->eh_flag != DIR_FLAG && head->eh_flag != FILE_FLAG) + { + LOG(1, "No file flag found\n"); + fprintf(stderr, "The archive seems to be corrupted\n"); + return EE_ERROR; + } + if (head->eh_flag == FILE_FLAG) + { + fs = strtol(size, &endptr, 16); + if (*endptr) + { + LOG(1, "Cannot determine file size\n"); + fprintf(stderr, "The archive seems to be corrupted\n"); + return EE_ERROR; + } + head->eh_size = fs; + } + else + head->eh_size = 0; + return EE_OK; +} + +static int get_file_header(FILE *f, struct exar_header_s *head) { - char *endptr; char header[HDR_NAME]; - off_t fs; char rb; size_t i = 0; int st_version = 0; @@ -193,25 +225,9 @@ get_file_header(FILE *f, struct exar_header_s *head) head->eh_flag = header[HDR_DFLAG]; - if (head->eh_flag != DIR_FLAG && head->eh_flag != FILE_FLAG) - { - LOG(1, "No file flag found\n"); - fprintf(stderr, "The archive seems to be corrupted\n"); + if (check_header(head, &header[HDR_SIZE]) == EE_ERROR) { return EE_ERROR; } - if (head->eh_flag == FILE_FLAG) - { - fs = strtol(&header[HDR_SIZE], &endptr, 16); - if (*endptr) - { - LOG(1, "Cannot determine file size\n"); - fprintf(stderr, "The archive seems to be corrupted\n"); - return EE_ERROR; - } - head->eh_size = fs; - } - else - head->eh_size = 0; while (fread(&rb, 1, 1, f) > 0) { @@ -230,6 +246,47 @@ get_file_header(FILE *f, struct exar_header_s *head) return EE_OK; } static int +get_file_header_from_data(const unsigned char *data, int *offset, struct exar_header_s *head) +{ + char size[SZ_SIZE]; + size_t i = 0; + int st_version = 0; + const unsigned char *tmp = data;; + + *offset = 0; + + if ((st_version = version_cmp(tmp, 0)) != EE_OK) + return st_version; + tmp += SZ_VERSION; + + LOG(2, "Reading file header\n"); + memcpy(&(head->eh_flag), tmp, SZ_DFLAG); + tmp += SZ_DFLAG; + memcpy(size, tmp, SZ_SIZE); + tmp += SZ_SIZE; + + if (check_header(head, size) == EE_ERROR) { + return EE_ERROR; + } + *offset = SZ_VERSION + SZ_DFLAG + SZ_SIZE; + while (*tmp != '\0') + { + head->eh_name[i] = *tmp; + i++; + tmp++; + if (i == EXAR_NAME_MAX) + { + fprintf(stderr, "Cannot get filename\n"); + return EE_ERROR; + } + } + // terminating null byte + *offset += i+1; + + LOG(2, "Found file header (%s, %c, %jd)\n", head->eh_name, head->eh_flag, (intmax_t)head->eh_size); + return EE_OK; +} +static int next_file(FILE *f, struct exar_header_s *header) { if (*(header->eh_name)) @@ -247,7 +304,7 @@ next_file(FILE *f, struct exar_header_s *header) static int find_cmp(const char *name, const char *search) { - char buffer[EXAR_NAME_MAX]; + char buffer[EXAR_NAME_MAX] = {0}; if (strcmp(name, search) != 0) { size_t offset = get_offset(buffer, EXAR_NAME_MAX, name, NULL); @@ -284,7 +341,7 @@ extract(const char *archive, const char *file, off_t *s, int (*cmp)(const char * FILE *f = NULL; unsigned char *ret = NULL; if (s != NULL) - *s = 0; + *s = -1; if ((f = open_archive(archive, "r")) == NULL) goto finish; @@ -299,15 +356,15 @@ extract(const char *archive, const char *file, off_t *s, int (*cmp)(const char * if (fread(ret, 1, header.eh_size, f) != (size_t)header.eh_size) { fprintf(stderr, "Failed to read %s\n", header.eh_name); - *s = -1; free(ret); ret = NULL; } else if (s != NULL) *s = header.eh_size; } - else + else { fprintf(stderr, "%s is a directory, only regular files can be extracted\n", file); + } goto finish; } else if (header.eh_flag == FILE_FLAG) @@ -321,6 +378,37 @@ finish: close_file(f, archive); return ret; } +static unsigned char * +extract_from_data(const unsigned char *data, const char *file, off_t *s, int (*cmp)(const char *, const char *)) { + (void) data, (void) s, (void) cmp, (void) file; + unsigned char *ret = NULL; + struct exar_header_s header = EXAR_HEADER_EMPTY; + int offset = 0; + + if (s != NULL) + *s = -1; + + while((get_file_header_from_data(data, &offset, &header) == EE_OK)) { + data += offset; + if (cmp(header.eh_name, file) == 0) { + if (header.eh_flag == FILE_FLAG) { + ret = xcalloc(header.eh_size, sizeof(unsigned char)); + memcpy(ret, data, header.eh_size); + if (s != NULL) { + *s = header.eh_size; + } + return ret; + } + else { + fprintf(stderr, "%s is a directory, only regular files can be extracted\n", file); + return NULL; + } + } + data += header.eh_size; + } + fprintf(stderr, "File %s was not found.\n", file); + return NULL; +} static int write_file_header(FILE *f, const char *name, char flag, off_t r) @@ -569,6 +657,20 @@ exar_search_extract(const char *archive, const char *file, off_t *s) return extract(archive, file, s, find_cmp); } +unsigned char * +exar_extract_from_data(const unsigned char *data, const char *file, off_t *s) +{ + assert(data != NULL); + + return extract_from_data(data, file, s, strcmp); +} +unsigned char * +exar_search_extract_from_data(const unsigned char *data, const char *file, off_t *s) +{ + assert(data != NULL); + + return extract_from_data(data, file, s, find_cmp); +} int exar_delete(const char *archive, const char *file) { @@ -696,8 +798,17 @@ exar_check_version(const char *archive) close_file(f, archive); return result; } +int +exar_check_version_from_data(const unsigned char *data, size_t s) +{ + assert(data != NULL); + + if (s < SZ_VERSION) + return EE_ERROR; + return version_cmp(data, 0) == EE_OK ? EE_OK : EE_ERROR; +} void -exar_verbose(unsigned char v) +exar_verbose(const unsigned char v) { s_verbose = v & EXAR_VERBOSE_MASK; } diff --git a/exar/exar.h b/exar/exar.h index 5bae266c..34ee5490 100644 --- a/exar/exar.h +++ b/exar/exar.h @@ -102,6 +102,34 @@ exar_extract(const char *archive, const char *file, off_t *size); unsigned char * exar_search_extract(const char *archive, const char *search, off_t *size); +/* + * Searches for a file and extracts the content from raw archive data. + * + * @data The data + * @file The path of the file in the archive + * @size Return location for the size, if an error occurs size will be set to -1 + * + * @returns A newly allocated char buffer with the file content or NULL if an error + * occured or the file was not found in the archive + * */ +unsigned char * +exar_extract_from_data(const unsigned char *data, const char *file, off_t *size); + +/* + * Searches for a file and extracts the content from raw archive data + * + * @data The data + * @search The search term. The search term must either match the full path or + * the filename + * @size Return location for the size, if an error occurs size will be set to -1 + * + * @returns A newly allocated char buffer with the file content or NULL if an error + * occured or the file was not found in the archive + * */ + +unsigned char * +exar_search_extract_from_data(const unsigned char *data, const char *file, off_t *size); + /* * Deletes a file from the archive, if it is a directory it is removed * recursively. @@ -118,7 +146,6 @@ exar_delete(const char *archive, const char *file); * Checks if the file is an archive file with compatible version number * * @archive The archive - * @verbose Whether to print error messages to stderr * * @returns 0 on success and -1 on error */ @@ -126,6 +153,16 @@ int exar_check_version(const char *archive); /* + * Checks if the given data is an archive file with compatible version number + * + * @data The archive + * + * @returns 0 on success and -1 on error + */ +int +exar_check_version_from_data(const unsigned char *data, size_t s); + +/* * Print info about the archive to stdout. * * @archive The archive @@ -161,5 +198,5 @@ exar_search_contains(const char *archive, const char *search); * @v_flags */ void -exar_verbose(unsigned char v_flags); +exar_verbose(const unsigned char v_flags); #endif diff --git a/exar/main.c b/exar/main.c index 0255f397..48217039 100644 --- a/exar/main.c +++ b/exar/main.c @@ -91,6 +91,16 @@ int main (int argc, char **argv) { int flag = 0; + char buffer[4096] = {0}; + FILE *f = fopen(argv[1], "r"); + exar_verbose(EXAR_VERBOSE_MASK); + fread(buffer, 1, 4096, f); + puts(buffer); + char *data = (char*)exar_extract_from_data((unsigned char *)buffer, "foo/main.js", NULL); + puts(data); + //printf("%d %lu\n", exar_check_version_from_data(buffer), strlen(buffer)); + fclose(f); + return 0; if (argc < 3) { help(EXIT_FAILURE); |