Browse code

Add simple form to ask for the e-mail and get the reply via POST request

Dario Rodriguez authored on 05/05/2015 19:14:56
Showing 5 changed files
... ...
@@ -1,5 +1,10 @@
1 1
 <!doctype html>
2 2
 <html>
3 3
 <head><title>Newsletter</title></head>
4
-<body></body>
4
+<body>
5
+<form action="/~/addemail" method="post">
6
+	<input id="email" name="email" placeholder="e-mail">
7
+	<input type="submit" value="subscribe">
8
+<form>
9
+</body>
5 10
 </html>
... ...
@@ -1,6 +1,6 @@
1 1
 WEBKERNEL=../../webkernel/src
2 2
 CC=gcc
3
-CFLAGS=-g -Wall -I$(WEBKERNEL) -I../res -DWK_DEBUG_CONN -DBUFSIZE=16384
3
+CFLAGS=-g -Wall -I$(WEBKERNEL) -I../res -DWK_DEBUG_IO -DWK_DEBUG_CONN -DBUFSIZE=16384
4 4
 LDFLAGS=
5 5
 
6 6
 all: newslettersan
... ...
@@ -27,7 +27,7 @@ typedef enum esection {
27 27
 
28 28
 
29 29
 newslconfig *
30
-newslconfig_init(char *configfile)
30
+newslconfig_init(char *configfile, char *deflogfile, char *defrootdir)
31 31
 {
32 32
 	newslconfig *config;
33 33
 	FILE *f;
... ...
@@ -96,6 +96,8 @@ newslconfig_init(char *configfile)
96 96
                         if(section==section_general) {
97 97
                                 if(strcmp(ptr,"logfile")==0) {
98 98
                                         configvalue=&(config->logfile);
99
+                                } else if(strcmp(ptr,"rootdir")==0) {
100
+                                        configvalue=&(config->rootdir);
99 101
 				} else {
100 102
                                         log_write("CONF","%s:%i: unknown key, ignoring key-value pair; key:\"%s\"\n",configfile,lineno,ptr);
101 103
                                         continue;
... ...
@@ -119,6 +121,11 @@ newslconfig_init(char *configfile)
119 121
                 }
120 122
         }
121 123
         fclose(f),f=NULL;
124
+	if((config->logfile==NULL && (config->logfile=strdup(deflogfile))==NULL) ||
125
+	   (config->rootdir==NULL && (config->rootdir=strdup(defrootdir))==NULL)) {
126
+		newslconfig_free(config),config=NULL;
127
+		return(NULL);
128
+	}
122 129
         return(config);
123 130
 }
124 131
 
... ...
@@ -129,6 +136,8 @@ newslconfig_free(newslconfig *config)
129 136
                 return;
130 137
         if(config->logfile!=NULL)
131 138
                 free(config->logfile),config->logfile=NULL;
139
+        if(config->rootdir!=NULL)
140
+                free(config->rootdir),config->rootdir=NULL;
132 141
         free(config),config=NULL;
133 142
         return;
134 143
 }
... ...
@@ -143,7 +152,7 @@ newslconfig_exists(char *configfile)
143 152
 }
144 153
 
145 154
 int
146
-newslconfig_write(char *configfile,char *logfile)
155
+newslconfig_write(char *configfile,char *logfile,char *rootdir)
147 156
 {
148 157
         FILE *f;
149 158
         if((f=fopen(configfile,"w"))==NULL)
... ...
@@ -151,6 +160,7 @@ newslconfig_write(char *configfile,char *logfile)
151 160
         fprintf(f,"; newslettersan config file\n");
152 161
         fprintf(f,"[general]\n");
153 162
         fprintf(f,"logfile=%s\n",(logfile!=NULL)?logfile:"newslettersan.log");
163
+        fprintf(f,"rootdir=%s\n",(rootdir!=NULL)?rootdir:"subscribe");
154 164
         return(0);
155 165
 }
156 166
 
... ...
@@ -14,12 +14,13 @@
14 14
 
15 15
 typedef struct newslconfig {
16 16
 	char *logfile;
17
+	char *rootdir;
17 18
 } newslconfig;
18 19
 
19
-newslconfig *newslconfig_init(char *configfile);
20
+newslconfig *newslconfig_init(char *configfile, char *deflogfile, char *defrootdir);
20 21
 void newslconfig_free(newslconfig *config);
21 22
 
22 23
 int newslconfig_exists(char *configfile);
23
-int newslconfig_write(char *configfile,char *logfile);
24
+int newslconfig_write(char *configfile,char *logfile,char *rootdir);
24 25
 
25 26
 #endif
... ...
@@ -23,20 +23,23 @@
23 23
 
24 24
 #define CONFIGFILE "newslettersan.cfg"
25 25
 #define CFLOGFILE "newslettersan.log"
26
+#define CFROOTDIR "subscribe"
26 27
 
27 28
 static int signal_init(int signum, void (*fn)(int));
28 29
 static void sigint(int signum);
29 30
 volatile int sigint_flag=0;
30 31
 
32
+wk_action callback_post(wk *web, int connid, wk_uri *uri, void *userptr);
31 33
 wk_action callback_http(wk *web, int connid, wk_uri *uri, void *userptr);
34
+int newsl_serve_buffer_with_rootdir(newslettersan *newsl, wk *web, int connid, char *data, int datalen, const char *mime);
32 35
 
33 36
 int
34 37
 main(int argc, char *argv[])
35 38
 {
36 39
         int timeout=500;
37 40
         int serverfd;
38
-	newslettersan *newsl,newslstore;
39
-	char *hostnameport;
41
+        newslettersan *newsl,newslstore;
42
+        char *hostnameport;
40 43
         char hostname[128];
41 44
         char *host;
42 45
         long hostsize;
... ...
@@ -51,9 +54,9 @@ main(int argc, char *argv[])
51 54
         if(newslconfig_exists(CONFIGFILE)!=0) {
52 55
                 log_setlogfile(CFLOGFILE);
53 56
                 log_write("INIT","Config file not found, writing default file %s",CONFIGFILE);
54
-                newslconfig_write(CONFIGFILE,CFLOGFILE);
57
+                newslconfig_write(CONFIGFILE,CFLOGFILE,CFROOTDIR);
55 58
         }
56
-        if((newsl->config=newslconfig_init(CONFIGFILE))==NULL) {
59
+        if((newsl->config=newslconfig_init(CONFIGFILE,CFLOGFILE,CFROOTDIR))==NULL) {
57 60
                 log_setlogfile(CFLOGFILE);
58 61
                 log_write("INIT","ERROR: insufficient memory or config file error");
59 62
                 return(1);
... ...
@@ -82,7 +85,7 @@ main(int argc, char *argv[])
82 85
                 return(2);
83 86
         }
84 87
         sock_setunsafe(serverfd);
85
-        if((newsl->web=wk_init(serverfd,newsl->ssel,NULL,callback_http,NULL,NULL,newsl))==NULL) {
88
+        if((newsl->web=wk_init(serverfd,newsl->ssel,NULL,callback_http,callback_post,NULL,newsl))==NULL) {
86 89
                 sselect_free(newsl->ssel),newsl->ssel=NULL;
87 90
                 log_write("INIT","ERROR: couldn't init web server");
88 91
                 return(2);
... ...
@@ -120,25 +123,114 @@ sigint(int signum)
120 123
         sigint_flag=1;
121 124
 }
122 125
 
126
+wk_action
127
+callback_post(wk *web, int connid, wk_uri *uri, void *userptr)
128
+{
129
+        newslettersan *newsl=(newslettersan *)userptr;
130
+        char partialpath[1024];
131
+        int l;
132
+        if(newsl==NULL)
133
+                return(wkact_finished);
134
+        /* check that URI starts with /$rootdir/ */
135
+        l=strlen(newsl->config->rootdir);
136
+        if(uri->path[0]!='/' || memcmp(uri->path+1,newsl->config->rootdir,l)!=0 ||
137
+                uri->path[l+1]!='/') {
138
+                return(wkact_finished);
139
+        }
140
+        /* copy the path below $rootdir into partialpath */
141
+        strncpy(partialpath,uri->path+1+l,sizeof(partialpath)-1);
142
+        partialpath[sizeof(partialpath)-1]='\0';
143
+        /* set push variables for the specified URI */
144
+        /* to be able to retrieve them in callback_http */
145
+        if(strcmp(partialpath,"/addemail")==0) {
146
+                wk_post_addvalid(web,connid,"email",NULL);
147
+        }
148
+        return(wkact_finished);
149
+}
150
+
123 151
 wk_action
124 152
 callback_http(wk *web, int connid, wk_uri *uri, void *userptr)
125 153
 {
126 154
         newslettersan *newsl=(newslettersan *)userptr;
127 155
         resindex *res;
156
+        int l;
128 157
         char partialpath[1024];
129
-	if(newsl==NULL)
130
-		return(wkact_finished);
131
-	strncpy(partialpath,uri->path,sizeof(partialpath)-1);
158
+        if(newsl==NULL)
159
+                return(wkact_finished);
160
+        /* redirect to the real root URI if request is "/" */
161
+        if(strcmp(uri->path,"/")==0) {
162
+                partialpath[0]='/';
163
+                strncpy(partialpath+1,newsl->config->rootdir,sizeof(partialpath)-1);
164
+                partialpath[sizeof(partialpath)-1]='\0';
165
+                if((l=strlen(partialpath))<(sizeof(partialpath)-2))
166
+                        strcpy(partialpath+l,"/");
167
+                wk_serve_redirect(web,connid,partialpath);
168
+                return(wkact_finished);
169
+        }
170
+        /* check that URI starts with /$rootdir/ */
171
+        l=strlen(newsl->config->rootdir);
172
+        if(uri->path[0]!='/' || memcmp(uri->path+1,newsl->config->rootdir,l)!=0 ||
173
+                uri->path[l+1]!='/') {
174
+                wk_serve_error(web,connid,wkerr_notfound);
175
+                return(wkact_finished);
176
+        }
177
+        /* copy the path below $rootdir into partialpath */
178
+        strncpy(partialpath,uri->path+1+l,sizeof(partialpath)-1);
132 179
         partialpath[sizeof(partialpath)-1]='\0';
133
-	if(strcmp(uri->path,"/")==0)
134
-                strcpy(partialpath,"/index.html");
180
+        /* change the root url to index.html if neccessary */
181
+        if(strcmp(partialpath,"/")==0) {
182
+                strncpy(partialpath,"/index.html",sizeof(partialpath));
183
+                partialpath[sizeof(partialpath)-1]='\0';
184
+        }
185
+        /* serve the requested page */
135 186
         if(partialpath[0]=='/' && (res=res_find(resindexdata,partialpath+1))!=NULL) {
136
-		log_write("HTTP","Serving in-memory file %s",partialpath+1);
137
-		wk_serve_etagset(web,connid,res->etag);
138
-		wk_serve_buffer_as_file(web,connid,res->data,res->len,mime_getdefault(res->name,"application/octet-stream"));
139
-		return(wkact_finished);
140
-	}
141
-	wk_serve_error(web,connid,wkerr_notfound);
187
+                log_write("HTTP","Serving in-memory file %s",partialpath+1);
188
+                wk_serve_etagset(web,connid,res->etag);
189
+                newsl_serve_buffer_with_rootdir(newsl,web,connid,(char *) res->data,res->len,mime_getdefault(res->name,"application/octet-stream"));
190
+                return(wkact_finished);
191
+        } else if(strcmp(partialpath,"/addemail")==0) {
192
+                char *email;
193
+                if((email=wk_post_get(web,connid,"email",NULL))==NULL) {
194
+                        wk_serve_error(web,connid,wkerr_internal);
195
+                        return(wkact_finished);
196
+                }
197
+                #warning TODO: do something with the email
198
+                wk_serve_buffer_as_file(web,connid,email,strlen(email),"text/plain");
199
+                return(wkact_finished);
200
+        }
201
+        wk_serve_error(web,connid,wkerr_notfound);
142 202
         return(wkact_finished);
143 203
 }
144 204
 
205
+int
206
+newsl_serve_buffer_with_rootdir(newslettersan *newsl, wk *web, int connid, char *data, int datalen, const char *mime)
207
+{
208
+        int res;
209
+        sbuf *buf;
210
+        int sbufid;
211
+        char *last,*next,*end;
212
+        if(newsl==NULL || web==NULL || data==NULL || datalen<0)
213
+                return(-1); /* sanity check failed */
214
+        if((sbufid=wk_sbufacquire(web))==-1 || (buf=wk_sbufget(web,sbufid))==NULL)
215
+                return(-1);
216
+        /* we copy the buffer substituting /~/ for /$rootdir/ */
217
+        end=data+datalen;
218
+        for(last=data,next=((last+3)<=end)?memchr(last,'/',end-last-3):NULL;next!=NULL;next=((last+3)<=end)?memchr(last,'/',end-last-3):NULL) {
219
+                if(memcmp(next,"/~/",3)==0) {
220
+                        sbuf_add(buf,last,next-last);
221
+                        sbuf_add(buf,"/",1);
222
+                        sbuf_addstr(buf,newsl->config->rootdir);
223
+                        sbuf_add(buf,"/",1);
224
+                        last=next+3;
225
+                } else {
226
+                        sbuf_add(buf,last,next-last+1);
227
+                        last=next+1;
228
+                }
229
+        }
230
+        sbuf_add(buf,last,end-last);
231
+        /* send the constructed buffer */
232
+        res=wk_serve_buffer_as_file(web,connid,sbuf_ptr(buf),sbuf_count(buf),mime);
233
+        wk_sbufrelease(web,sbufid),sbufid=-1,buf=NULL;
234
+        return(res);
235
+
236
+}