1 /**
2 * Copyright (C) 2014 Aaron Ball <nullspoon@iohq.net>
3 *
4 * Remoteinfo is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * Remoteinfo is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with remoteinfo. If not, see <http://www.gnu.org/licenses/>.
16 */
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20
21 #define qsmax 512
22
23 /**
24 * Searches the query string for the specified key, and copies the value
25 * to the out variable.
26 *
27 * @param char* key Key to search the query string for
28 * @param int len Maximum length of key and value (for security reasons)
29 * @param char* out Pointer to output variable value will be copied to
30 *
31 * @return int Found (1), not found (0), or error (-1)
32 */
33 int getqs(char* key, int len, char* out) {
34 char* qs;
35 char* val;
36 int valstart;
37 int i;
38
39 // Get the query string
40 qs = getenv("QUERY_STRING");
41
42 // Exit early if the query string was not found.
43 if(qs == NULL) return -1;
44
45 // Search for the key in the query string
46 val = strstr(qs, key);
47
48 // Exit early if the key/value was not found.
49 if(val == NULL) return 0;
50
51 i = 0;
52 // Find the equals sign
53 while(val[i] != '=') {
54 // break if we hit a qs delimiter (&)
55 if(val[i] == '&') return 0;
56 // Break if we hit the maximum length (for security, to avoid buffer
57 // overflows or overflow dumps.
58 if((i + 1) == len) return 0;
59 i++;
60 }
61 // Repoint the start of val
62 val = &val[i + 1];
63
64 // Reset i to 0
65 i = 0;
66 while(val[i] != '\0') {
67 // break if we hit a qs delimiter (&)
68 if(val[i] == '&') break;
69 // Break if we hit the maximum length (for security, to avoid buffer
70 // overflows or overflow dumps.
71 if((i + 1) == len) break;
72 // copy char in
73 out[i] = val[i];
74 i++;
75 }
76 out[i] = '\0';
77 return 1;
78 }
79
80
81 void read_file(char* path, FILE* out) {
82 FILE *f = fopen(path, "r");
83
84 fprintf(out, "<pre>");
85
86 char buf;
87 while((buf = fgetc(f)) != EOF) {
88 if(buf == '<') {
89 // Print an html line break if we fine a newline
90 fprintf(out, "<");
91 } else {
92 fprintf(out, "%c", buf);
93 }
94 }
95 fprintf(out, "</pre>");
96
97 fclose(f);
98 }
99
100 void stylesheet(char* path, FILE* out) {
101 fprintf(out, "<link rel=\"stylesheet\" ");
102 fprintf(out, "type=\"text/css\" href=\"%s\" />\n", path);
103 }
104
105 int print_html_header(FILE* out) {
106 fprintf(out, "<html>\n");
107 fprintf(out, "<head>\n");
108 stylesheet("style.css", out);
109 fprintf(out, "</head>\n");
110 fprintf(out, "<body>\n");
111 }
112
113 void print_body(FILE* out) {
114 char q[qsmax];
115 int found;
116 char* reqvar;
117
118 // Get value of q
119 found = getqs("q", qsmax, q);
120 if(found != 1) return;
121
122 // All looks well, let's try to handle the query string.
123 if(strcmp(q, "ip") == 0) {
124 // IP request
125 reqvar = getenv("REMOTE_ADDR");
126 if(reqvar == NULL) {
127 fprintf(out, "ERROR: REMOTE_ADDR not set.");
128 } else {
129 fprintf(out, "%s", getenv("REMOTE_ADDR"));
130 }
131 } else if(strcmp(q, "agent") == 0) {
132 // Useragent request
133 reqvar = getenv("HTTP_USER_AGENT");
134 if(reqvar == NULL) {
135 fprintf(out, "ERROR: HTTP_USER_AGENT not set.");
136 } else {
137 fprintf(out, "%s", getenv("HTTP_USER_AGENT"));
138 }
139 }
140 fprintf(out, "\n");
141 }
142
143
144 void print_html_footer(FILE* out) {
145 fprintf(out, "</body>\n</html>\n");
146 }
147
148
149 int main(int argc, char* argv[]) {
150 // Print the content type header (very useful)
151 fprintf(stdout, "Content-Type: text/html;\n\n");
152
153 // Check if "type" qs is specified, and handle appropriately if it is
154 // This is for printing in different formats (eg: style html, json, etc)
155 int found;
156 char type[qsmax];
157 found = getqs("type", qsmax, type);
158
159 if(found == 1) {
160 // Prints the html header (<html><head>, etc.)
161 print_html_header(stdout);
162 }
163
164 print_body(stdout);
165
166 // Annnnd the footer
167 if(found == 1) {
168 // Prints the html footer (</body></html>)
169 print_html_footer(stdout);
170 }
171
172 return 0;
173 }
|