Introduction
Introduction Statistics Contact Development Disclaimer Help
gopher.c - frontends - front-ends for some sites (experiment)
Log
Files
Refs
README
LICENSE
---
gopher.c (4954B)
---
1 #include <sys/socket.h>
2 #include <sys/types.h>
3
4 #include <ctype.h>
5 #include <errno.h>
6 #include <netdb.h>
7 #include <stdarg.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <time.h>
12 #include <unistd.h>
13
14 #include "https.h"
15 #include "reddit.h"
16 #include "util.h"
17
18 #define OUT(s) (fputs((s), stdout))
19 #define OUTLINK(s) gophertext(stdout, s, strlen(s))
20 #define OUTTEXT(s) gophertext(stdout, s, strlen(s))
21
22 static const char *baserel = "/reddit.cgi";
23 static const char *host = "127.0.0.1", *port = "70";
24
25 static char before[16], after[16], subreddit[1024];
26
27 void
28 line(int _type, const char *username, const char *selector)
29 {
30 putchar(_type);
31 OUTTEXT(username);
32 putchar('\t');
33 OUTLINK(selector);
34 printf("\t%s\t%s\r\n", host, port);
35 }
36
37 void
38 error(const char *s)
39 {
40 line('3', s, "");
41 }
42
43 void
44 info(const char *s)
45 {
46 line('i', s, "");
47 }
48
49 void
50 dir(const char *username, const char *selector)
51 {
52 line('1', username, selector);
53 }
54
55 void
56 html(const char *username, const char *selector)
57 {
58 line('h', username, selector);
59 }
60
61 void
62 page(int _type, const char *username, const char *page)
63 {
64 putchar(_type);
65 OUTTEXT(username);
66 putchar('\t');
67 printf("%s?p=%s", baserel, page);
68 printf("\t%s\t%s\r\n", host, port);
69 }
70
71 void
72 header(void)
73 {
74 }
75
76 void footer(void)
77 {
78 printf(".\r\n");
79 }
80
81 void
82 printitem(struct item *item)
83 {
84 if (!item || !item->title[0])
85 return;
86
87 struct tm *tm = gmtime(&(item->created_utc));
88
89 putchar('h');
90 OUTTEXT(item->title);
91 OUT(" by ");
92 OUTTEXT(item->author);
93 OUT(" at ");
94 printf("%04d-%02d-%02d %02d:%02d",
95 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
96 tm->tm_hour, tm->tm_min);
97 OUT("\tURL:");
98 OUTLINK(item->url);
99 printf("\t%s\t%s\r\n", host, port);
100
101 /* if global (no subreddit), show where it was posted */
102 if (!subreddit[0]) {
103 printf("1Posted in r/");
104 OUTTEXT(item->subreddit);
105 OUT("\t");
106 OUTTEXT(baserel);
107 OUT("?subreddit=");
108 OUTTEXT(item->subreddit);
109 printf("\t%s\t%s\r\n", host, port);
110 }
111
112 printf("hUpvotes: %ld, downvotes %ld, comments: %ld",
113 item->ups, item->downs, item->num_comments);
114 OUT("\tURL:https://old.reddit.com/r/");
115 OUTTEXT(item->subreddit);
116 OUTTEXT("/comments/");
117 if (reddit_isvalidlink(item->name) && !strncmp(item->name, "t3_"…
118 OUTTEXT(item->name + 3);
119 printf("/\t%s\t%s\r\n", host, port);
120
121 /* TODO: also noticed "spoiler" as value, ignore? */
122 if (item->thumbnail[0] &&
123 strcmp(item->thumbnail, "self") &&
124 strcmp(item->thumbnail, "default")) {
125 putchar('h');
126 OUT("Thumbnail");
127 OUT("\tURL:");
128 OUTTEXT(item->thumbnail);
129 printf("\t%s\t%s\r\n", host, port);
130 }
131
132 if (item->is_video) {
133 putchar('h');
134 OUT("Video, duration: ");
135 printf("%ld, url: ", item->duration);
136 OUTTEXT(item->dash_url);
137 OUT("\tURL:");
138 OUTTEXT(item->dash_url);
139 printf("\t%s\t%s\r\n", host, port);
140 }
141
142 info("");
143 }
144
145 int
146 render_pagination(struct list_response *r)
147 {
148 int i = 0;
149
150 if (r->before[0]) {
151 printf("1Previous page");
152 OUT("\t");
153 OUTTEXT(baserel);
154 OUT("?subreddit=");
155 OUTTEXT(subreddit);
156 OUT("&before=");
157 OUTTEXT(r->before);
158 printf("\t%s\t%s\r\n", host, port);
159 i++;
160 }
161 if (r->after[0]) {
162 printf("1Next page");
163 OUT("\t");
164 OUTTEXT(baserel);
165 OUT("?subreddit=");
166 OUTTEXT(subreddit);
167 OUT("&after=");
168 OUTTEXT(r->after);
169 printf("\t%s\t%s\r\n", host, port);
170 i++;
171 }
172 return i;
173 }
174
175 int
176 render(struct list_response *r)
177 {
178 size_t i;
179
180 header();
181
182 if (pledge("stdio", NULL) == -1)
183 exit(1);
184
185 if (render_pagination(r))
186 info("");
187
188 for (i = 0; i < r->nitems; i++)
189 printitem(&(r->items[i]));
190
191 render_pagination(r);
192
193 footer();
194
195 return 0;
196 }
197
198 static void
199 usage(void)
200 {
201 printf("3Specify a subreddit\t\t%s\t%s\r\n", host, port);
202 printf(".\r\n");
203 exit(1);
204 }
205
206 int
207 main(int argc, char *argv[])
208 {
209 struct list_response *r;
210 char *querystring, *p, *search;
211
212 if (pledge("stdio dns inet rpath unveil", NULL) == -1)
213 exit(1);
214 if (unveil(TLS_CA_CERT_FILE, "r") == -1 ||
215 unveil(NULL, NULL) == -1)
216 exit(1);
217
218 if ((p = getenv("SERVER_NAME")))
219 host = p;
220 if ((p = getenv("SERVER_PORT")))
221 port = p;
222
223 if (!(querystring = getenv("QUERY_STRING")))
224 querystring = "";
225
226 if ((p = getparam(querystring, "subreddit"))) {
227 if (decodeparam(subreddit, sizeof(subreddit), p) == -1)
228 subreddit[0] = '\0';
229 } else {
230 if (!(search = getenv("X_GOPHER_SEARCH"))) /* geomyidae …
231 search = getenv("SEARCHREQUEST"); /* gophernicus…
232
233 if (search && !uriencode(search, subreddit, sizeof(subre…
234 usage();
235 }
236
237 if ((p = getparam(querystring, "before"))) {
238 if (decodeparam(before, sizeof(before), p) == -1)
239 before[0] = '\0';
240 if (!reddit_isvalidlink(before))
241 before[0] = '\0';
242 }
243
244 if ((p = getparam(querystring, "after"))) {
245 if (decodeparam(after, sizeof(after), p) == -1)
246 after[0] = '\0';
247 if (!reddit_isvalidlink(after))
248 after[0] = '\0';
249 }
250
251 r = reddit_list(subreddit, 100, before, after);
252 if (!r || r->nitems == 0) {
253 error("No items found");
254 printf(".\r\n");
255 exit(1);
256 }
257
258 render(r);
259
260 return 0;
261 }
You are viewing proxied material from codemadness.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.