#include #include #include #include #include void throw_error(void){ puts("Status: 501 Failure\r\n\ Content-Type: text/html; charset=US-ASCII\r\n\r\n\ Error in data processing\nCodepages Explorer: "); }; void error_exit(int e){ puts(""); exit(e); }; #define ABCDEF0123456789(x) ( ((x)<='9') ? (x)&0xF : (9+((x)&0x1F)) ) int x2_to_byte(unsigned char lowx, unsigned char highx, unsigned char *byte){ int h; if ( !isxdigit(highx) /* order is important? */ || !isxdigit(lowx) ) return(-1); h = (ABCDEF0123456789(highx) << 4) + ABCDEF0123456789(lowx); if (byte) *byte = (unsigned char)h; return(h); }; #define xFF(x) (((unsigned char)0xFF) & (x)) char const *pa; int get_char(){ unsigned char c; if (!(c = *pa)) return(-2); pa++; if (c=='&') return(-1); if (c=='+') return((int)' '); if (c=='%') { if (x2_to_byte(pa[1], pa[0], &c) < 0) { throw_error(); puts("QUERY_STRING contains a % character not followed by two hexadecimal digits."); error_exit(1); }; /** sscanf(pa, "%2x", &h); **/ pa += 2; /** c = (unsigned char)h; **/ }; if (c&~0x7F) { throw_error(); printf("decoding for high-bit-set octets, such as \\%03o, is not possible in this version." , c); error_exit(1); }; return(c); }; #define MAX_CHARSET_NAME 127 #define BLAH 35 char blah_blah[BLAH+MAX_CHARSET_NAME+1]="Content-Type: text/plain; charset=\""; #define charset (blah_blah+BLAH) char content[512]; main(){ char const *query_string, *bpa; int charset_name_size, g, length=0, ne=0x100; if ( !(query_string = getenv("QUERY_STRING")) || strncmp(query_string, "charset=", 8) ) { puts("Status: 302 Found\r\n\ Location: http://www.superstructure.info/browser/compromised/toxic-sniffing.html#better\r\n\ Content-Type: text/plain\r\nContent-Length: 0\r\n\r"); return(0); }; pa = query_string + 8; for (charset_name_size=0; charset_name_sizestring= parameter not specified."); error_exit(1); }; if (g < 0) break; charset[charset_name_size] = (char)g; }; charset[charset_name_size] = '\0'; if (strncmp(pa, "string=", 7)) { throw_error(); puts("the string= parameter must occur right after charset value."); error_exit(1); }; for (pa += 7; length < sizeof(content); length++) { bpa = pa; if (ne >= 0x100) { if ((g = get_char()) < 0) break; } else { /* workaround for 1- and 2-digits octal escapes */ if ((g = ne) < 0) break; ne = 0x100; }; if (g == '\\') { if ( ((g = get_char()) >= '0') && (g <= '7') ) { g &= 7; if ( ((ne = get_char()) >= '0') && (ne <= '7') ) { g = 8*g + (ne&7); if ( ((ne = get_char()) >= '0') && (ne <= '7') ) { g = 8*g + (ne&7); ne = 0x100; }; }; } else switch (g) { case (int)'a': content[length] = '\a'; goto NextChar; case (int)'b': content[length] = '\b'; goto NextChar; case (int)'t': content[length] = '\t'; goto NextChar; case (int)'n': content[length] = '\n'; goto NextChar; case (int)'v': content[length] = '\v'; goto NextChar; case (int)'f': content[length] = '\f'; goto NextChar; case (int)'r': content[length] = '\r'; goto NextChar; case (int)'\"': case (int)'\'': case (int)'\\': break; case (int)'x': if (x2_to_byte(xFF(get_char()), xFF(get_char()), &(content[length])) >= 0) goto NextChar; /* There is intentionally no unconditional break here! */ default: throw_error(); printf("Unknown escape sequence: %s\n", bpa); error_exit(1); }; }; content[length] = (char)g; NextChar: ; }; fwrite(blah_blah, 1, BLAH+charset_name_size, stdout); printf("\"\r\nX-Content-Type-Options: nosniff\r\nContent-Length: %u\r\n\r\n", length); fwrite(content, 1, length, stdout); return(0); };