237 |
return result; |
return result; |
238 |
} |
} |
239 |
|
|
240 |
|
static unsigned int hex_value(char c) { |
241 |
|
if ('0' <= c && c <= '9') { |
242 |
|
return c - '0'; |
243 |
|
} |
244 |
|
else if ('A' <= c && c <= 'F') { |
245 |
|
return c - 'A'; |
246 |
|
} |
247 |
|
else if ('a' <= c && c <= 'f') { |
248 |
|
return c - 'a'; |
249 |
|
} |
250 |
|
else { |
251 |
|
return 0; |
252 |
|
} |
253 |
|
} |
254 |
|
|
255 |
|
static char * decode_uri_component(const char * s) { |
256 |
|
size_t length = strlen(s); |
257 |
|
char * result = xmalloc(length + 1); |
258 |
|
char * p = result; |
259 |
|
while (*s != '\0') { |
260 |
|
if (*s == '%') { |
261 |
|
if (s[1] == '\0' || s[2] == '\0') { |
262 |
|
*p = '\0'; |
263 |
|
return result; |
264 |
|
} |
265 |
|
*p = hex_value(s[1]) * 16 + hex_value(s[2]); |
266 |
|
s += 2; |
267 |
|
} |
268 |
|
else { |
269 |
|
*p = *s; |
270 |
|
} |
271 |
|
p++; |
272 |
|
s++; |
273 |
|
} |
274 |
|
*p = '\0'; |
275 |
|
return result; |
276 |
|
} |
277 |
|
|
278 |
static const char * get_entity(char c) { |
static const char * get_entity(char c) { |
279 |
switch(c) { |
switch(c) { |
280 |
case '<': |
case '<': |
614 |
} |
} |
615 |
|
|
616 |
mkdir_if_necessary(report_directory); |
mkdir_if_necessary(report_directory); |
617 |
char * path = make_path(report_directory, "jscoverage.json"); |
char * current_report_directory; |
618 |
|
if (str_starts_with(abs_path, "/jscoverage-store/") && abs_path[18] != '\0') { |
619 |
|
char * dir = decode_uri_component(abs_path + 18); |
620 |
|
current_report_directory = make_path(report_directory, dir); |
621 |
|
free(dir); |
622 |
|
} |
623 |
|
else { |
624 |
|
current_report_directory = xstrdup(report_directory); |
625 |
|
} |
626 |
|
mkdir_if_necessary(current_report_directory); |
627 |
|
char * path = make_path(current_report_directory, "jscoverage.json"); |
628 |
|
|
629 |
/* check if the JSON file exists */ |
/* check if the JSON file exists */ |
630 |
struct stat buf; |
struct stat buf; |
641 |
} |
} |
642 |
} |
} |
643 |
if (result != 0) { |
if (result != 0) { |
644 |
|
free(current_report_directory); |
645 |
free(path); |
free(path); |
646 |
Coverage_delete(coverage); |
Coverage_delete(coverage); |
647 |
send_response(exchange, 500, "Could not merge with existing coverage data\n"); |
send_response(exchange, 500, "Could not merge with existing coverage data\n"); |
653 |
free(path); |
free(path); |
654 |
Coverage_delete(coverage); |
Coverage_delete(coverage); |
655 |
if (result != 0) { |
if (result != 0) { |
656 |
|
free(current_report_directory); |
657 |
send_response(exchange, 500, "Could not write coverage data\n"); |
send_response(exchange, 500, "Could not write coverage data\n"); |
658 |
return; |
return; |
659 |
} |
} |
660 |
|
|
661 |
/* copy other files */ |
/* copy other files */ |
662 |
jscoverage_copy_resources(report_directory); |
jscoverage_copy_resources(current_report_directory); |
663 |
path = make_path(report_directory, "jscoverage.js"); |
path = make_path(current_report_directory, "jscoverage.js"); |
664 |
|
free(current_report_directory); |
665 |
FILE * f = fopen(path, "ab"); |
FILE * f = fopen(path, "ab"); |
666 |
free(path); |
free(path); |
667 |
if (f == NULL) { |
if (f == NULL) { |
719 |
} |
} |
720 |
|
|
721 |
static void instrument_js(const char * id, const uint16_t * characters, size_t num_characters, Stream * output_stream) { |
static void instrument_js(const char * id, const uint16_t * characters, size_t num_characters, Stream * output_stream) { |
722 |
|
const struct Resource * resource = get_resource("report.js"); |
723 |
|
Stream_write(output_stream, resource->data, resource->length); |
724 |
|
|
725 |
LOCK(&javascript_mutex); |
LOCK(&javascript_mutex); |
726 |
jscoverage_instrument_js(id, characters, num_characters, output_stream); |
jscoverage_instrument_js(id, characters, num_characters, output_stream); |
727 |
UNLOCK(&javascript_mutex); |
UNLOCK(&javascript_mutex); |
|
|
|
|
const struct Resource * resource = get_resource("report.js"); |
|
|
Stream_write(output_stream, resource->data, resource->length); |
|
728 |
} |
} |
729 |
|
|
730 |
static bool is_hop_by_hop_header(const char * h) { |
static bool is_hop_by_hop_header(const char * h) { |