81a54b573914d230981ad2c063e5571ffff9f2b5
[citadel.git] / citadel / modules / bio / serv_bio.c
1 /*
2  * This module implementsserver commands related to the display and
3  * manipulation of user "bio" files.
4  *
5  * Copyright (c) 1987-2015 by the citadel.org team
6  *
7  * This program is open source software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  */
17
18 #include "ctdl_module.h"
19 #include "config.h"
20
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <dirent.h>
24
25
26 /*
27  * enter user bio
28  */
29 void cmd_ebio(char *cmdbuf) {
30         char buf[SIZ];
31         FILE *fp;
32
33         unbuffer_output();
34
35         if (!(CC->logged_in)) {
36                 cprintf("%d Not logged in.\n",ERROR + NOT_LOGGED_IN);
37                 return;
38         }
39
40         snprintf(buf, sizeof buf, "%s%ld",ctdl_bio_dir,CC->user.usernum);
41         fp = fopen(buf,"w");
42         if (fp == NULL) {
43                 cprintf("%d Cannot create file: %s\n", ERROR + INTERNAL_ERROR,
44                                 strerror(errno));
45                 return;
46         }
47         cprintf("%d  \n",SEND_LISTING);
48         while(client_getln(buf, sizeof buf) >= 0 && strcmp(buf,"000")) {
49                 if (ftell(fp) < CtdlGetConfigLong("c_maxmsglen")) {
50                         fprintf(fp,"%s\n",buf);
51                 }
52         }
53         fclose(fp);
54 }
55
56 /*
57  * read user bio
58  */
59 void cmd_rbio(char *cmdbuf)
60 {
61         struct ctdluser ruser;
62         char buf[256];
63         FILE *fp;
64
65         extract_token(buf, cmdbuf, 0, '|', sizeof buf);
66         if (CtdlGetUser(&ruser, buf) != 0) {
67                 cprintf("%d No such user.\n",ERROR + NO_SUCH_USER);
68                 return;
69         }
70         snprintf(buf, sizeof buf, "%s%ld",ctdl_bio_dir,ruser.usernum);
71         
72         cprintf("%d OK|%s|%ld|%d|%ld|%ld|%ld\n", LISTING_FOLLOWS,
73                 ruser.fullname, ruser.usernum, ruser.axlevel,
74                 (long)ruser.lastcall, ruser.timescalled, ruser.posted);
75         fp = fopen(buf,"r");
76         if (fp == NULL)
77                 cprintf("%s has no bio on file.\n", ruser.fullname);
78         else {
79                 while (fgets(buf, sizeof buf, fp) != NULL) cprintf("%s",buf);
80                 fclose(fp);
81         }
82         cprintf("000\n");
83 }
84
85 /*
86  * list of users who have entered bios
87  */
88 void cmd_lbio(char *cmdbuf)
89 {
90         DIR *filedir = NULL;
91         struct dirent *filedir_entry;
92         struct dirent *d;
93         int dont_resolve_uids;
94         size_t d_namelen;
95         struct ctdluser usbuf;
96         int d_type = 0;
97
98
99         d = (struct dirent *)malloc(offsetof(struct dirent, d_name) + PATH_MAX + 2);
100         if (d == NULL) {
101                 cprintf("%d Cannot open listing.\n", ERROR + FILE_NOT_FOUND);
102                 return;
103         }
104
105         filedir = opendir (ctdl_bio_dir);
106         if (filedir == NULL) {
107                 free(d);
108                 cprintf("%d Cannot open listing.\n", ERROR + FILE_NOT_FOUND);
109                 return;
110         }
111         dont_resolve_uids = *cmdbuf == '1';
112         cprintf("%d\n", LISTING_FOLLOWS);
113         while ((readdir_r(filedir, d, &filedir_entry) == 0) &&
114                (filedir_entry != NULL))
115         {
116 #ifdef _DIRENT_HAVE_D_NAMLEN
117                 d_namelen = filedir_entry->d_namlen;
118
119 #else
120                 d_namelen = strlen(filedir_entry->d_name);
121 #endif
122
123 #ifdef _DIRENT_HAVE_D_TYPE
124                 d_type = filedir_entry->d_type;
125 #else
126
127 #ifndef DT_UNKNOWN
128 #define DT_UNKNOWN     0
129 #define DT_DIR         4
130 #define DT_REG         8
131 #define DT_LNK         10
132
133 #define IFTODT(mode)   (((mode) & 0170000) >> 12)
134 #define DTTOIF(dirtype)        ((dirtype) << 12)
135 #endif
136                 d_type = DT_UNKNOWN;
137 #endif
138                 if ((d_namelen == 1) && 
139                     (filedir_entry->d_name[0] == '.'))
140                         continue;
141
142                 if ((d_namelen == 2) && 
143                     (filedir_entry->d_name[0] == '.') &&
144                     (filedir_entry->d_name[1] == '.'))
145                         continue;
146
147                 if (d_type == DT_UNKNOWN) {
148                         struct stat s;
149                         char path[PATH_MAX];
150                         snprintf(path, PATH_MAX, "%s/%s", 
151                                  ctdl_bio_dir, filedir_entry->d_name);
152                         if (lstat(path, &s) == 0) {
153                                 d_type = IFTODT(s.st_mode);
154                         }
155                 }
156                 switch (d_type)
157                 {
158                 case DT_DIR:
159                         break;
160                 case DT_LNK:
161                 case DT_REG:
162                         if (dont_resolve_uids) {
163                                 filedir_entry->d_name[d_namelen++] = '\n';
164                                 filedir_entry->d_name[d_namelen] = '\0';
165                                 client_write(filedir_entry->d_name, d_namelen);
166                         }
167                         else if (CtdlGetUserByNumber(&usbuf,atol(filedir_entry->d_name))==0)
168                                 cprintf("%s\n", usbuf.fullname);
169                 }
170         }
171         free(d);
172         closedir(filedir);
173         cprintf("000\n");
174
175 }
176
177
178
179 CTDL_MODULE_INIT(bio)
180 {
181         if (!threading)
182         {
183                 CtdlRegisterProtoHook(cmd_ebio, "EBIO", "Enter your bio");
184                 CtdlRegisterProtoHook(cmd_rbio, "RBIO", "Read a user's bio");
185                 CtdlRegisterProtoHook(cmd_lbio, "LBIO", "List users with bios");
186         }
187         /* return our module name for the log */
188         return "bio";
189 }
190
191