| 45 | } |
| 46 | |
| 47 | static char *url_decode_internal(const char **query, int len, |
| 48 | const char *stop_at, struct strbuf *out, |
| 49 | int decode_plus) |
| 50 | { |
| 51 | const char *q = *query; |
| 52 | |
| 53 | while (len) { |
| 54 | unsigned char c = *q; |
| 55 | |
| 56 | if (!c) |
| 57 | break; |
| 58 | if (stop_at && strchr(stop_at, c)) { |
| 59 | q++; |
| 60 | len--; |
| 61 | break; |
| 62 | } |
| 63 | |
| 64 | if (c == '%' && (len < 0 || len >= 3)) { |
| 65 | int val = hex2chr(q + 1); |
| 66 | if (0 < val) { |
| 67 | strbuf_addch(out, val); |
| 68 | q += 3; |
| 69 | len -= 3; |
| 70 | continue; |
| 71 | } |
| 72 | } |
| 73 | |
| 74 | if (decode_plus && c == '+') |
| 75 | strbuf_addch(out, ' '); |
| 76 | else |
| 77 | strbuf_addch(out, c); |
| 78 | q++; |
| 79 | len--; |
| 80 | } |
| 81 | *query = q; |
| 82 | return strbuf_detach(out, NULL); |
| 83 | } |
| 84 | |
| 85 | char *url_decode(const char *url) |
| 86 | { |
no test coverage detected