|
|
1.1 root 1: /* sbbs.h */
2:
3: /* Synchronet class (sbbs_t) definition and exported function prototypes */
4:
5: /* $Id: sbbs.h,v 1.289 2006/12/29 08:41:50 rswindell Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #ifndef _SBBS_H
39: #define _SBBS_H
40:
41: /****************************/
42: /* Standard library headers */
43: /****************************/
44:
45: /***************/
46: /* OS-specific */
47: /***************/
48: #if defined(_WIN32) /* Windows */
49:
50: #define NOCRYPT /* Stop windows.h from loading wincrypt.h */
51: /* Is windows.h REALLY necessary?!?! */
52: #define WIN32_LEAN_AND_MEAN
53: #include <io.h>
54: #include <share.h>
55: #include <windows.h>
56: #include <process.h> /* _beginthread() prototype */
57: #include <direct.h> /* _mkdir() prototype */
58: #include <mmsystem.h> /* SND_ASYNC */
59:
60: #if defined(_DEBUG) && defined(_MSC_VER)
61: #include <crtdbg.h> /* Windows debug macros and stuff */
62: #endif
63:
64: #if defined(__cplusplus)
65: extern "C"
66: #endif
67: extern HINSTANCE hK32;
68:
69: #elif defined(__unix__) /* Unix-variant */
70:
71: #include <unistd.h> /* close */
72:
73: #endif
74:
75: #ifdef _THREAD_SUID_BROKEN
76: extern int thread_suid_broken; /* NPTL is no longer broken */
77: #else
78: #define thread_suid_broken FALSE
79: #endif
80:
81: /******************/
82: /* ANSI C Library */
83: /******************/
84: #include <time.h>
85: #include <errno.h>
86: #include <stdio.h>
87: #include <ctype.h>
88: #include <fcntl.h> /* open */
89: #include <stdarg.h>
90: #include <stdlib.h>
91: #include <string.h>
92:
93: #ifndef __unix__
94:
95: #include <malloc.h>
96:
97: #endif
98:
99: #include <sys/stat.h>
100:
101: #ifdef JAVASCRIPT
102: #ifdef __unix__
103: #define XP_UNIX
104: #else
105: #define XP_PC
106: #define XP_WIN
107: #endif
108: #define JS_THREADSAFE /* Required! */
109: #include <jsapi.h>
110: #include <jsprf.h> /* JS-safe sprintf functions */
111: #include <jsnum.h> /* JSDOUBLE_IS_NaN() */
112:
113: #endif
114:
115: #ifdef USE_CRYPTLIB
116: #include <cryptlib.h>
117: #endif
118:
119: /***********************/
120: /* Synchronet-specific */
121: /***********************/
122: #ifdef __cplusplus
123: #include "startup.h"
124: #include "threadwrap.h" /* pthread_mutex_t */
125: #endif
126: #ifdef SBBS
127: #include "text.h"
128: #endif
129:
130: /* xpdev */
131: #ifndef LINK_LIST_THREADSAFE
132: #define LINK_LIST_THREADSAFE
133: #endif
134: #include "genwrap.h"
135: #include "semfile.h"
136: #include "dirwrap.h"
137: #include "filewrap.h"
138: #include "sockwrap.h"
139: #include "link_list.h"
140: #include "msg_queue.h"
141:
142: #include "smblib.h"
143: #include "ars_defs.h"
144: #include "scfgdefs.h"
145: #include "scfglib.h"
146: #include "userdat.h"
147: #include "riodefs.h"
148: #include "cmdshell.h"
149: #include "ringbuf.h" /* RingBuf definition */
150: #include "client.h" /* client_t definition */
151: #include "crc16.h"
152: #include "crc32.h"
153: #include "telnet.h"
154: #include "nopen.h"
155:
156: /* Synchronet Node Instance class definition */
157: #ifdef __cplusplus
158: class sbbs_t
159: {
160:
161: public:
162:
163: sbbs_t(ushort node_num, DWORD addr, char* host_name, SOCKET
164: ,scfg_t*, char* text[], client_t* client_info);
165: ~sbbs_t();
166:
167: bbs_startup_t* startup;
168:
169: bool init(void);
170: BOOL terminated;
171:
172: client_t client;
173: SOCKET client_socket;
174: SOCKET client_socket_dup;
175: DWORD client_addr;
176: char client_name[128];
177: char client_ident[128];
178: DWORD local_addr;
179: #ifdef USE_CRYPTLIB
180: CRYPT_SESSION ssh_session;
181: bool ssh_mode;
182: SOCKET passthru_socket;
183: bool passthru_output_thread_running;
184: bool passthru_input_thread_running;
185: #endif
186:
187: scfg_t cfg;
188:
189: int outchar_esc; // track ANSI escape seq output
190:
191: int rioctl(ushort action); // remote i/o control
192: bool rio_abortable;
193:
194: RingBuf inbuf;
195: RingBuf outbuf;
196: HANDLE input_thread;
197: pthread_mutex_t input_thread_mutex;
198: bool input_thread_mutex_locked; // by someone other than the input_thread
199:
200: int outcom(uchar ch); // send character
201: int incom(unsigned long timeout=0); // receive character
202:
203: void spymsg(char *msg); // send message to active spies
204:
205: void putcom(char *str, int len=0); // Send string
206: void hangup(void); // Hangup modem
207:
208: uchar telnet_local_option[0x100];
209: uchar telnet_remote_option[0x100];
210: void send_telnet_cmd(uchar cmd, uchar opt);
211: void request_telnet_opt(uchar cmd, uchar opt);
212:
213: uchar telnet_cmd[64];
214: uint telnet_cmdlen;
215: ulong telnet_mode;
216: uchar telnet_last_rxch;
217: char terminal[TELNET_TERM_MAXLEN+1];
218:
219: time_t event_time; // Time of next exclusive event
220: char* event_code; // Internal code of next exclusive event
221: bool event_thread_running;
222: bool output_thread_running;
223: bool input_thread_running;
224:
225: #ifdef JAVASCRIPT
226:
227: JSRuntime* js_runtime;
228: JSContext* js_cx;
229: JSObject* js_glob;
230: js_branch_t js_branch;
231: long js_execfile(const char *fname);
232: bool js_init(ulong* stack_frame);
233: void js_create_user_objects(void);
234:
235: #endif
236:
237: char menu_dir[128]; /* Over-ride default menu dir */
238: char menu_file[128]; /* Over-ride menu file */
239:
240: user_t useron; /* User currently online */
241: node_t thisnode; /* Node information */
242: smb_t smb; /* Currently open message base */
243: char rlogin_name[LEN_ALIAS+1];
244: char rlogin_pass[LEN_PASS+1];
245:
246: uint temp_dirnum;
247:
248: FILE *nodefile_fp,
249: *node_ext_fp,
250: *logfile_fp;
251:
252: int nodefile; /* File handle for node.dab */
253: int node_ext; /* File handle for node.exb */
254: int inputfile; /* File handle to use for input */
255:
256: /* Batch download queue */
257: char **batdn_name; /* Filenames */
258: ushort *batdn_alt; /* Alternate path */
259: uint *batdn_dir, /* Directory for each file */
260: batdn_total; /* Total files */
261: long *batdn_offset; /* Offset for data */
262: ulong *batdn_size; /* Size of file in bytes */
263: ulong *batdn_cdt; /* Credit value of file */
264:
265: /* Batch upload queue */
266: char **batup_desc, /* Description for each file */
267: **batup_name; /* Filenames */
268: long *batup_misc; /* Miscellaneous bits */
269: ushort *batup_alt; /* Alternate path */
270: uint *batup_dir, /* Directory for each file */
271: batup_total; /* Total files */
272:
273: /*********************************/
274: /* Color Configuration Variables */
275: /*********************************/
276: char *text[TOTAL_TEXT]; /* Text from ctrl\text.dat */
277: char *text_sav[TOTAL_TEXT]; /* Text from ctrl\text.dat */
278: char dszlog[127]; /* DSZLOG enviornment variable */
279: int keybuftop,keybufbot; /* Keyboard input buffer pointers (for ungetkey) */
280: char keybuf[KEY_BUFSIZE]; /* Keyboard input buffer */
281: char * connection; /* Connection Description */
282: ulong cur_rate; /* Current Connection (DCE) Rate */
283: ulong cur_cps; /* Current Average Transfer CPS */
284: ulong dte_rate; /* Current COM Port (DTE) Rate */
285: time_t timeout; /* User inactivity timeout reference */
286: ulong timeleft_warn; /* low timeleft warning flag */
287: uchar curatr; /* Current Text Attributes Always */
288: uchar attr_stack[64]; /* Saved attributes (stack) */
289: int attr_sp; /* Attribute stack pointer */
290: long lncntr; /* Line Counter - for PAUSE */
291: long tos; /* Top of Screen */
292: long rows; /* Current number of Rows for User */
293: long cols; /* Current number of Columns for User */
294: long autoterm; /* Autodetected terminal type */
295: char slbuf[SAVE_LINES][LINE_BUFSIZE+1]; /* Saved for redisplay */
296: char slatr[SAVE_LINES]; /* Starting attribute of each line */
297: char slcuratr[SAVE_LINES]; /* Ending attribute of each line */
298: int slcnt; /* Number of lines currently saved */
299: char lbuf[LINE_BUFSIZE+1];/* Temp storage for each line output */
300: int lbuflen; /* Number of characters in line buffer */
301: char latr; /* Starting attribute of line buffer */
302: ulong console; /* Defines current Console settings */
303: char wordwrap[81]; /* Word wrap buffer */
304: time_t now, /* Used to store current time in Unix format */
305: answertime, /* Time call was answered */
306: logontime, /* Time user logged on */
307: starttime, /* Time stamp to use for time left calcs */
308: ns_time, /* File new-scan time */
309: last_ns_time; /* Most recent new-file-scan this call */
310: uchar action; /* Current action of user */
311: long online; /* Remote/Local or not online */
312: long sys_status; /* System Status */
313: subscan_t *subscan; /* User sub configuration/scan info */
314:
315: ulong logon_ulb, /* Upload Bytes This Call */
316: logon_dlb, /* Download Bytes This Call */
317: logon_uls, /* Uploads This Call */
318: logon_dls, /* Downloads This Call */
319: logon_posts, /* Posts This Call */
320: logon_emails, /* Emails This Call */
321: logon_fbacks; /* Feedbacks This Call */
322: uchar logon_ml; /* ML of the user upon logon */
323:
324: uint main_cmds; /* Number of Main Commands this call */
325: uint xfer_cmds; /* Number of Xfer Commands this call */
326: ulong posts_read; /* Number of Posts read this call */
327: char temp_uler[31]; /* User who uploaded the files to temp dir */
328: char temp_file[41]; /* Origin of extracted temp files */
329: long temp_cdt; /* Credit value of file that was extracted */
330: char autohang; /* Used for auto-hangup after transfer */
331: size_t logcol; /* Current column of log file */
332: uint criterrs; /* Critical error counter */
333:
334: uint curgrp; /* Current group */
335: uint *cursub; /* Current sub-board for each group */
336: uint curlib; /* Current library */
337: uint *curdir; /* Current directory for each library */
338: uint *usrgrp; /* Real group numbers */
339: uint usrgrps; /* Number groups this user has access to */
340: uint usrgrp_total; /* Total number of groups */
341: uint *usrlib; /* Real library numbers */
342: uint usrlibs; /* Number of libs this user can access */
343: uint usrlib_total; /* Total number of libraries */
344: uint **usrsub; /* Real sub numbers */
345: uint *usrsubs; /* Num of subs with access for each grp */
346: uint **usrdir; /* Real dir numbers */
347: uint *usrdirs; /* Num of dirs with access for each lib */
348: uint cursubnum; /* For ARS */
349: uint curdirnum; /* For ARS */
350: ulong timeleft; /* Number of seconds user has left online */
351:
352: char *comspec; /* Pointer to environment variable COMSPEC */
353: ushort altul; /* Upload to alternate path flag */
354: char cid[LEN_CID+1]; /* Caller ID (IP Address) of current caller */
355: char *noaccess_str; /* Why access was denied via ARS */
356: long noaccess_val; /* Value of parameter not met in ARS */
357: int errorlevel; /* Error level of external program */
358:
359: csi_t main_csi; /* Main Command Shell Image */
360:
361: smbmsg_t* current_msg; /* For message header @-codes */
362:
363: /* Global command shell variables */
364: uint global_str_vars;
365: char ** global_str_var;
366: long * global_str_var_name;
367: uint global_int_vars;
368: long * global_int_var;
369: long * global_int_var_name;
370: char * sysvar_p[MAX_SYSVARS];
371: uint sysvar_pi;
372: long sysvar_l[MAX_SYSVARS];
373: uint sysvar_li;
374:
375: /* ansi_term.cpp */
376: char * ansi(int atr); /* Returns ansi escape sequence for atr */
377: bool ansi_getxy(int* x, int* y);
378: void ansi_getlines(void);
379:
380: /* Command Shell Methods */
381: int exec(csi_t *csi);
382: int exec_function(csi_t *csi);
383: int exec_misc(csi_t *csi, char *path);
384: int exec_net(csi_t *csi);
385: int exec_msg(csi_t *csi);
386: int exec_file(csi_t *csi);
387: long exec_bin(const char *mod, csi_t *csi);
388: void clearvars(csi_t *bin);
389: void freevars(csi_t *bin);
390: char** getstrvar(csi_t *bin, long name);
391: long* getintvar(csi_t *bin, long name);
392: char* copystrvar(csi_t *csi, char *p, char *str);
393: void skipto(csi_t *csi, uchar inst);
394: bool ftp_cmd(csi_t* csi, SOCKET ctrl_sock, char* cmdsrc, char* rsp);
395: bool ftp_put(csi_t* csi, SOCKET ctrl_sock, char* src, char* dest);
396: bool ftp_get(csi_t* csi, SOCKET ctrl_sock, char* src, char* dest, bool dir=false);
397: SOCKET ftp_data_sock(csi_t* csi, SOCKET ctrl_sock, SOCKADDR_IN*);
398:
399: bool select_shell(void);
400: bool select_editor(void);
401:
402: void sys_info(void);
403: void user_info(void);
404: void xfer_policy(void);
405:
406: void xfer_prot_menu(enum XFER_TYPE);
407: void node_stats(uint node_num);
408: void sys_stats(void);
409: void logonlist(void);
410: bool spy(uint node_num);
411:
412: void reset_logon_vars(void);
413:
414: uint finduser(char *str);
415:
416: int sub_op(uint subnum);
417: ulong getlastmsg(uint subnum, ulong *ptr, time_t *t);
418: time_t getmsgtime(uint subnum, ulong ptr);
419: ulong getmsgnum(uint subnum, time_t t);
420:
421: int dir_op(uint dirnum);
422: int getuserxfers(int fromuser, int destuser, char *fname);
423:
424: void getmsgptrs(void);
425: void putmsgptrs(void);
426: void getusrsubs(void);
427: void getusrdirs(void);
428: uint getusrsub(uint subnum);
429: uint getusrgrp(uint subnum);
430:
431: uint userdatdupe(uint usernumber, uint offset, uint datlen, char *dat
432: ,bool del);
433: void gettimeleft(void);
434: bool gettimeleft_inside;
435:
436: /* str.cpp */
437: char* timestr(time_t *intime);
438: char timestr_output[60];
439: void userlist(long mode);
440: size_t gettmplt(char *outstr, char *tmplt, long mode);
441: void sif(char *fname, char *answers, long len); /* Synchronet Interface File */
442: void sof(char *fname, char *answers, long len);
443: void create_sif_dat(char *siffile, char *datfile);
444: void read_sif_dat(char *siffile, char *datfile);
445: void printnodedat(uint number, node_t* node);
446: bool inputnstime(time_t *dt);
447: bool chkpass(char *pass, user_t* user, bool unique);
448: char * cmdstr(char *instr, char *fpath, char *fspec, char *outstr);
449: char cmdstr_output[512];
450:
451: void subinfo(uint subnum);
452: void dirinfo(uint dirnum);
453: bool trashcan(char *insearch, char *name);
454: void time_bank(void);
455: void change_user(void);
456:
457: /* writemsg.cpp */
458: void automsg(void);
459: bool writemsg(char *str, char *top, char *title, long mode, int subnum
460: ,char *dest);
461: char* msg_tmp_fname(int xedit, char* fname, size_t len);
462: char putmsg(char *str, long mode);
463: bool msgabort(void);
464: bool email(int usernumber, char *top, char *title, long mode);
465: void forwardmail(smbmsg_t* msg, int usernum);
466: void removeline(char *str, char *str2, char num, char skip);
467: ulong msgeditor(char *buf, char *top, char *title);
468: void editfile(char *path);
469: int loadmsg(smbmsg_t *msg, ulong number);
470: ushort chmsgattr(ushort attr);
471: void show_msgattr(ushort attr);
472: void show_msghdr(smbmsg_t* msg);
473: void show_msg(smbmsg_t* msg, long mode);
474: void msgtotxt(smbmsg_t* msg, char *str, int header, int tails);
475: void quotemsg(smbmsg_t* msg, int tails);
476: void editmsg(smbmsg_t* msg, uint subnum);
477: void editor_inf(int xeditnum,char *dest, char *title, long mode
478: ,uint subnum);
479: void copyfattach(uint to, uint from, char *title);
480: bool movemsg(smbmsg_t* msg, uint subnum);
481:
482: /* postmsg.cpp */
483: bool postmsg(uint subnum, smbmsg_t* msg, long wm_mode);
484:
485: /* mail.cpp */
486: int delmail(uint usernumber,int which);
487: void telluser(smbmsg_t* msg);
488: void delallmail(uint usernumber);
489:
490: /* getmsg.cpp */
491: post_t* loadposts(long *posts, uint subnum, ulong ptr, long mode);
492:
493: /* readmail.cpp */
494: void readmail(uint usernumber, int sent);
495:
496: /* bulkmail.cpp */
497: bool bulkmail(uchar *ar);
498: int bulkmailhdr(smb_t*, smbmsg_t*, uint usernum);
499:
500: /* con_out.cpp */
501: int bputs(char *str); /* BBS puts function */
502: int rputs(char *str); /* BBS raw puts function */
503: int bprintf(char *fmt, ...); /* BBS printf function */
504: int rprintf(char *fmt, ...); /* BBS raw printf function */
505: void backspace(void); /* Output a destructive backspace via outchar */
506: void outchar(char ch); /* Output a char - check echo and emu. */
507: void center(char *str);
508: void clearline(void);
509: void cleartoeol(void);
510: void cursor_home(void);
511: void cursor_up(int count=1);
512: void cursor_down(int count=1);
513: void cursor_left(int count=1);
514: void cursor_right(int count=1);
515: long term_supports(long cmp_flags=0);
516:
517: /* getstr.cpp */
518: size_t getstr_offset;
519: size_t getstr(char *str, size_t length, long mode);
520: long getnum(ulong max);
521: void insert_indicator(void);
522:
523: /* getkey.cpp */
524: char getkey(long mode); /* Waits for a key hit local or remote */
525: long getkeys(char *str, ulong max);
526: void ungetkey(char ch); /* Places 'ch' into the input buffer */
527: char question[128];
528: bool yesno(char *str);
529: bool noyes(char *str);
530: void pause(void);
531: char * mnestr;
532: void mnemonics(char *str);
533:
534: /* inkey.cpp */
535: char inkey(long mode, unsigned long timeout=0);
536: char handle_ctrlkey(char ch, long mode=0);
537:
538: /* prntfile.cpp */
539: void printfile(char *str, long mode);
540: void printtail(char *str, int lines, long mode);
541: void menu(const char *code);
542:
543: int uselect(int add, uint n, char *title, char *item, uchar *ar);
544: uint uselect_total, uselect_num[500];
545:
546: void redrwstr(char *strin, int i, int l, long mode);
547: void attr(int atr); /* Change local and remote text attributes */
548: void ctrl_a(char x); /* Peforms the Ctrl-Ax attribute changes */
549:
550: /* atcodes.cpp */
551: int show_atcode(char *code);
552: char* atcode(char* sp, char* str, size_t maxlen);
553:
554: /* getnode.cpp */
555: int getsmsg(int usernumber);
556: int getnmsg(void);
557: int whos_online(bool listself);/* Lists active nodes, returns active nodes */
558: void nodelist(void);
559: int getnodeext(uint number, char * str);
560: int getnodedat(uint number, node_t * node, bool lock);
561: void nodesync(void);
562: user_t nodesync_user;
563: bool nodesync_inside;
564:
565: /* putnode.cpp */
566: int putnodedat(uint number, node_t * node);
567: int putnodeext(uint number, char * str);
568:
569: /* logonoff.cpp */
570: bool answer();
571: int login(char *str, char *pw);
572: bool logon(void);
573: void logout(void);
574: void logoff(void);
575: BOOL newuser(void); /* Get new user */
576: void backout(void);
577:
578: /* text_sec.cpp */
579: int text_sec(void); /* Text sections */
580:
581: /* readmsgs.cpp */
582: int scanposts(uint subnum, long mode, char* find); /* Scan sub-board */
583: long listsub(uint subnum, long mode, long start, char* search);
584: long listmsgs(uint subnum, long mode, post_t* post, long start, long posts);
585: long searchposts(uint subnum, post_t* post, long start, long msgs, char* find);
586: long showposts_toyou(post_t* post, ulong start, long posts);
587: void msghdr(smbmsg_t* msg);
588:
589: /* chat.cpp */
590: void chatsection(void);
591: void multinodechat(int channel=1);
592: void nodepage(void);
593: void nodemsg(void);
594: uint nodemsg_inside;
595: uint hotkey_inside;
596: uchar lastnodemsg; /* Number of node last message was sent to */
597: char lastnodemsguser[LEN_ALIAS+1];
598: void guruchat(char* line, char* guru, int gurunum, char* last_answer);
599: bool guruexp(char **ptrptr, char *line);
600: void localguru(char *guru, int gurunum);
601: bool sysop_page(void);
602: bool guru_page(void);
603: void privchat(bool local=false);
604: bool chan_access(uint cnum);
605: int getnodetopage(int all, int telegram);
606:
607: /* main.cpp */
608: void printstatslog(uint node);
609: ulong logonstats(void);
610: void logoffstats(void);
611: int nopen(char *str, int access);
612: int mv(char *src, char *dest, char copy); /* fast file move/copy function */
613: bool chksyspass(void);
614: bool chk_ar(uchar * str, user_t * user); /* checks access requirements */
615: bool ar_exp(uchar ** ptrptr, user_t * user);
616: void daily_maint(void);
617:
618: /* upload.cpp */
619: bool uploadfile(file_t* f);
620: char sbbsfilename[128],sbbsfiledesc[128]; /* env vars */
621: bool upload(uint dirnum);
622: char upload_lastdesc[LEN_FDESC+1];
623: bool bulkupload(uint dirnum);
624:
625: /* download.cpp */
626: void downloadfile(file_t* f);
627: void notdownloaded(ulong size, time_t start, time_t end);
628: int protocol(prot_t* prot, enum XFER_TYPE, char *fpath, char *fspec, bool cd);
629: char* protcmdline(prot_t* prot, enum XFER_TYPE type);
630: void seqwait(uint devnum);
631: void autohangup(void);
632: bool checkdszlog(file_t*);
633: bool checkprotresult(prot_t*, int error, file_t*);
634: bool sendfile(char* fname, char prot=0);
635: bool recvfile(char* fname, char prot=0);
636:
637: /* file.cpp */
638: void fileinfo(file_t* f);
639: void openfile(file_t* f);
640: void closefile(file_t* f);
641: bool removefcdt(file_t* f);
642: bool movefile(file_t* f, int newdir);
643: char * getfilespec(char *str);
644: bool checkfname(char *fname);
645: bool addtobatdl(file_t* f);
646:
647: /* listfile.cpp */
648: bool listfile(char *fname, char *buf, uint dirnum
649: ,char *search, char letter, ulong datoffset);
650: int listfiles(uint dirnum, char *filespec, int tofile, long mode);
651: int listfileinfo(uint dirnum, char *filespec, long mode);
652: void listfiletofile(char *fname, char *buf, uint dirnum, int file);
653: int batchflagprompt(uint dirnum, file_t bf[], uint total, long totalfiles);
654:
655: /* bat_xfer.cpp */
656: void batchmenu(void);
657: void batch_create_list(void);
658: void batch_add_list(char *list);
659: bool create_batchup_lst(void);
660: bool create_batchdn_lst(bool native);
661: bool create_bimodem_pth(void);
662: void batch_upload(void);
663: void batch_download(int xfrprot);
664: BOOL start_batch_download(void);
665:
666: /* tmp_xfer.cpp */
667: void temp_xfer(void);
668: void extract(uint dirnum);
669: char * temp_cmd(void); /* Returns temp file command line */
670: ulong create_filelist(char *name, long mode);
671:
672: /* viewfile.cpp */
673: int viewfile(file_t* f, int ext);
674: void viewfiles(uint dirnum, char *fspec);
675: void viewfilecontents(file_t* f);
676:
677: /* sortdir.cpp */
678: void resort(uint dirnum);
679:
680: /* xtrn.cpp */
681: int external(const char* cmdline, long mode, const char* startup_dir=NULL);
682:
683: /* xtrn_sec.cpp */
684: int xtrn_sec(void); /* The external program section */
685: void xtrndat(char* name, char* dropdir, uchar type, ulong tleft
686: ,ulong misc);
687: bool exec_xtrn(uint xtrnnum); /* Executes online external program */
688: bool user_event(user_event_t); /* Executes user event(s) */
689: char xtrn_access(uint xnum); /* Does useron have access to xtrn? */
690: void moduserdat(uint xtrnnum);
691:
692: /* logfile.cpp */
693: void logentry(char *code,char *entry);
694: void log(char *str); /* Writes 'str' to node log */
695: void logch(char ch, bool comma); /* Writes 'ch' to node log */
696: void logline(char *code,char *str); /* Writes 'str' on it's own line in log */
697: void logofflist(void); /* List of users logon activity */
698: bool syslog(char* code, char *entry);
699: void errorlog(char *text); /* Logs errors to ERROR.LOG and NODE.LOG */
700: bool errorlog_inside;
701: bool errormsg_inside;
702: void errormsg(int line, const char *file, const char* action, const char *object
703: ,ulong access, const char *extinfo=NULL);
704:
705: /* qwk.cpp */
706: bool qwklogon;
707: ulong qwkmail_last;
708: void qwk_sec(void);
709: int qwk_route(char *inaddr, char *fulladdr);
710: void update_qwkroute(char *via);
711: void qwk_success(ulong msgcnt, char bi, char prepack);
712: void qwksetptr(uint subnum, char *buf, int reset);
713: void qwkcfgline(char *buf,uint subnum);
714: int set_qwk_flag(ulong flag);
715:
716: /* pack_qwk.cpp */
717: bool pack_qwk(char *packet, ulong *msgcnt, bool prepack);
718:
719: /* un_qwk.cpp */
720: bool unpack_qwk(char *packet,uint hubnum);
721:
722: /* pack_rep.cpp */
723: bool pack_rep(uint hubnum);
724:
725: /* un_rep.cpp */
726: bool unpack_rep(char* repfile=NULL);
727:
728: /* msgtoqwk.cpp */
729: ulong msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, int subnum, int conf);
730:
731: /* qwktomsg.cpp */
732: bool qwktomsg(FILE *qwk_fp, char *hdrblk, char fromhub, uint subnum
733: ,uint touser);
734:
735: /* fido.cpp */
736: bool netmail(char *into, char *subj, long mode);
737: void qwktonetmail(FILE *rep, char *block, char *into, uchar fromhub);
738: bool lookup_netuser(char *into);
739:
740: bool inetmail(char *into, char *subj, long mode);
741: bool qnetmail(char *into, char *subj, long mode);
742:
743: /* useredit.cpp */
744: void useredit(int usernumber);
745: int searchup(char *search,int usernum);
746: int searchdn(char *search,int usernum);
747: void maindflts(user_t* user);
748: void purgeuser(int usernumber);
749:
750: /* ver.cpp */
751: void ver(void);
752:
753: /* scansubs.cpp */
754: void scansubs(long mode);
755: void scanallsubs(long mode);
756: void new_scan_cfg(ulong misc);
757: void new_scan_ptr_cfg(void);
758:
759: /* scandirs.cpp */
760: void scanalldirs(long mode);
761: void scandirs(long mode);
762:
763: #define nosound()
764: #define checkline()
765:
766: void catsyslog(int crash);
767:
768: /* telgate.cpp */
769: void telnet_gate(char* addr, ulong mode); // See TG_* for mode bits
770:
771: };
772:
773: #endif /* __cplusplus */
774:
775: #ifdef DLLEXPORT
776: #undef DLLEXPORT
777: #endif
778: #ifdef DLLCALL
779: #undef DLLCALL
780: #endif
781: #ifdef _WIN32
782: #ifdef SBBS_EXPORTS
783: #define DLLEXPORT __declspec(dllexport)
784: #else
785: #define DLLEXPORT __declspec(dllimport)
786: #endif
787: #ifdef __BORLANDC__
788: #define DLLCALL __stdcall
789: #else
790: #define DLLCALL
791: #endif
792: #else /* !_WIN32 */
793: #define DLLEXPORT
794: #define DLLCALL
795: #endif
796:
797: #ifdef __cplusplus
798: extern "C" {
799: #endif
800:
801: /* main.cpp */
802: DLLEXPORT int DLLCALL sbbs_random(int);
803: DLLEXPORT void DLLCALL sbbs_srand(void);
804:
805: /* getstats.c */
806: DLLEXPORT BOOL DLLCALL getstats(scfg_t* cfg, char node, stats_t* stats);
807: DLLEXPORT ulong DLLCALL getposts(scfg_t* cfg, uint subnum);
808: DLLEXPORT long DLLCALL getfiles(scfg_t* cfg, uint dirnum);
809:
810: /* getmail.c */
811: DLLEXPORT int DLLCALL getmail(scfg_t* cfg, int usernumber, BOOL sent);
812: DLLEXPORT mail_t * DLLCALL loadmail(smb_t* smb, long* msgs, uint usernumber
813: ,int which, long mode);
814: DLLEXPORT void DLLCALL freemail(mail_t* mail);
815: DLLEXPORT void DLLCALL delfattach(scfg_t*, smbmsg_t*);
816:
817: /* postmsg.cpp */
818: DLLEXPORT int DLLCALL savemsg(scfg_t*, smb_t*, smbmsg_t*, client_t*, char* msgbuf);
819: DLLEXPORT void DLLCALL signal_sub_sem(scfg_t*, uint subnum);
820: DLLEXPORT int DLLCALL msg_client_hfields(smbmsg_t*, client_t*);
821:
822: /* filedat.c */
823: DLLEXPORT BOOL DLLCALL getfileixb(scfg_t* cfg, file_t* f);
824: DLLEXPORT BOOL DLLCALL putfileixb(scfg_t* cfg, file_t* f);
825: DLLEXPORT BOOL DLLCALL getfiledat(scfg_t* cfg, file_t* f);
826: DLLEXPORT BOOL DLLCALL putfiledat(scfg_t* cfg, file_t* f);
827: DLLEXPORT void DLLCALL putextdesc(scfg_t* cfg, uint dirnum, ulong datoffset, char *ext);
828: DLLEXPORT void DLLCALL getextdesc(scfg_t* cfg, uint dirnum, ulong datoffset, char *ext);
829: DLLEXPORT char* DLLCALL getfilepath(scfg_t* cfg, file_t* f, char* path);
830:
831: DLLEXPORT BOOL DLLCALL removefiledat(scfg_t* cfg, file_t* f);
832: DLLEXPORT BOOL DLLCALL addfiledat(scfg_t* cfg, file_t* f);
833: DLLEXPORT BOOL DLLCALL findfile(scfg_t* cfg, uint dirnum, char *filename);
834: DLLEXPORT char * DLLCALL padfname(char *filename, char *str);
835: DLLEXPORT char * DLLCALL unpadfname(char *filename, char *str);
836: DLLEXPORT BOOL DLLCALL rmuserxfers(scfg_t* cfg, int fromuser, int destuser, char *fname);
837:
838: DLLEXPORT int DLLCALL update_uldate(scfg_t* cfg, file_t* f);
839:
840: /* str_util.c */
841: DLLEXPORT char * DLLCALL truncstr(char* str, const char* set);
842: DLLEXPORT char * DLLCALL ascii_str(uchar* str);
843: DLLEXPORT BOOL DLLCALL findstr(char *insearch, char *fname);
844: DLLEXPORT BOOL DLLCALL trashcan(scfg_t* cfg, char *insearch, char *name);
845: DLLEXPORT char * DLLCALL strip_exascii(char *str);
846: DLLEXPORT char * DLLCALL prep_file_desc(char *str);
847: DLLEXPORT char * DLLCALL strip_ctrl(char *str);
848: DLLEXPORT char * DLLCALL net_addr(net_t* net);
849: DLLEXPORT BOOL DLLCALL validattr(char a);
850: DLLEXPORT size_t DLLCALL strip_invalid_attr(char *str);
851: DLLEXPORT char * DLLCALL ultoac(ulong l,char *str);
852: DLLEXPORT char * DLLCALL rot13(char* str);
853:
854: /* msg_id.c */
855: DLLEXPORT char * DLLCALL ftn_msgid(sub_t* sub, smbmsg_t* msg);
856: DLLEXPORT char * DLLCALL get_msgid(scfg_t* cfg, uint subnum, smbmsg_t* msg);
857:
858:
859: /* date_str.c */
860: DLLEXPORT char * DLLCALL zonestr(short zone);
861: DLLEXPORT time_t DLLCALL dstrtounix(scfg_t*, char *str);
862: DLLEXPORT char * DLLCALL unixtodstr(scfg_t*, time_t, char *str);
863: DLLEXPORT char * DLLCALL sectostr(uint sec, char *str);
864: DLLEXPORT char * DLLCALL hhmmtostr(scfg_t* cfg, struct tm* tm, char* str);
865: DLLEXPORT char * DLLCALL timestr(scfg_t* cfg, time_t *intime, char* str);
866: DLLEXPORT when_t DLLCALL rfc822date(char* p);
867: DLLEXPORT char * DLLCALL msgdate(when_t when, char* buf);
868:
869: /* load_cfg.c */
870: DLLEXPORT BOOL DLLCALL load_cfg(scfg_t* cfg, char* text[], BOOL prep, char* error);
871: DLLEXPORT void DLLCALL free_cfg(scfg_t* cfg);
872: DLLEXPORT void DLLCALL free_text(char* text[]);
873: DLLEXPORT ushort DLLCALL sys_timezone(scfg_t* cfg);
874:
875: /* scfgsave.c */
876: DLLEXPORT BOOL DLLCALL save_cfg(scfg_t* cfg, int backup_level);
877: DLLEXPORT BOOL DLLCALL write_node_cfg(scfg_t* cfg, int backup_level);
878: DLLEXPORT BOOL DLLCALL write_main_cfg(scfg_t* cfg, int backup_level);
879: DLLEXPORT BOOL DLLCALL write_msgs_cfg(scfg_t* cfg, int backup_level);
880: DLLEXPORT BOOL DLLCALL write_file_cfg(scfg_t* cfg, int backup_level);
881: DLLEXPORT BOOL DLLCALL write_chat_cfg(scfg_t* cfg, int backup_level);
882: DLLEXPORT BOOL DLLCALL write_xtrn_cfg(scfg_t* cfg, int backup_level);
883: DLLEXPORT BOOL DLLCALL fcopy(char* src, char* dest);
884: DLLEXPORT BOOL DLLCALL fcompare(char* fn1, char* fn2);
885: DLLEXPORT BOOL DLLCALL backup(char *org, int backup_level, BOOL ren);
886: DLLEXPORT void DLLCALL refresh_cfg(scfg_t* cfg);
887:
888:
889: /* scfglib1.c */
890: DLLEXPORT char * DLLCALL prep_dir(char* base, char* dir, size_t buflen);
891:
892: /* logfile.cpp */
893: DLLEXPORT BOOL DLLCALL hacklog(scfg_t* cfg, char* prot, char* user, char* text
894: ,char* host, SOCKADDR_IN* addr);
895: DLLEXPORT BOOL DLLCALL spamlog(scfg_t* cfg, char* prot, char* action, char* reason
896: ,char* host, char* ip_addr, char* to, char* from);
897:
898: DLLEXPORT char * DLLCALL remove_ctrl_a(char* instr, char* outstr);
899:
900: /* data_ovl.cpp */
901: DLLEXPORT BOOL DLLCALL getmsgptrs(scfg_t* cfg, uint usernumber, subscan_t* subscan);
902: DLLEXPORT BOOL DLLCALL putmsgptrs(scfg_t* cfg, uint usernumber, subscan_t* subscan);
903:
904: /* sockopt.c */
905: DLLEXPORT int DLLCALL set_socket_options(scfg_t* cfg, SOCKET sock, const char* section
906: ,char* error, size_t errlen);
907:
908: /* xtrn.cpp */
909: DLLEXPORT char* DLLCALL cmdstr(scfg_t* cfg, user_t* user, const char* instr
910: ,const char* fpath, const char* fspec, char* cmd);
911:
912: #ifdef JAVASCRIPT
913:
914: typedef struct {
915: const char* name;
916: JSNative call;
917: uint8 nargs;
918: int type; /* return type */
919: const char* args; /* arguments */
920: const char* desc; /* description */
921: int ver; /* version added/modified */
922: } jsSyncMethodSpec;
923:
924: typedef struct {
925: const char *name;
926: int8 tinyid;
927: uint8 flags;
928: int ver; /* version added/modified */
929: } jsSyncPropertySpec;
930:
931: typedef struct {
932: const char* name;
933: int val;
934: } jsConstIntSpec;
935:
936: typedef struct {
937: char version[128];
938: const char* version_detail;
939: DWORD* interface_addr;
940: DWORD* options;
941: DWORD* clients;
942: } js_server_props_t;
943:
944: enum {
945: JSTYPE_ARRAY=JSTYPE_LIMIT
946: ,JSTYPE_ALIAS
947: ,JSTYPE_UNDEF
948: #if !defined(JSTYPE_NULL) /* JSTYPE_NULL was removed after 1.5 rc 6a (?) */
949: ,JSTYPE_NULL
950: #endif
951: };
952:
953: #ifdef BUILD_JSDOCS /* String compiled into debug build only, for JS documentation generation */
954: #define JSDOCSTR(s) s
955: #else
956: #define JSDOCSTR(s) NULL
957: #endif
958:
959: /* main.cpp */
960: DLLEXPORT JSBool DLLCALL js_DescribeSyncObject(JSContext* cx, JSObject* obj, const char*, int ver);
961: DLLEXPORT JSBool DLLCALL js_DescribeSyncConstructor(JSContext* cx, JSObject* obj, const char*);
962: DLLEXPORT JSBool DLLCALL js_DefineSyncMethods(JSContext* cx, JSObject* obj, jsSyncMethodSpec*, BOOL append);
963: DLLEXPORT JSBool DLLCALL js_DefineSyncProperties(JSContext* cx, JSObject* obj, jsSyncPropertySpec*);
964: DLLEXPORT JSBool DLLCALL js_DefineConstIntegers(JSContext* cx, JSObject* obj, jsConstIntSpec*, int flags);
965: DLLEXPORT JSBool DLLCALL js_CreateArrayOfStrings(JSContext* cx, JSObject* parent
966: ,const char* name, char* str[], uintN flags);
967: DLLEXPORT char* DLLCALL js_ValueToStringBytes(JSContext* cx, jsval val, size_t* len);
968:
969: #define JSVAL_IS_NUM(v) (JSVAL_IS_NUMBER(v) && (!JSVAL_IS_DOUBLE(v) || !JSDOUBLE_IS_NaN(*JSVAL_TO_DOUBLE(v))))
970:
971: /* js_server.c */
972: DLLEXPORT JSObject* DLLCALL js_CreateServerObject(JSContext* cx, JSObject* parent
973: ,js_server_props_t* props);
974:
975: /* js_global.c */
976: DLLEXPORT JSObject* DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethodSpec* methods);
977: DLLEXPORT JSObject* DLLCALL js_CreateCommonObjects(JSContext* cx
978: ,scfg_t* cfg /* common */
979: ,scfg_t* node_cfg /* node-specific */
980: ,jsSyncMethodSpec* methods /* global */
981: ,time_t uptime /* system */
982: ,char* host_name /* system */
983: ,char* socklib_desc /* system */
984: ,js_branch_t* js_branch /* js */
985: ,client_t* client /* client */
986: ,SOCKET client_socket /* client */
987: ,js_server_props_t* props /* server */
988: );
989:
990: /* js_internal.c */
991: DLLEXPORT JSObject* DLLCALL js_CreateInternalJsObject(JSContext*, JSObject* parent, js_branch_t* branch);
992: DLLEXPORT JSBool DLLCALL js_CommonBranchCallback(JSContext*, js_branch_t*);
993: DLLEXPORT void DLLCALL js_EvalOnExit(JSContext*, JSObject*, js_branch_t*);
994:
995: /* js_system.c */
996: DLLEXPORT JSObject* DLLCALL js_CreateSystemObject(JSContext* cx, JSObject* parent
997: ,scfg_t* cfg, time_t uptime
998: ,char* host_name
999: ,char* socklib_desc);
1000:
1001: /* js_client.c */
1002: DLLEXPORT JSObject* DLLCALL js_CreateClientObject(JSContext* cx, JSObject* parent
1003: ,char* name, client_t* client, SOCKET sock);
1004: /* js_user.c */
1005: DLLEXPORT JSObject* DLLCALL js_CreateUserClass(JSContext* cx, JSObject* parent, scfg_t* cfg);
1006: DLLEXPORT JSObject* DLLCALL js_CreateUserObject(JSContext* cx, JSObject* parent, scfg_t* cfg
1007: ,char* name, uint usernumber);
1008: DLLEXPORT JSBool DLLCALL js_CreateUserObjects(JSContext* cx, JSObject* parent, scfg_t* cfg
1009: ,user_t* user, char* html_index_file
1010: ,subscan_t* subscan);
1011: /* js_file_area.c */
1012: DLLEXPORT JSObject* DLLCALL js_CreateFileAreaObject(JSContext* cx, JSObject* parent, scfg_t* cfg
1013: ,user_t* user, char* html_index_file);
1014:
1015: /* js_msg_area.c */
1016: DLLEXPORT JSObject* DLLCALL js_CreateMsgAreaObject(JSContext* cx, JSObject* parent, scfg_t* cfg
1017: ,user_t* user, subscan_t* subscan);
1018: DLLEXPORT BOOL DLLCALL js_CreateMsgAreaProperties(JSContext* cx, scfg_t* cfg
1019: ,JSObject* subobj, uint subnum);
1020:
1021: /* js_xtrn_area.c */
1022: DLLEXPORT JSObject* DLLCALL js_CreateXtrnAreaObject(JSContext* cx, JSObject* parent, scfg_t* cfg
1023: ,user_t* user);
1024:
1025: /* js_msgbase.c */
1026: DLLEXPORT JSObject* DLLCALL js_CreateMsgBaseClass(JSContext* cx, JSObject* parent, scfg_t* cfg);
1027: DLLEXPORT BOOL DLLCALL js_ParseMsgHeaderObject(JSContext* cx, JSObject* hdrobj, smbmsg_t*);
1028:
1029: /* js_socket.c */
1030: DLLEXPORT JSObject* DLLCALL js_CreateSocketClass(JSContext* cx, JSObject* parent);
1031: DLLEXPORT JSObject* DLLCALL js_CreateSocketObject(JSContext* cx, JSObject* parent
1032: ,char *name, SOCKET sock);
1033: DLLEXPORT void DLLCALL js_timeval(JSContext* cx, jsval val, struct timeval* tv);
1034: DLLEXPORT SOCKET DLLCALL js_socket(JSContext *cx, jsval val);
1035:
1036: /* js_queue.c */
1037: DLLEXPORT JSObject* DLLCALL js_CreateQueueClass(JSContext* cx, JSObject* parent);
1038: DLLEXPORT JSObject* DLLCALL js_CreateQueueObject(JSContext* cx, JSObject* parent
1039: ,char *name, msg_queue_t* q);
1040: BOOL js_enqueue_value(JSContext *cx, msg_queue_t* q, jsval val, char* name);
1041:
1042: /* js_file.c */
1043: DLLEXPORT JSObject* DLLCALL js_CreateFileClass(JSContext* cx, JSObject* parent);
1044:
1045: /* js_sprintf.c */
1046: DLLEXPORT char* DLLCALL js_sprintf(JSContext* cx, uint argn, uintN argc, jsval *argv);
1047: DLLEXPORT void DLLCALL js_sprintf_free(char *);
1048:
1049: /* js_console.cpp */
1050: JSObject* js_CreateConsoleObject(JSContext* cx, JSObject* parent);
1051:
1052: /* js_bbs.cpp */
1053: JSObject* js_CreateBbsObject(JSContext* cx, JSObject* parent);
1054:
1055: /* js_uifc.c */
1056: JSObject* js_CreateUifcObject(JSContext* cx, JSObject* parent);
1057:
1058: #endif
1059:
1060: /* str_util.c */
1061: int bstrlen(char *str);
1062: void backslashcolon(char *str);
1063: ulong ahtoul(char *str); /* Converts ASCII hex to ulong */
1064: char * hexplus(uint num, char *str); /* Hex plus for 3 digits up to 9000 */
1065: uint hptoi(char *str);
1066: int pstrcmp(char **str1, char **str2); /* Compares pointers to pointers */
1067: int strsame(char *str1, char *str2); /* Compares number of same chars */
1068:
1069: /* load_cfg.c */
1070: BOOL md(char *path);
1071:
1072: #ifdef SBBS /* These aren't exported */
1073:
1074: /* main.c */
1075: int lputs(int level, char *); /* log output */
1076: int lprintf(int level, char *fmt, ...); /* log output */
1077: int eprintf(int level, char *fmt, ...); /* event log */
1078: SOCKET open_socket(int type, const char* protocol);
1079: SOCKET accept_socket(SOCKET s, SOCKADDR* addr, socklen_t* addrlen);
1080: int close_socket(SOCKET);
1081: u_long resolve_ip(char *addr);
1082:
1083: char * readtext(long *line, FILE *stream);
1084:
1085: /* ver.cpp */
1086: char* socklib_version(char* str, char* winsock_ver);
1087:
1088: /* sortdir.cpp */
1089: int fnamecmp_a(char **str1, char **str2); /* for use with resort() */
1090: int fnamecmp_d(char **str1, char **str2);
1091: int fdatecmp_a(uchar **buf1, uchar **buf2);
1092: int fdatecmp_d(uchar **buf1, uchar **buf2);
1093:
1094: /* file.cpp */
1095: BOOL filematch(char *filename, char *filespec);
1096:
1097: /* sbbscon.c */
1098: #if defined(__unix__) && defined(NEEDS_DAEMON)
1099: int daemon(int nochdir, int noclose);
1100: #endif
1101:
1102: #endif /* SBBS */
1103:
1104: extern const char* wday[]; /* abbreviated weekday names */
1105: extern const char* mon[]; /* abbreviated month names */
1106: extern char lastuseron[LEN_ALIAS+1]; /* Name of user last online */
1107:
1108: #ifdef __cplusplus
1109: }
1110: #endif
1111:
1112: extern
1113: #ifdef __cplusplus
1114: "C"
1115: #endif
1116: const char* beta_version;
1117:
1118: /* Global data */
1119:
1120: /* ToDo: These should be hunted down and killed */
1121: #define lread(f,b,l) read(f,b,l)
1122: #define lfread(b,l,f) fread(b,l,f)
1123: #define lwrite(f,b,l) write(f,b,l)
1124: #define lfwrite(b,l,f) fwrite(b,l,f)
1125: #define lkbrd(x) 0
1126:
1127: #endif /* Don't add anything after this line */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.