... | ... |
@@ -12,18 +12,22 @@ clean: |
12 | 12 |
kakumei: kakumei.o loglib.o parselib.o sbuf.o \ |
13 | 13 |
socklib.o webkernel.o gen_res.o \ |
14 | 14 |
kakumei_session.o kakumei_pass.o \ |
15 |
- kakumei_posts.o kakumei_config.o |
|
15 |
+ kakumei_posts.o kakumei_config.o \ |
|
16 |
+ kakumei_email.o |
|
16 | 17 |
$(CC) $(LDFLAGS_KAKUMEI) kakumei.o loglib.o parselib.o sbuf.o \ |
17 | 18 |
socklib.o webkernel.o gen_res.o \ |
18 | 19 |
kakumei_session.o kakumei_pass.o \ |
19 | 20 |
kakumei_posts.o kakumei_config.o \ |
21 |
+ kakumei_email.o \ |
|
20 | 22 |
-o kakumei |
21 | 23 |
|
22 | 24 |
kakumei.o: kakumei.c ../src/gen_res.c |
23 | 25 |
|
24 | 26 |
../src/gen_res.c: ../res/index.html ../res/script.js ../res/style.css \ |
25 | 27 |
../res/newuser.html ../res/newuser.js ../res/newuser.css \ |
26 |
- ../res/posts.html ../res/posts.js ../res/posts.css |
|
28 |
+ ../res/posts.html ../res/posts.js ../res/posts.css \ |
|
29 |
+ ../res/newpost.html ../res/newpost.js ../res/newpost.css \ |
|
30 |
+ ../res/account.html ../res/account.js ../res/account.css |
|
27 | 31 |
( cd ../res && ./gen.sh ) |
28 | 32 |
|
29 | 33 |
gen_res.o: ../src/gen_res.c |
... | ... |
@@ -24,6 +24,7 @@ |
24 | 24 |
#include "kakumei_session.h" |
25 | 25 |
#include "kakumei_pass.h" |
26 | 26 |
#include "kakumei_posts.h" |
27 |
+#include "kakumei_email.h" |
|
27 | 28 |
#include "kakumei_config.h" |
28 | 29 |
|
29 | 30 |
#define CONFIGFILE "kakumei.conf" |
... | ... |
@@ -50,6 +51,8 @@ wk_action http_lastpost(wk *web, int connid, wk_uri *uri, void *userptr,char *us |
50 | 51 |
wk_action http_getpost(wk *web, int connid, wk_uri *uri, void *userptr,char *user); |
51 | 52 |
wk_action http_newpost(wk *web, int connid, wk_uri *uri, void *userptr,char *user); |
52 | 53 |
wk_action http_newcomment(wk *web, int connid, wk_uri *uri, void *userptr,char *user); |
54 |
+wk_action http_changeemail(wk *web, int connid, wk_uri *uri, void *userptr,char *user); |
|
55 |
+wk_action http_getemail(wk *web, int connid, wk_uri *uri, void *userptr,char *user); |
|
53 | 56 |
|
54 | 57 |
int |
55 | 58 |
main(int argc, char *argv[]) |
... | ... |
@@ -113,8 +116,8 @@ main(int argc, char *argv[]) |
113 | 116 |
log_write("INIT","Server initialized, waiting connections..."); |
114 | 117 |
while(!sigint_flag) { |
115 | 118 |
sselect_wait(ka->ssel,timeout); |
116 |
- if(sigint_flag) |
|
117 |
- break; |
|
119 |
+ if(sigint_flag) |
|
120 |
+ break; |
|
118 | 121 |
wk_service(ka->web); |
119 | 122 |
} |
120 | 123 |
wk_free(ka->web),ka->web=NULL; |
... | ... |
@@ -322,6 +325,10 @@ callback_http(wk *web, int connid, wk_uri *uri, void *userptr) |
322 | 325 |
return(http_newpost(web,connid,uri,userptr,user)); |
323 | 326 |
else if(memcmp(uri->path,"/newcomment?",12)==0) |
324 | 327 |
return(http_newcomment(web,connid,uri,userptr,user)); |
328 |
+ else if(memcmp(uri->path,"/changeemail?",13)==0) |
|
329 |
+ return(http_changeemail(web,connid,uri,userptr,user)); |
|
330 |
+ else if(memcmp(uri->path,"/getemail?",10)==0) |
|
331 |
+ return(http_getemail(web,connid,uri,userptr,user)); |
|
325 | 332 |
} |
326 | 333 |
/* not found */ |
327 | 334 |
log_write("HTTP","URI not found: %s",uri->path); |
... | ... |
@@ -457,7 +464,6 @@ http_lastpost(wk *web, int connid, wk_uri *uri, void *userptr,char *user) |
457 | 464 |
wk_serve_buffer_as_file(web,connid,reply,strlen(reply),"text/plain"); |
458 | 465 |
log_write("LSTP","Reply: %s",reply); |
459 | 466 |
return(wkact_finished); |
460 |
- |
|
461 | 467 |
} |
462 | 468 |
|
463 | 469 |
wk_action |
... | ... |
@@ -496,6 +502,7 @@ http_newpost(wk *web, int connid, wk_uri *uri, void *userptr,char *user) |
496 | 502 |
log_write("NEWP","invalid post, send error"); |
497 | 503 |
return(wkact_finished); |
498 | 504 |
} |
505 |
+ email_notify(ka,user,-1); |
|
499 | 506 |
log_write("NEWP","Replying with last post"); |
500 | 507 |
return(http_lastpost(web,connid,uri,userptr,user)); |
501 | 508 |
} |
... | ... |
@@ -519,6 +526,41 @@ http_newcomment(wk *web, int connid, wk_uri *uri, void *userptr,char *user) |
519 | 526 |
} |
520 | 527 |
wk_serve_buffer_as_file(web,connid,n,strlen(n),"text/plain"); |
521 | 528 |
log_write("NEWC","Reply: %s",n); |
529 |
+ email_notify(ka,user,num); |
|
530 |
+ return(wkact_finished); |
|
531 |
+} |
|
532 |
+ |
|
533 |
+wk_action |
|
534 |
+http_changeemail(wk *web, int connid, wk_uri *uri, void *userptr,char *user) |
|
535 |
+{ |
|
536 |
+ char useremail[128]; |
|
537 |
+ kakumei *ka=(kakumei *)userptr; |
|
538 |
+ if(wk_uri_copyvar(uri,"a",useremail,sizeof(useremail))==NULL) |
|
539 |
+ useremail[0]='\0'; |
|
540 |
+ if(email_set(ka,user,useremail)!=0) { |
|
541 |
+ wk_serve_error(web,connid,wkerr_internal); |
|
542 |
+ log_write("EMCH","couldn't change email, send error"); |
|
543 |
+ return(wkact_finished); |
|
544 |
+ } |
|
545 |
+ /* valid */ |
|
546 |
+ wk_serve_buffer_as_file(web,connid,useremail,strlen(useremail),"text/plain"); |
|
547 |
+ log_write("EMCH","Reply: %s",useremail); |
|
548 |
+ return(wkact_finished); |
|
549 |
+} |
|
550 |
+ |
|
551 |
+wk_action |
|
552 |
+http_getemail(wk *web, int connid, wk_uri *uri, void *userptr,char *user) |
|
553 |
+{ |
|
554 |
+ char useremail[128]; |
|
555 |
+ kakumei *ka=(kakumei *)userptr; |
|
556 |
+ if(email_get(ka,user,useremail,sizeof(useremail))!=0) { |
|
557 |
+ wk_serve_error(web,connid,wkerr_internal); |
|
558 |
+ log_write("EMGT","no user email, send error"); |
|
559 |
+ return(wkact_finished); |
|
560 |
+ } |
|
561 |
+ /* valid */ |
|
562 |
+ wk_serve_buffer_as_file(web,connid,useremail,strlen(useremail),"text/plain"); |
|
563 |
+ log_write("EMGT","Reply: %s",useremail); |
|
522 | 564 |
return(wkact_finished); |
523 | 565 |
} |
524 | 566 |
|
... | ... |
@@ -19,6 +19,13 @@ |
19 | 19 |
#include "kakumei_config.h" |
20 | 20 |
|
21 | 21 |
#define MAXLINESIZE 2048 |
22 |
+#define LINESBLOCK 32 |
|
23 |
+ |
|
24 |
+typedef enum esection { |
|
25 |
+ section_none=0, |
|
26 |
+ section_general, |
|
27 |
+ section_mail |
|
28 |
+} esection; |
|
22 | 29 |
|
23 | 30 |
kaconfig * |
24 | 31 |
kaconfig_init(char *configfile) |
... | ... |
@@ -28,7 +35,7 @@ kaconfig_init(char *configfile) |
28 | 35 |
char line[MAXLINESIZE]; |
29 | 36 |
int len; |
30 | 37 |
char *ptr,*sep,*value; |
31 |
- int generalsection; |
|
38 |
+ esection section; |
|
32 | 39 |
int lineno; |
33 | 40 |
char **configvalue; |
34 | 41 |
if((f=fopen(configfile,"r"))==NULL) |
... | ... |
@@ -38,15 +45,22 @@ kaconfig_init(char *configfile) |
38 | 45 |
return(NULL); |
39 | 46 |
} |
40 | 47 |
memset(config,0,sizeof(kaconfig)); |
41 |
- generalsection=0; |
|
48 |
+ section=section_none; |
|
42 | 49 |
lineno=0; |
43 | 50 |
while(fgets(line,sizeof(line),f)!=NULL) { |
44 | 51 |
lineno++; |
45 | 52 |
line[sizeof(line)-1]='\0'; |
46 | 53 |
/* trim line */ |
54 |
+ for(ptr=line;*ptr!='\0' && strchr("\t ",*ptr)!=NULL;ptr++) |
|
55 |
+ ; |
|
47 | 56 |
len=strlen(line); |
48 |
- while(len>1 && strchr("\n\t ",line[len-1])!=NULL) |
|
49 |
- line[len-1]='\0',len--; |
|
57 |
+ if(!(section==section_mail && memcmp(ptr,"line.",5)==0)) { |
|
58 |
+ while(len>0 && strchr("\n\t ",line[len-1])!=NULL) |
|
59 |
+ line[len-1]='\0',len--; |
|
60 |
+ } else { |
|
61 |
+ while(len>0 && line[len-1]=='\n') |
|
62 |
+ line[len-1]='\0',len--; |
|
63 |
+ } |
|
50 | 64 |
for(ptr=line;*ptr!='\0' && strchr("\t ",*ptr)!=NULL;ptr++) |
51 | 65 |
; |
52 | 66 |
len=strlen(ptr); |
... | ... |
@@ -56,11 +70,13 @@ kaconfig_init(char *configfile) |
56 | 70 |
/* parse line */ |
57 | 71 |
if(*ptr=='[' && ptr[len-1]==']') { |
58 | 72 |
/* section */ |
59 |
- if(strcmp(ptr,"[general]")==0) |
|
60 |
- generalsection=1; |
|
61 |
- else { |
|
73 |
+ if(strcmp(ptr,"[general]")==0) { |
|
74 |
+ section=section_general; |
|
75 |
+ } else if(strcmp(ptr,"[mail]")==0) { |
|
76 |
+ section=section_mail; |
|
77 |
+ } else { |
|
62 | 78 |
log_write("CONF","%s:%i: unknown section name \"%s\"\n",configfile,lineno,ptr); |
63 |
- generalsection=0; |
|
79 |
+ section=section_none; |
|
64 | 80 |
} |
65 | 81 |
continue; |
66 | 82 |
} else if((sep=strchr(ptr,'='))!=NULL) { |
... | ... |
@@ -71,38 +87,77 @@ kaconfig_init(char *configfile) |
71 | 87 |
sep--; |
72 | 88 |
*sep='\0'; |
73 | 89 |
} |
74 |
- /* trim value */ |
|
75 |
- while(*value!='\0' && strchr(" \t",*value)!=NULL) |
|
76 |
- value++; |
|
90 |
+ if(!(section==section_mail && memcmp(ptr,"line.",5)==0)) { |
|
91 |
+ /* trim value */ |
|
92 |
+ while(*value!='\0' && strchr(" \t",*value)!=NULL) |
|
93 |
+ value++; |
|
94 |
+ } |
|
77 | 95 |
/* sanity check */ |
78 | 96 |
if(*value=='\0') { |
79 |
- log_write("CONF","%s:%i: ignoring key without value; key:\"%s\"\n",configfile,lineno,ptr); |
|
97 |
+ if(!(section==section_mail && memcmp(ptr,"line.",5)==0)) |
|
98 |
+ log_write("CONF","%s:%i: ignoring key without value; key:\"%s\"\n",configfile,lineno,ptr); |
|
80 | 99 |
continue; |
81 | 100 |
} |
82 | 101 |
/* assign value */ |
83 |
- if(generalsection!=1) { |
|
102 |
+ if(section==section_none) { |
|
84 | 103 |
log_write("CONF","%s:%i: ignoring key-value pair in unknown section; key:\"%s\"\n",configfile,lineno,ptr); |
85 | 104 |
continue; |
86 | 105 |
} |
87 | 106 |
/* identify key-value pair */ |
88 |
- if(strcmp(ptr,"logfile")==0) { |
|
89 |
- configvalue=&(config->logfile); |
|
90 |
- } else if(strcmp(ptr,"cookiename")==0) { |
|
91 |
- configvalue=&(config->cookiename); |
|
92 |
- } else if(strcmp(ptr,"cookiedomain")==0) { |
|
93 |
- configvalue=&(config->cookiedomain); |
|
94 |
- } else if(strcmp(ptr,"bannerpath")==0) { |
|
95 |
- configvalue=&(config->bannerpath); |
|
96 |
- } else if(strcmp(ptr,"sslproxy")==0) { |
|
97 |
- if(strcmp(value,"true")==0 || strcmp(value,"1")==0 || strcmp(value,"yes")==0) |
|
98 |
- config->sslproxy=1; |
|
99 |
- else |
|
100 |
- config->sslproxy=0; |
|
101 |
- continue; |
|
102 |
- } else { |
|
103 |
- log_write("CONF","%s:%i: unknown key, ignoring key-value pair; key:\"%s\"\n",configfile,lineno,ptr); |
|
107 |
+ if(section==section_general) { |
|
108 |
+ if(strcmp(ptr,"logfile")==0) { |
|
109 |
+ configvalue=&(config->logfile); |
|
110 |
+ } else if(strcmp(ptr,"cookiename")==0) { |
|
111 |
+ configvalue=&(config->cookiename); |
|
112 |
+ } else if(strcmp(ptr,"cookiedomain")==0) { |
|
113 |
+ configvalue=&(config->cookiedomain); |
|
114 |
+ } else if(strcmp(ptr,"bannerpath")==0) { |
|
115 |
+ configvalue=&(config->bannerpath); |
|
116 |
+ } else if(strcmp(ptr,"sslproxy")==0) { |
|
117 |
+ if(strcmp(value,"true")==0 || strcmp(value,"1")==0 || strcmp(value,"yes")==0) |
|
118 |
+ config->sslproxy=1; |
|
119 |
+ else |
|
120 |
+ config->sslproxy=0; |
|
121 |
+ continue; |
|
122 |
+ } else { |
|
123 |
+ log_write("CONF","%s:%i: unknown key, ignoring key-value pair; key:\"%s\"\n",configfile,lineno,ptr); |
|
124 |
+ continue; |
|
125 |
+ } |
|
126 |
+ } else if(section==section_mail) { |
|
127 |
+ if(strcmp(ptr,"from")==0) { |
|
128 |
+ configvalue=&(config->from); |
|
129 |
+ } else if(strcmp(ptr,"subjpost")==0) { |
|
130 |
+ configvalue=&(config->subjpost); |
|
131 |
+ } else if(strcmp(ptr,"subjcomment")==0) { |
|
132 |
+ configvalue=&(config->subjcomment); |
|
133 |
+ } else if(memcmp(ptr,"line.",5)==0) { |
|
134 |
+ int lineno=atoi(ptr+5); |
|
135 |
+ if(lineno<0) |
|
136 |
+ lineno=0; |
|
137 |
+ if(lineno>=config->sizelines) { |
|
138 |
+ char **lines; |
|
139 |
+ int minsize; |
|
140 |
+ minsize=(lineno+LINESBLOCK)/LINESBLOCK; |
|
141 |
+ minsize*=LINESBLOCK; |
|
142 |
+ if((lines=realloc(config->lines,minsize*sizeof(char *)))==NULL) { |
|
143 |
+ fclose(f),f=NULL; |
|
144 |
+ kaconfig_free(config),config=NULL; |
|
145 |
+ return(NULL); /* insufficient memory */ |
|
146 |
+ } |
|
147 |
+ config->lines=lines; |
|
148 |
+ memset(lines+config->sizelines,0,sizeof(char *)*(minsize-config->sizelines)); |
|
149 |
+ config->sizelines=minsize; |
|
150 |
+ } |
|
151 |
+ configvalue=config->lines+lineno; |
|
152 |
+ if(config->usedlines<=lineno) |
|
153 |
+ config->usedlines=lineno+1; |
|
154 |
+ } else { |
|
155 |
+ log_write("CONF","%s:%i: unknown key, ignoring key-value pair; key:\"%s\"\n",configfile,lineno,ptr); |
|
156 |
+ continue; |
|
157 |
+ } |
|
158 |
+ |
|
159 |
+ } else |
|
104 | 160 |
continue; |
105 |
- } |
|
106 | 161 |
/* store value */ |
107 | 162 |
if(*configvalue!=NULL) { |
108 | 163 |
log_write("CONF","%s:%i: duplicate key, ignoring key-value pair; key:\"%s\"\n",configfile,lineno,ptr); |
... | ... |
@@ -137,6 +192,22 @@ kaconfig_free(kaconfig *config) |
137 | 192 |
free(config->cookiedomain),config->cookiedomain=NULL; |
138 | 193 |
if(config->bannerpath!=NULL) |
139 | 194 |
free(config->bannerpath),config->bannerpath=NULL; |
195 |
+ if(config->from!=NULL) |
|
196 |
+ free(config->from),config->from=NULL; |
|
197 |
+ if(config->subjpost!=NULL) |
|
198 |
+ free(config->subjpost),config->subjpost=NULL; |
|
199 |
+ if(config->subjcomment!=NULL) |
|
200 |
+ free(config->subjcomment),config->subjcomment=NULL; |
|
201 |
+ if(config->lines!=NULL) { |
|
202 |
+ int i; |
|
203 |
+ for(i=0;i<config->usedlines;i++) { |
|
204 |
+ if(config->lines[i]!=NULL) |
|
205 |
+ free(config->lines[i]),config->lines[i]=NULL; |
|
206 |
+ } |
|
207 |
+ config->sizelines=0; |
|
208 |
+ config->usedlines=0; |
|
209 |
+ free(config->lines),config->lines=NULL; |
|
210 |
+ } |
|
140 | 211 |
free(config),config=NULL; |
141 | 212 |
return; |
142 | 213 |
} |
... | ... |
@@ -163,6 +234,7 @@ kaconfig_write(char *configfile,char *logfile, char *cookiename,char *cookiedoma |
163 | 234 |
fprintf(f,"cookiedomain=%s\n",(cookiedomain!=NULL)?cookiedomain:"localhost"); |
164 | 235 |
fprintf(f,"bannerpath=%s\n",(bannerpath!=NULL)?bannerpath:"default.png"); |
165 | 236 |
fprintf(f,"sslproxy=%s\n",(sslproxy==0)?"no":"yes"); |
237 |
+ fprintf(f,"\n[mail]\nfrom=\nsubjpost=New post\nsubjcomment=New comment in post\nline.0=There is a new post or comment\nline.1=Best regards, kakumei web\n"); |
|
166 | 238 |
return(0); |
167 | 239 |
} |
168 | 240 |
|
... | ... |
@@ -12,11 +12,19 @@ |
12 | 12 |
#ifndef KAKUMEI_CONFIG_H |
13 | 13 |
#define KAKUMEI_CONFIG_H |
14 | 14 |
typedef struct kaconfig { |
15 |
+ /* general */ |
|
15 | 16 |
char *logfile; |
16 | 17 |
char *cookiename; |
17 | 18 |
char *cookiedomain; |
18 | 19 |
char *bannerpath; |
19 | 20 |
int sslproxy; |
21 |
+ /* mail */ |
|
22 |
+ char *from; |
|
23 |
+ char *subjpost; |
|
24 |
+ char *subjcomment; |
|
25 |
+ int sizelines; |
|
26 |
+ int usedlines; |
|
27 |
+ char **lines; |
|
20 | 28 |
} kaconfig; |
21 | 29 |
|
22 | 30 |
kaconfig *kaconfig_init(char *configfile); |
23 | 31 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,219 @@ |
1 |
+/* |
|
2 |
+ * kakumei_email.c |
|
3 |
+ * |
|
4 |
+ * E-mail management |
|
5 |
+ * |
|
6 |
+ * Author: Dario Rodriguez dario@softhome.net |
|
7 |
+ * This program is licensed under the terms of the Affero GPL v1+ |
|
8 |
+ */ |
|
9 |
+ |
|
10 |
+#include <stdio.h> |
|
11 |
+#include <stdlib.h> |
|
12 |
+#include <unistd.h> |
|
13 |
+#include <string.h> |
|
14 |
+#include <fcntl.h> |
|
15 |
+#include <sys/types.h> |
|
16 |
+#include <sys/stat.h> |
|
17 |
+#include <dirent.h> |
|
18 |
+#include "sbuf.h" |
|
19 |
+#include "loglib.h" |
|
20 |
+#include "kakumei.h" |
|
21 |
+#include "kakumei_email.h" |
|
22 |
+ |
|
23 |
+#define RD 0 |
|
24 |
+#define WR 1 |
|
25 |
+ |
|
26 |
+static int email_openprogram(kakumei *ka, char *program,char **args, int *parent2child, int *child2parent); |
|
27 |
+static char **email_sendmailargs(kakumei *ka, sbuf *buf, char *fromuser); |
|
28 |
+static int writestr(int fd, char *ptr); |
|
29 |
+ |
|
30 |
+int |
|
31 |
+email_set(kakumei *ka, char *user, char *email) |
|
32 |
+{ |
|
33 |
+ char filename[1024]; |
|
34 |
+ int fd; |
|
35 |
+ if(ka==NULL || user==NULL || user[0]=='\0' || email==NULL) { |
|
36 |
+ log_write("MAIL","sanity check error"); |
|
37 |
+ return(-1); |
|
38 |
+ } |
|
39 |
+ mkdir(USERSDIR,0700); |
|
40 |
+ snprintf(filename,sizeof(filename)-1,"%s/%s/email",USERSDIR,user); |
|
41 |
+ filename[sizeof(filename)-1]='\0'; |
|
42 |
+ if(email[0]=='\0') { |
|
43 |
+ unlink(filename); |
|
44 |
+ return(0); |
|
45 |
+ } |
|
46 |
+ if((fd=open(filename,O_WRONLY|O_TRUNC|O_CREAT,0600))==-1) |
|
47 |
+ return(-1); |
|
48 |
+ write(fd,email,strlen(email)); |
|
49 |
+ close(fd),fd=-1; |
|
50 |
+ return(0); |
|
51 |
+} |
|
52 |
+ |
|
53 |
+int |
|
54 |
+email_get(kakumei *ka, char *user, char *email,int sizeemail) |
|
55 |
+{ |
|
56 |
+ char filename[1024]; |
|
57 |
+ int fd; |
|
58 |
+ if(ka==NULL || user==NULL || user[0]=='\0' || email==NULL || sizeemail<1) { |
|
59 |
+ log_write("MAIL","sanity check error"); |
|
60 |
+ return(-1); |
|
61 |
+ } |
|
62 |
+ snprintf(filename,sizeof(filename)-1,"%s/%s/email",USERSDIR,user); |
|
63 |
+ filename[sizeof(filename)-1]='\0'; |
|
64 |
+ if((fd=open(filename,O_RDONLY))==-1) |
|
65 |
+ return(-1); |
|
66 |
+ memset(email,0,sizeemail); |
|
67 |
+ read(fd,email,sizeemail-1); |
|
68 |
+ email[sizeemail-1]='\0'; |
|
69 |
+ close(fd),fd=-1; |
|
70 |
+ return(0); |
|
71 |
+} |
|
72 |
+ |
|
73 |
+int |
|
74 |
+email_notify(kakumei *ka, char *fromuser, int numpost) |
|
75 |
+{ |
|
76 |
+ int bufnum; |
|
77 |
+ sbuf *buf; |
|
78 |
+ int parent2child,child2parent; |
|
79 |
+ char **args; |
|
80 |
+ int i; |
|
81 |
+ /* check if from has been defined in config file */ |
|
82 |
+ if(ka->config->from==NULL) { |
|
83 |
+ log_write("MAIL","mail isn't configured in kakumei config file (no \"from\")"); |
|
84 |
+ return(-1); |
|
85 |
+ } |
|
86 |
+ /* generate the list of recipients */ |
|
87 |
+ if((bufnum=wk_sbufacquire(ka->web))==-1) { |
|
88 |
+ log_write("MAIL","couldn't acquire buffer to prepare the recipients list"); |
|
89 |
+ return(-1); |
|
90 |
+ } |
|
91 |
+ if((buf=wk_sbufget(ka->web,bufnum))==NULL) { |
|
92 |
+ log_write("EINT","%s:%i",__FILE__,__LINE__); |
|
93 |
+ return(-1); |
|
94 |
+ } |
|
95 |
+ if((args=email_sendmailargs(ka,buf,fromuser))==NULL) { |
|
96 |
+ wk_sbufrelease(ka->web,bufnum),bufnum=-1; |
|
97 |
+ log_write("MAIL","couldn't build recipient list"); |
|
98 |
+ return(-1); |
|
99 |
+ } |
|
100 |
+ /* send the message */ |
|
101 |
+ if(email_openprogram(ka,"/usr/sbin/sendmail",args,&parent2child,&child2parent)<=0) { |
|
102 |
+ wk_sbufrelease(ka->web,bufnum),bufnum=-1; |
|
103 |
+ log_write("MAIL","couldn't exec sendmail"); |
|
104 |
+ return(-1); |
|
105 |
+ } |
|
106 |
+ wk_sbufrelease(ka->web,bufnum),bufnum=-1; |
|
107 |
+ writestr(parent2child,"From: "); |
|
108 |
+ writestr(parent2child,(ka->config->from!=NULL)?ka->config->from:""); |
|
109 |
+ writestr(parent2child,"\nSubject: "); |
|
110 |
+ if(numpost==-1) |
|
111 |
+ writestr(parent2child,(ka->config->subjpost!=NULL)?ka->config->subjpost:"kakumei post"); |
|
112 |
+ else |
|
113 |
+ writestr(parent2child,(ka->config->subjcomment!=NULL)?ka->config->subjcomment:"kakumei comment"); |
|
114 |
+ if(numpost!=-1) { |
|
115 |
+ char mybuf[32]; |
|
116 |
+ snprintf(mybuf,sizeof(mybuf)," #%i",numpost); |
|
117 |
+ mybuf[sizeof(mybuf)-1]='\0'; |
|
118 |
+ writestr(parent2child,mybuf); |
|
119 |
+ } |
|
120 |
+ writestr(parent2child,"\n\n"); |
|
121 |
+ for(i=0;i<ka->config->usedlines;i++) { |
|
122 |
+ writestr(parent2child,(ka->config->lines[i]==NULL)?"":ka->config->lines[i]); |
|
123 |
+ writestr(parent2child,"\n"); |
|
124 |
+ } |
|
125 |
+ close(parent2child),parent2child=-1; |
|
126 |
+ close(child2parent),child2parent=-1; |
|
127 |
+ log_write("MAIL","sent email notify from user:%s post:%i",fromuser,numpost); |
|
128 |
+ return(0); |
|
129 |
+} |
|
130 |
+ |
|
131 |
+static int |
|
132 |
+email_openprogram(kakumei *ka, char *program,char **args, int *paramparent2child, int *paramchild2parent) |
|
133 |
+{ |
|
134 |
+ int parent2child[2]; |
|
135 |
+ int child2parent[2]; |
|
136 |
+ int pid; |
|
137 |
+ parent2child[0]=parent2child[1]=-1; |
|
138 |
+ child2parent[0]=child2parent[1]=-1; |
|
139 |
+ if(pipe(parent2child)!=0 || pipe(child2parent)!=0) { |
|
140 |
+ close(parent2child[0]); /* just in case the first pipe() succeeded but not the second */ |
|
141 |
+ close(parent2child[1]); |
|
142 |
+ return(-1); /* Couldn't create pipes for communicating with child process */ |
|
143 |
+ } |
|
144 |
+ if((pid=fork())==0) { |
|
145 |
+ /* child process */ |
|
146 |
+ int i,l; |
|
147 |
+ close(0); |
|
148 |
+ dup(parent2child[RD]); |
|
149 |
+ close(1); |
|
150 |
+ dup(child2parent[WR]); |
|
151 |
+ l=getdtablesize(); |
|
152 |
+ for(i=2;i<l;i++) |
|
153 |
+ close(i); |
|
154 |
+ execv(program,args); |
|
155 |
+ exit(1); /* error in exec */ |
|
156 |
+ } |
|
157 |
+ close(parent2child[RD]),parent2child[RD]=-1; |
|
158 |
+ close(child2parent[WR]),child2parent[WR]=-1; |
|
159 |
+ *paramparent2child=parent2child[WR]; |
|
160 |
+ *paramchild2parent=child2parent[RD]; |
|
161 |
+ return(pid); |
|
162 |
+} |
|
163 |
+ |
|
164 |
+static char ** |
|
165 |
+email_sendmailargs(kakumei *ka, sbuf *buf, char *fromuser) |
|
166 |
+{ |
|
167 |
+ DIR *dir; |
|
168 |
+ struct dirent *de; |
|
169 |
+ int pre; |
|
170 |
+ int n,k; |
|
171 |
+ char *ptr; |
|
172 |
+ char **args; |
|
173 |
+ char email[128]; |
|
174 |
+ sbuf_wipe(buf); |
|
175 |
+ pre=2; |
|
176 |
+ sbuf_addstr(buf,"sendmail"); |
|
177 |
+ sbuf_add(buf,"",1); |
|
178 |
+ sbuf_addstr(buf,"-i"); |
|
179 |
+ sbuf_add(buf,"",1); |
|
180 |
+ if((dir=opendir(USERSDIR))==NULL) { |
|
181 |
+ log_write("MAIL","couldn't open users directory"); |
|
182 |
+ return(NULL); |
|
183 |
+ } |
|
184 |
+ for(n=0;(de=readdir(dir))!=NULL;) { |
|
185 |
+ if(strcmp(de->d_name,fromuser)==0) |
|
186 |
+ continue; |
|
187 |
+ if(email_get(ka,de->d_name,email,sizeof(email))!=0) |
|
188 |
+ continue; |
|
189 |
+ uri_urldecode(email); |
|
190 |
+ sbuf_add(buf,email,strlen(email)+1); |
|
191 |
+ n++; |
|
192 |
+ } |
|
193 |
+ closedir(dir),dir=NULL; |
|
194 |
+ if(n==0) { |
|
195 |
+ log_write("MAIL","no recipients for e-mail notification"); |
|
196 |
+ return(NULL); /* no recipients */ |
|
197 |
+ } |
|
198 |
+ n+=pre; |
|
199 |
+ if(sbuf_unused(buf)<(sizeof(char *)*(n+1))) { |
|
200 |
+ log_write("MAIL","too many recipients, couldn't build list"); |
|
201 |
+ return(NULL); /* too many recipients */ |
|
202 |
+ } |
|
203 |
+ args=(char **)sbuf_ptrunused(buf); |
|
204 |
+ memset((char *)args,0,(sizeof(char *)*(n+1))); |
|
205 |
+ for(k=0,ptr=sbuf_ptr(buf);k<n;k++) { |
|
206 |
+ args[k]=ptr; |
|
207 |
+ ptr+=strlen(ptr)+1; |
|
208 |
+ } |
|
209 |
+ args[k]=NULL; |
|
210 |
+ sbuf_addfromunused(buf,(sizeof(char *)*(n+1))); |
|
211 |
+ return(args); |
|
212 |
+} |
|
213 |
+ |
|
214 |
+static int |
|
215 |
+writestr(int fd, char *ptr) |
|
216 |
+{ |
|
217 |
+ return(write(fd,ptr,strlen(ptr))); |
|
218 |
+} |
|
219 |
+ |
0 | 220 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,17 @@ |
1 |
+/* |
|
2 |
+ * kakumei_email.c |
|
3 |
+ * |
|
4 |
+ * E-mail management |
|
5 |
+ * |
|
6 |
+ * Header file. |
|
7 |
+ * |
|
8 |
+ * Author: Dario Rodriguez dario@softhome.net |
|
9 |
+ * This program is licensed under the terms of the Affero GPL v1+ |
|
10 |
+ */ |
|
11 |
+ |
|
12 |
+#include "kakumei.h" |
|
13 |
+ |
|
14 |
+int email_set(kakumei *ka, char *user, char *email); |
|
15 |
+int email_get(kakumei *ka, char *user, char *email,int sizeemail); |
|
16 |
+int email_notify(kakumei *ka, char *fromuser, int numpost); |
|
17 |
+ |