1 /*****************************************************************************
2 * HPT --- FTN NetMail/EchoMail Tosser
3 *****************************************************************************
4 *
5 * hpt-to-libareafix interface by val khokhlov, 2:550/180@fidonet
6 *
7 * This file is part of HPT.
8 *
9 * HPT is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2, or (at your option) any
12 * later version.
13 *
14 * HPT is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with HPT; see the file COPYING. If not, write to the Free
21 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *****************************************************************************/
23 /* $Id$ */
24
25 #include <string.h>
26 #include <huskylib/xstr.h>
27 #include <smapi/msgapi.h>
28 #include <fidoconf/fidoconf.h>
29 #include <fidoconf/common.h>
30 #include <fidoconf/afixcmd.h>
31 #include <areafix/areafix.h>
32 #include <areafix/afglobal.h>
33 #include <areafix/callback.h>
34 #include <areafix/query.h>
35 #include "global.h"
36 #include "fcommon.h"
37 #include "hpt.h"
38 #include "dupe.h"
39 #include "scanarea.h"
40 #include "toss.h"
41 #ifdef DO_PERL
42 #include "hptperl.h"
43 #endif
44
45 extern s_message **msgToSysop;
46
afGetArea(char * areaName)47 s_area *afGetArea(char *areaName) {
48 s_area *area = getArea(config, areaName);
49 return area != &(config->badArea) ? area : NULL;
50 }
51
afIsValidConference(const char * s)52 int afIsValidConference(const char *s) {
53 if (!s || strlen(s) > 60) return BM_AREATAG_TOO_LONG;
54 /* according to FSC-0074 with lowercase symbols */
55 /* lowercase symbols only for internal use */
56 while (*s) {
57 if ( !(*s >= 33 && *s <= 126) ) return BM_ILLEGAL_CHARS;
58 s++;
59 }
60 return 0;
61 }
62
afSendMsg(s_message * tmpmsg)63 int afSendMsg(s_message *tmpmsg) {
64 processNMMsg(tmpmsg, NULL, getRobotsArea(config), 0, MSGLOCAL);
65 writeEchoTossLogEntry(getRobotsArea(config)->areaName);
66 closeOpenedPkt();
67 freeMsgBuffers(tmpmsg);
68 return 1;
69 }
70
afWriteMsgToSysop(s_message * msg)71 int afWriteMsgToSysop(s_message *msg) {
72 msgToSysop[0] = msg;
73 writeMsgToSysop();
74 freeMsgBuffers(msg);
75 msgToSysop[0] = NULL;
76 return 1;
77 }
78
afReportAutoCreate(char * c_area,char * descr,hs_addr pktOrigAddr,ps_addr forwardAddr)79 void afReportAutoCreate(char *c_area, char *descr, hs_addr pktOrigAddr, ps_addr forwardAddr) {
80 unused(descr);
81 #if 0 /* val: don't know why is was here; so trying to fix */
82 if (forwardAddr == NULL) makeMsgToSysop(c_area, pktOrigAddr, NULL);
83 else makeMsgToSysop(c_area, *forwardAddr, &pktOrigAddr);
84 #else
85 makeMsgToSysop(c_area, pktOrigAddr, forwardAddr);
86 #endif
87 }
88
afDeleteArea(s_link * link,s_area * area)89 int afDeleteArea(s_link *link, s_area *area) {
90
91 unused(link);
92
93 if (area->dupeCheck != dcOff && config->typeDupeBase != commonDupeBase) {
94 char *dupename = createDupeFileName(area);
95 if (dupename) {
96 unlink(dupename);
97 nfree(dupename);
98 }
99 }
100 return 1;
101 }
102
afRescanArea(char ** report,s_link * link,s_area * area,long rescanCount,long rescanAfter)103 int afRescanArea(char **report, s_link *link, s_area *area, long rescanCount, long rescanAfter) {
104 char *an = area->areaName;
105 s_arealink *arealink;
106 long rcc = 0;
107
108 arealink = getAreaLink(area, link->hisAka);
109
110 if ((area->msgbType == MSGTYPE_PASSTHROUGH) || (!arealink->rescan)) {
111 xscatprintf(report," %s %s no rescan possible\r",
112 an, print_ch(49-strlen(an), '.'));
113 w_log(LL_AREAFIX, "areafix: %s area no rescan possible to %s",
114 an, aka2str(link->hisAka));
115 } else {
116 if (link->rescanLimit) {
117 if (rescanCount < 0 || rescanCount > link->rescanLimit)
118 rescanCount = link->rescanLimit;
119 }
120 if (arealink->aexport) {
121 rcc = rescanEMArea(area, arealink, rescanCount, rescanAfter);
122 tossTempOutbound(config->tempOutbound);
123 } else {
124 rcc = 0;
125 xscatprintf(report," %s %s no access to export\r",
126 an, print_ch(49-strlen(an), '.'));
127 w_log(LL_AREAFIX, "areafix: %s -- no access to export for %s",
128 an, aka2str(link->hisAka));
129 }
130 xscatprintf(report," %s %s rescanned %lu mails\r",
131 an, print_ch(49-strlen(an), '.'), rcc);
132 w_log(LL_AREAFIX,"areafix: %s rescanned %lu mails to %s",
133 an, rcc, aka2str(link->hisAka));
134 }
135 return rcc;
136 }
137
getLinkRobot(s_link * link)138 s_link_robot *getLinkRobot(s_link *link) {
139 return &(link->areafix);
140 }
141
autoPassive()142 void autoPassive()
143 {
144 time_t time_cur, time_test;
145 struct stat stat_file;
146 s_message *msg;
147 FILE *f;
148 char *line, *path;
149 unsigned int i, rc = 0;
150
151 for (i = 0; i < config->linkCount; i++) {
152
153 if (config->links[i]->autoPause==0 || (config->links[i]->Pause == (ECHOAREA|FILEAREA))
154 ) continue;
155
156 if (createOutboundFileName(config->links[i],
157 config->links[i]->echoMailFlavour,
158 FLOFILE) == 0) {
159 f = fopen(config->links[i]->floFile, "rt");
160 if (f) {
161 while ((line = readLine(f)) != NULL) {
162 line = trimLine(line);
163 path = line;
164 if (!isArcMail(path)) {
165 nfree(line);
166 continue;
167 }
168 if (*path && (*path == '^' || *path == '#')) {
169 path++;
170 /* set Pause if files stored only in outbound */
171 if (*path && strncmp(config->outbound,path,strlen(config->outbound)-1)==0 && stat(path, &stat_file) != -1) {
172
173 time_cur = time(NULL);
174 if (time_cur > stat_file.st_mtime) {
175 time_test = (time_cur - stat_file.st_mtime)/3600;
176 } else { /* buggly time on file, anyway don't autopause on it */
177 time_test = 0;
178 }
179
180 if (time_test >= (time_t)(config->links[i]->autoPause*24)) {
181 w_log(LL_AREAFIX, "autopause: the file %s is %d days old", path, time_test/24);
182 if (Changepause((cfgFile) ? cfgFile :
183 getConfigFileName(),
184 config->links[i], 1,
185 config->links[i]->Pause^(ECHOAREA|FILEAREA))) {
186 UINT j, k;
187 int mask = config->links[i]->areafix.reportsAttr ? config->links[i]->areafix.reportsAttr : robot->reportsAttr;
188 msg = makeMessage(config->links[i]->ourAka,
189 &(config->links[i]->hisAka),
190 robot->fromName ? robot->fromName : versionStr,
191 config->links[i]->name,
192 "AutoPassive", 1,
193 MSGPRIVATE | MSGLOCAL | (mask & (MSGKILL|MSGCPT)) );
194 msg->text = createKludges(config, NULL,
195 config->links[i]->ourAka,
196 &(config->links[i]->hisAka),
197 versionStr);
198 xstrcat(&msg->text, "\r System switched to passive, your subscription is paused.\r\r"
199 " You are being unsubscribed from echo areas with no downlinks besides you!\r\r"
200 " When you wish to continue receiving echomail, please send requests\r"
201 " to AreaFix containing the %RESUME command.");
202 xscatprintf(&msg->text, "\r\r--- %s autopause\r", versionStr);
203 msg->textLength = strlen(msg->text);
204 #ifdef DO_PERL
205 perl_robotmsg(msg, robot->name);
206 #endif
207 processNMMsg(msg, NULL, getRobotsArea(config), 0, MSGLOCAL);
208 writeEchoTossLogEntry(getRobotsArea(config)->areaName);
209 closeOpenedPkt();
210 freeMsgBuffers(msg);
211 nfree(msg);
212
213 /* update arealink access */
214 for (k = 0; k < config->echoAreaCount; k++)
215 for (j = 0; j < config->echoAreas[k].downlinkCount; j++)
216 if (config->links[i] == config->echoAreas[k].downlinks[j]->link)
217 {
218 setLinkAccess(config, &(config->echoAreas[k]), config->echoAreas[k].downlinks[j]);
219 break;
220 }
221
222 /* pause areas with one link alive while others are paused */
223 if (robot->autoAreaPause)
224 rc += pauseArea(ACT_PAUSE, config->links[i], NULL);
225 #ifdef DO_PERL
226 /* update perl vars */
227 perl_invalidate(PERL_CONF_LINKS|PERL_CONF_AREAS);
228 #endif
229 } /* end changepause */
230 nfree(line);
231 /* fclose(f); file closed after endwhile */
232 break;
233 }
234 } /* endif */
235 } /* endif ^# */
236 nfree(line);
237 } /* endwhile */
238 fclose(f);
239 } /* endif */
240 nfree(config->links[i]->floFile);
241 remove(config->links[i]->bsyFile);
242 nfree(config->links[i]->bsyFile);
243 }
244 nfree(config->links[i]->pktFile);
245 nfree(config->links[i]->packFile);
246 } /* endfor */
247
248 /* send created messages to links */
249 if (rc) sendAreafixMessages();
250 }
251
init_hptafix(void)252 int init_hptafix(void) {
253 /* vars */
254 af_config = config;
255 af_cfgFile = cfgFile;
256 af_app = &theApp;
257 af_versionStr = versionStr;
258 af_quiet = quiet;
259 af_silent_mode = silent_mode;
260 af_report_changes = report_changes;
261 af_send_notify = cmNotifyLink;
262 af_pause = ECHOAREA;
263 /* callbacks and hooks */
264 call_sstrdup = &safe_strdup;
265 call_smalloc = &safe_malloc;
266 call_srealloc = &safe_realloc;
267
268 call_getArea = &afGetArea;
269 call_isValid = &afIsValidConference;
270 call_sendMsg = &afSendMsg;
271 call_writeMsgToSysop = &afWriteMsgToSysop;
272 call_getLinkRobot = &getLinkRobot;
273 hook_onDeleteArea = &afDeleteArea;
274 hook_onRescanArea = &afRescanArea;
275 hook_onAutoCreate = &afReportAutoCreate;
276 #ifdef DO_PERL
277 hook_onConfigChange = &perl_invalidate;
278 hook_echolist = &perl_echolist;
279 hook_afixcmd = &perl_afixcmd;
280 hook_afixreq = &perl_afixreq;
281 hook_robotmsg = &perl_robotmsg;
282 #endif
283 robot = getRobot(config, "areafix", 0); /* !!! val: change this later !!! */
284 return init_areafix("areafix");
285 }
286