... | ... |
@@ -4,7 +4,7 @@ |
4 | 4 |
* Posts management |
5 | 5 |
* |
6 | 6 |
* Author: Dario Rodriguez dario@softhome.net |
7 |
- * This progran is licensed under the terms of the Affero GPL v1+ |
|
7 |
+ * This program is licensed under the terms of the Affero GPL v1+ |
|
8 | 8 |
*/ |
9 | 9 |
|
10 | 10 |
#include <stdio.h> |
... | ... |
@@ -35,8 +35,8 @@ post_new(kakumei *ka, char *user, char *title, char *text) |
35 | 35 |
return(-1); |
36 | 36 |
} |
37 | 37 |
last=post_last(ka); |
38 |
- if(last==-1) |
|
39 |
- last=0; /* post number starts on 1 (last+1)*/ |
|
38 |
+ if(last==-1) |
|
39 |
+ last=0; /* post number starts on 1 (last+1)*/ |
|
40 | 40 |
filename[0]='\0'; |
41 | 41 |
for(num=last+1;num<MAXPOSTS;num++) { |
42 | 42 |
snprintf(filename,sizeof(filename),"%s/%04i/%04i.json",POSTSDIR,num/10000,num%10000); |
... | ... |
@@ -35,6 +35,8 @@ post_new(kakumei *ka, char *user, char *title, char *text) |
35 | 35 |
return(-1); |
36 | 36 |
} |
37 | 37 |
last=post_last(ka); |
38 |
+ if(last==-1) |
|
39 |
+ last=0; /* post number starts on 1 (last+1)*/ |
|
38 | 40 |
filename[0]='\0'; |
39 | 41 |
for(num=last+1;num<MAXPOSTS;num++) { |
40 | 42 |
snprintf(filename,sizeof(filename),"%s/%04i/%04i.json",POSTSDIR,num/10000,num%10000); |
... | ... |
@@ -114,6 +114,7 @@ post_addcomment(kakumei *ka, int postnum, char *user, char *text) |
114 | 114 |
char filename[1024]; |
115 | 115 |
char buf[16]; |
116 | 116 |
FILE *f; |
117 |
+ int off; |
|
117 | 118 |
if(ka==NULL || postnum<0 || user==NULL || text==NULL) { |
118 | 119 |
log_write("POST","Sanity check error\n"); |
119 | 120 |
return(-1); |
... | ... |
@@ -121,17 +122,25 @@ post_addcomment(kakumei *ka, int postnum, char *user, char *text) |
121 | 122 |
if(post_get(ka,postnum,filename,sizeof(filename))!=0) |
122 | 123 |
return(-1); |
123 | 124 |
if((f=fopen(filename,"r+"))==NULL) { |
124 |
- log_write("POST","Couldn't open post file fot appending\n"); |
|
125 |
+ log_write("POST","Couldn't open post file for appending\n"); |
|
125 | 126 |
return(-1); |
126 | 127 |
} |
127 |
- fseek(f,-2,SEEK_END); |
|
128 |
- if(fread(buf,1,2,f)!=2 || buf[0]!=']' || buf[1]!='}') { |
|
128 |
+ fseek(f,-5,SEEK_END); |
|
129 |
+ if(fread(buf,1,5,f)!=5) { |
|
130 |
+ fclose(f),f=NULL; |
|
131 |
+ log_write("POST","Post file contents are too small\n"); |
|
132 |
+ return(-1); |
|
133 |
+ } |
|
134 |
+ off=(buf[4]=='\n')?1:0; |
|
135 |
+ if(buf[4-off]!='}' || buf[3-off]!=']' || buf[2-off]!='\n') { |
|
129 | 136 |
fclose(f),f=NULL; |
130 | 137 |
log_write("POST","Post file contents are corrupted\n"); |
131 | 138 |
return(-1); |
132 | 139 |
} |
133 |
- fseek(f,-2,SEEK_END); |
|
134 |
- fprintf(f," { \"author\":\"%s\",\"date\":%li,\"text\":\"%s\"},\n]}",user,(long)time(NULL),text); |
|
140 |
+ fseek(f,-4-off,SEEK_END); |
|
141 |
+ fprintf(f,"%c%s\n { \"author\":\"%s\",\"date\":%li,\"text\":\"%s\"}\n]}", |
|
142 |
+ buf[1-off],(buf[1-off]!='[')?",":"", |
|
143 |
+ user,(long)time(NULL),text); |
|
135 | 144 |
fclose(f),f=NULL; |
136 | 145 |
return(0); |
137 | 146 |
} |
... | ... |
@@ -22,7 +22,7 @@ |
22 | 22 |
#define MAXPOSTS 2000000 |
23 | 23 |
|
24 | 24 |
int |
25 |
-post_new(kakumei *ka, char *user, char *text) |
|
25 |
+post_new(kakumei *ka, char *user, char *title, char *text) |
|
26 | 26 |
{ |
27 | 27 |
int last; |
28 | 28 |
int num; |
... | ... |
@@ -31,9 +31,9 @@ post_new(kakumei *ka, char *user, char *text) |
31 | 31 |
FILE *f; |
32 | 32 |
struct stat st; |
33 | 33 |
if(ka==NULL || user==NULL || user[0]=='\0' || text==NULL || text[0]=='\0') { |
34 |
- log_write("POST","sanity check error\n"); |
|
34 |
+ log_write("POST","sanity check error\n"); |
|
35 | 35 |
return(-1); |
36 |
- } |
|
36 |
+ } |
|
37 | 37 |
last=post_last(ka); |
38 | 38 |
filename[0]='\0'; |
39 | 39 |
for(num=last+1;num<MAXPOSTS;num++) { |
... | ... |
@@ -43,9 +43,9 @@ post_new(kakumei *ka, char *user, char *text) |
43 | 43 |
break; /* this one is ok: file doesn't exist */ |
44 | 44 |
} |
45 | 45 |
if(filename[0]=='\0' || num>=MAXPOSTS) { |
46 |
- log_write("POST","couldn't generate filename or too many posts\n"); |
|
46 |
+ log_write("POST","couldn't generate filename or too many posts\n"); |
|
47 | 47 |
return(-1); |
48 |
- } |
|
48 |
+ } |
|
49 | 49 |
/* create dir structure */ |
50 | 50 |
mkdir(DATADIR,0700); |
51 | 51 |
mkdir(POSTSDIR,0700); |
... | ... |
@@ -54,11 +54,12 @@ post_new(kakumei *ka, char *user, char *text) |
54 | 54 |
mkdir(dirname,0700); |
55 | 55 |
/* save the new post */ |
56 | 56 |
if((f=fopen(filename,"w"))==NULL) { |
57 |
- log_write("POST","couldn't save post\n"); |
|
57 |
+ log_write("POST","couldn't save post\n"); |
|
58 | 58 |
return(-1); |
59 |
- } |
|
59 |
+ } |
|
60 | 60 |
fprintf(f,"{\n \"author\":\"%s\",\n",user); |
61 | 61 |
fprintf(f," \"date\":%li,\n",(long)time(NULL)); |
62 |
+ fprintf(f," \"title\":\"%s\",\n",title); |
|
62 | 63 |
fprintf(f," \"text\":\"%s\",\n",text); |
63 | 64 |
fprintf(f," \"comments\":[\n]}\n"); |
64 | 65 |
fclose(f),f=NULL; |
... | ... |
@@ -81,9 +82,9 @@ post_last(kakumei *ka) |
81 | 82 |
snprintf(filename,sizeof(filename)-1,"%s/%s",POSTSDIR,"last"); |
82 | 83 |
filename[sizeof(filename)-1]='\0'; |
83 | 84 |
if((fd=open(filename,O_RDONLY))==-1) { |
84 |
- log_write("POST","couldn't get last post number\n"); |
|
85 |
+ log_write("POST","couldn't get last post number\n"); |
|
85 | 86 |
return(-1); |
86 |
- } |
|
87 |
+ } |
|
87 | 88 |
memset(readbuf,0,sizeof(readbuf)); |
88 | 89 |
read(fd,readbuf,sizeof(readbuf)-1); |
89 | 90 |
close(fd),fd=-1; |
... | ... |
@@ -95,15 +96,15 @@ post_get(kakumei *ka, int num, char *filename, int filenamesize) |
95 | 96 |
{ |
96 | 97 |
struct stat st; |
97 | 98 |
if(ka==NULL || num<0 || filename==NULL || filenamesize<=0) { |
98 |
- log_write("POST","Sanity check error\n"); |
|
99 |
+ log_write("POST","Sanity check error\n"); |
|
99 | 100 |
return(-1); |
100 |
- } |
|
101 |
+ } |
|
101 | 102 |
snprintf(filename,filenamesize,"%s/%04i/%04i.json",POSTSDIR,num/10000,num%10000); |
102 | 103 |
filename[filenamesize-1]='\0'; |
103 | 104 |
if(stat(filename,&st)!=0) { |
104 |
- log_write("POST","Post file doesn't exist\n"); |
|
105 |
+ log_write("POST","Post file doesn't exist\n"); |
|
105 | 106 |
return(-1); /* file doesn't exist */ |
106 |
- } |
|
107 |
+ } |
|
107 | 108 |
return(0); |
108 | 109 |
} |
109 | 110 |
|
... | ... |
@@ -114,19 +115,19 @@ post_addcomment(kakumei *ka, int postnum, char *user, char *text) |
114 | 115 |
char buf[16]; |
115 | 116 |
FILE *f; |
116 | 117 |
if(ka==NULL || postnum<0 || user==NULL || text==NULL) { |
117 |
- log_write("POST","Sanity check error\n"); |
|
118 |
+ log_write("POST","Sanity check error\n"); |
|
118 | 119 |
return(-1); |
119 |
- } |
|
120 |
- if(post_get(ka,postnum,filename,sizeof(filename))!=0) |
|
120 |
+ } |
|
121 |
+ if(post_get(ka,postnum,filename,sizeof(filename))!=0) |
|
121 | 122 |
return(-1); |
122 | 123 |
if((f=fopen(filename,"r+"))==NULL) { |
123 |
- log_write("POST","Couldn't open post file fot appending\n"); |
|
124 |
+ log_write("POST","Couldn't open post file fot appending\n"); |
|
124 | 125 |
return(-1); |
125 |
- } |
|
126 |
+ } |
|
126 | 127 |
fseek(f,-2,SEEK_END); |
127 | 128 |
if(fread(buf,1,2,f)!=2 || buf[0]!=']' || buf[1]!='}') { |
128 | 129 |
fclose(f),f=NULL; |
129 |
- log_write("POST","Post file contents are corrupted\n"); |
|
130 |
+ log_write("POST","Post file contents are corrupted\n"); |
|
130 | 131 |
return(-1); |
131 | 132 |
} |
132 | 133 |
fseek(f,-2,SEEK_END); |
... | ... |
@@ -15,6 +15,7 @@ |
15 | 15 |
#include <sys/types.h> |
16 | 16 |
#include <sys/stat.h> |
17 | 17 |
#include <time.h> |
18 |
+#include "loglib.h" |
|
18 | 19 |
#include "kakumei.h" |
19 | 20 |
#include "kakumei_posts.h" |
20 | 21 |
|
... | ... |
@@ -29,8 +30,10 @@ post_new(kakumei *ka, char *user, char *text) |
29 | 30 |
char dirname[1024]; |
30 | 31 |
FILE *f; |
31 | 32 |
struct stat st; |
32 |
- if(ka==NULL || user==NULL || user[0]=='\0' || text==NULL || text[0]=='\0') |
|
33 |
+ if(ka==NULL || user==NULL || user[0]=='\0' || text==NULL || text[0]=='\0') { |
|
34 |
+ log_write("POST","sanity check error\n"); |
|
33 | 35 |
return(-1); |
36 |
+ } |
|
34 | 37 |
last=post_last(ka); |
35 | 38 |
filename[0]='\0'; |
36 | 39 |
for(num=last+1;num<MAXPOSTS;num++) { |
... | ... |
@@ -39,8 +42,10 @@ post_new(kakumei *ka, char *user, char *text) |
39 | 42 |
if(stat(filename,&st)!=0) |
40 | 43 |
break; /* this one is ok: file doesn't exist */ |
41 | 44 |
} |
42 |
- if(filename[0]=='\0' || num>=MAXPOSTS) |
|
45 |
+ if(filename[0]=='\0' || num>=MAXPOSTS) { |
|
46 |
+ log_write("POST","couldn't generate filename or too many posts\n"); |
|
43 | 47 |
return(-1); |
48 |
+ } |
|
44 | 49 |
/* create dir structure */ |
45 | 50 |
mkdir(DATADIR,0700); |
46 | 51 |
mkdir(POSTSDIR,0700); |
... | ... |
@@ -48,12 +53,13 @@ post_new(kakumei *ka, char *user, char *text) |
48 | 53 |
dirname[sizeof(dirname)-1]='\0'; |
49 | 54 |
mkdir(dirname,0700); |
50 | 55 |
/* save the new post */ |
51 |
- if((f=fopen(filename,"w"))==NULL) |
|
56 |
+ if((f=fopen(filename,"w"))==NULL) { |
|
57 |
+ log_write("POST","couldn't save post\n"); |
|
52 | 58 |
return(-1); |
59 |
+ } |
|
53 | 60 |
fprintf(f,"{\n \"author\":\"%s\",\n",user); |
54 | 61 |
fprintf(f," \"date\":%li,\n",(long)time(NULL)); |
55 | 62 |
fprintf(f," \"text\":\"%s\",\n",text); |
56 |
- fprintf(f," \"text\":\"%s\",\n",text); |
|
57 | 63 |
fprintf(f," \"comments\":[\n]}\n"); |
58 | 64 |
fclose(f),f=NULL; |
59 | 65 |
/* save the "last" mark */ |
... | ... |
@@ -74,8 +80,10 @@ post_last(kakumei *ka) |
74 | 80 |
int fd; |
75 | 81 |
snprintf(filename,sizeof(filename)-1,"%s/%s",POSTSDIR,"last"); |
76 | 82 |
filename[sizeof(filename)-1]='\0'; |
77 |
- if((fd=open(filename,O_RDONLY))==-1) |
|
83 |
+ if((fd=open(filename,O_RDONLY))==-1) { |
|
84 |
+ log_write("POST","couldn't get last post number\n"); |
|
78 | 85 |
return(-1); |
86 |
+ } |
|
79 | 87 |
memset(readbuf,0,sizeof(readbuf)); |
80 | 88 |
read(fd,readbuf,sizeof(readbuf)-1); |
81 | 89 |
close(fd),fd=-1; |
... | ... |
@@ -86,12 +94,16 @@ int |
86 | 94 |
post_get(kakumei *ka, int num, char *filename, int filenamesize) |
87 | 95 |
{ |
88 | 96 |
struct stat st; |
89 |
- if(ka==NULL || num<0 || filename==NULL || filenamesize<=0) |
|
97 |
+ if(ka==NULL || num<0 || filename==NULL || filenamesize<=0) { |
|
98 |
+ log_write("POST","Sanity check error\n"); |
|
90 | 99 |
return(-1); |
100 |
+ } |
|
91 | 101 |
snprintf(filename,filenamesize,"%s/%04i/%04i.json",POSTSDIR,num/10000,num%10000); |
92 | 102 |
filename[filenamesize-1]='\0'; |
93 |
- if(stat(filename,&st)!=0) |
|
103 |
+ if(stat(filename,&st)!=0) { |
|
104 |
+ log_write("POST","Post file doesn't exist\n"); |
|
94 | 105 |
return(-1); /* file doesn't exist */ |
106 |
+ } |
|
95 | 107 |
return(0); |
96 | 108 |
} |
97 | 109 |
|
... | ... |
@@ -101,15 +113,20 @@ post_addcomment(kakumei *ka, int postnum, char *user, char *text) |
101 | 113 |
char filename[1024]; |
102 | 114 |
char buf[16]; |
103 | 115 |
FILE *f; |
104 |
- if(ka==NULL || postnum<0 || user==NULL || text==NULL) |
|
116 |
+ if(ka==NULL || postnum<0 || user==NULL || text==NULL) { |
|
117 |
+ log_write("POST","Sanity check error\n"); |
|
105 | 118 |
return(-1); |
106 |
- if(post_get(ka,postnum,filename,sizeof(filename))!=0) |
|
119 |
+ } |
|
120 |
+ if(post_get(ka,postnum,filename,sizeof(filename))!=0) |
|
107 | 121 |
return(-1); |
108 |
- if((f=fopen(filename,"r+"))==NULL) |
|
122 |
+ if((f=fopen(filename,"r+"))==NULL) { |
|
123 |
+ log_write("POST","Couldn't open post file fot appending\n"); |
|
109 | 124 |
return(-1); |
125 |
+ } |
|
110 | 126 |
fseek(f,-2,SEEK_END); |
111 | 127 |
if(fread(buf,1,2,f)!=2 || buf[0]!=']' || buf[1]!='}') { |
112 | 128 |
fclose(f),f=NULL; |
129 |
+ log_write("POST","Post file contents are corrupted\n"); |
|
113 | 130 |
return(-1); |
114 | 131 |
} |
115 | 132 |
fseek(f,-2,SEEK_END); |
1 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,120 @@ |
1 |
+/* |
|
2 |
+ * kakumei_posts.c |
|
3 |
+ * |
|
4 |
+ * Posts management |
|
5 |
+ * |
|
6 |
+ * Author: Dario Rodriguez dario@softhome.net |
|
7 |
+ * This progran 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 <time.h> |
|
18 |
+#include "kakumei.h" |
|
19 |
+#include "kakumei_posts.h" |
|
20 |
+ |
|
21 |
+#define MAXPOSTS 2000000 |
|
22 |
+ |
|
23 |
+int |
|
24 |
+post_new(kakumei *ka, char *user, char *text) |
|
25 |
+{ |
|
26 |
+ int last; |
|
27 |
+ int num; |
|
28 |
+ char filename[1024]; |
|
29 |
+ char dirname[1024]; |
|
30 |
+ FILE *f; |
|
31 |
+ struct stat st; |
|
32 |
+ if(ka==NULL || user==NULL || user[0]=='\0' || text==NULL || text[0]=='\0') |
|
33 |
+ return(-1); |
|
34 |
+ last=post_last(ka); |
|
35 |
+ filename[0]='\0'; |
|
36 |
+ for(num=last+1;num<MAXPOSTS;num++) { |
|
37 |
+ snprintf(filename,sizeof(filename),"%s/%04i/%04i.json",POSTSDIR,num/10000,num%10000); |
|
38 |
+ filename[sizeof(filename)-1]='\0'; |
|
39 |
+ if(stat(filename,&st)!=0) |
|
40 |
+ break; /* this one is ok: file doesn't exist */ |
|
41 |
+ } |
|
42 |
+ if(filename[0]=='\0' || num>=MAXPOSTS) |
|
43 |
+ return(-1); |
|
44 |
+ /* create dir structure */ |
|
45 |
+ mkdir(DATADIR,0700); |
|
46 |
+ mkdir(POSTSDIR,0700); |
|
47 |
+ snprintf(dirname,sizeof(dirname),"%s/%04i",POSTSDIR,num/10000); |
|
48 |
+ dirname[sizeof(dirname)-1]='\0'; |
|
49 |
+ mkdir(dirname,0700); |
|
50 |
+ /* save the new post */ |
|
51 |
+ if((f=fopen(filename,"w"))==NULL) |
|
52 |
+ return(-1); |
|
53 |
+ fprintf(f,"{\n \"author\":\"%s\",\n",user); |
|
54 |
+ fprintf(f," \"date\":%li,\n",(long)time(NULL)); |
|
55 |
+ fprintf(f," \"text\":\"%s\",\n",text); |
|
56 |
+ fprintf(f," \"text\":\"%s\",\n",text); |
|
57 |
+ fprintf(f," \"comments\":[\n]}\n"); |
|
58 |
+ fclose(f),f=NULL; |
|
59 |
+ /* save the "last" mark */ |
|
60 |
+ snprintf(filename,sizeof(filename)-1,"%s/%s",POSTSDIR,"last"); |
|
61 |
+ filename[sizeof(filename)-1]='\0'; |
|
62 |
+ if((f=fopen(filename,"w"))!=NULL) { |
|
63 |
+ fprintf(f,"%i",num); |
|
64 |
+ fclose(f),f=NULL; |
|
65 |
+ } |
|
66 |
+ return(0); |
|
67 |
+} |
|
68 |
+ |
|
69 |
+int |
|
70 |
+post_last(kakumei *ka) |
|
71 |
+{ |
|
72 |
+ char readbuf[128]; |
|
73 |
+ char filename[1024]; |
|
74 |
+ int fd; |
|
75 |
+ snprintf(filename,sizeof(filename)-1,"%s/%s",POSTSDIR,"last"); |
|
76 |
+ filename[sizeof(filename)-1]='\0'; |
|
77 |
+ if((fd=open(filename,O_RDONLY))==-1) |
|
78 |
+ return(-1); |
|
79 |
+ memset(readbuf,0,sizeof(readbuf)); |
|
80 |
+ read(fd,readbuf,sizeof(readbuf)-1); |
|
81 |
+ close(fd),fd=-1; |
|
82 |
+ return(atoi(readbuf)); |
|
83 |
+} |
|
84 |
+ |
|
85 |
+int |
|
86 |
+post_get(kakumei *ka, int num, char *filename, int filenamesize) |
|
87 |
+{ |
|
88 |
+ struct stat st; |
|
89 |
+ if(ka==NULL || num<0 || filename==NULL || filenamesize<=0) |
|
90 |
+ return(-1); |
|
91 |
+ snprintf(filename,filenamesize,"%s/%04i/%04i.json",POSTSDIR,num/10000,num%10000); |
|
92 |
+ filename[filenamesize-1]='\0'; |
|
93 |
+ if(stat(filename,&st)!=0) |
|
94 |
+ return(-1); /* file doesn't exist */ |
|
95 |
+ return(0); |
|
96 |
+} |
|
97 |
+ |
|
98 |
+int |
|
99 |
+post_addcomment(kakumei *ka, int postnum, char *user, char *text) |
|
100 |
+{ |
|
101 |
+ char filename[1024]; |
|
102 |
+ char buf[16]; |
|
103 |
+ FILE *f; |
|
104 |
+ if(ka==NULL || postnum<0 || user==NULL || text==NULL) |
|
105 |
+ return(-1); |
|
106 |
+ if(post_get(ka,postnum,filename,sizeof(filename))!=0) |
|
107 |
+ return(-1); |
|
108 |
+ if((f=fopen(filename,"r+"))==NULL) |
|
109 |
+ return(-1); |
|
110 |
+ fseek(f,-2,SEEK_END); |
|
111 |
+ if(fread(buf,1,2,f)!=2 || buf[0]!=']' || buf[1]!='}') { |
|
112 |
+ fclose(f),f=NULL; |
|
113 |
+ return(-1); |
|
114 |
+ } |
|
115 |
+ fseek(f,-2,SEEK_END); |
|
116 |
+ fprintf(f," { \"author\":\"%s\",\"date\":%li,\"text\":\"%s\"},\n]}",user,(long)time(NULL),text); |
|
117 |
+ fclose(f),f=NULL; |
|
118 |
+ return(0); |
|
119 |
+} |
|
120 |
+ |