/*
* Server functions which handle file transfers and room directories.
+ *
+ * Copyright (c) 1987-2015 by the citadel.org team
+ *
+ * This program is open source software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*/
-#include "sysdep.h"
-#include <stdlib.h>
-#include <unistd.h>
#include <stdio.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <ctype.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
-#include <limits.h>
#include <libcitadel.h>
-#include "citadel.h"
-#include "server.h"
-#include "config.h"
-#include "files.h"
-#include "sysdep_decls.h"
-#include "support.h"
-#include "room_ops.h"
-#include "msgbase.h"
-#include "citserver.h"
-#include "threads.h"
+#include <dirent.h>
+
#include "ctdl_module.h"
+#include "citserver.h"
+#include "support.h"
+#include "config.h"
#include "user_ops.h"
-
/*
* Server command to delete a file from a room's directory
*/
*/
void cmd_oimg(char *cmdbuf)
{
- char filename[256];
+ char filename[PATH_MAX];
char pathname[PATH_MAX];
char MimeTestBuf[32];
- struct ctdluser usbuf;
- char which_user[USERNAME_SIZE];
int which_floor;
int a;
int rv;
return;
}
- if (!strcasecmp(filename, "_userpic_")) {
- extract_token(which_user, cmdbuf, 1, '|', sizeof which_user);
- if (CtdlGetUser(&usbuf, which_user) != 0) {
- cprintf("%d No such user.\n",
- ERROR + NO_SUCH_USER);
- return;
- }
- snprintf(pathname, sizeof pathname,
- "%s/%ld",
- ctdl_usrpic_dir,
- usbuf.usernum);
- } else if (!strcasecmp(filename, "_floorpic_")) {
+ if (!strcasecmp(filename, "_floorpic_")) {
which_floor = extract_int(cmdbuf, 1);
- snprintf(pathname, sizeof pathname,
- "%s/floor.%d",
- ctdl_image_dir, which_floor);
- } else if (!strcasecmp(filename, "_roompic_")) {
+ snprintf(pathname, sizeof pathname, "%s/floor.%d", ctdl_image_dir, which_floor);
+ }
+ else if (!strcasecmp(filename, "_roompic_")) {
assoc_file_name(pathname, sizeof pathname, &CC->room, ctdl_image_dir);
- } else {
+ }
+ else {
for (a = 0; !IsEmptyStr(&filename[a]); ++a) {
filename[a] = tolower(filename[a]);
if ( (filename[a] == '/') || (filename[a] == '\\') ) {
OpenCmdResult(pathname, GuessMimeType(&MimeTestBuf[0], 32));
}
+
/*
* open a file for uploading
*/
basenm);
}
- if (!strcasecmp(basenm, "_userpic_")) {
- snprintf(CC->upl_path, sizeof CC->upl_path,
- "%s/%ld.gif",
- ctdl_usrpic_dir,
- CC->user.usernum);
- }
-
if ((!strcasecmp(basenm, "_floorpic_"))
&& (CC->user.axlevel >= AxAideU)) {
which_floor = extract_int(cmdbuf, 2);
*/
void cmd_ucls(char *cmd)
{
+ struct CitContext *CCC = CC;
FILE *fp;
char upload_notice[512];
static int seq = 0;
- if (CC->upload_fp == NULL) {
+ if (CCC->upload_fp == NULL) {
cprintf("%d You don't have an upload file open.\n", ERROR + RESOURCE_NOT_OPEN);
return;
}
fclose(CC->upload_fp);
- CC->upload_fp = NULL;
+ CCC->upload_fp = NULL;
- if ((!strcasecmp(cmd, "1")) && (CC->upload_type != UPL_FILE)) {
+ if ((!strcasecmp(cmd, "1")) && (CCC->upload_type != UPL_FILE)) {
cprintf("%d Upload completed.\n", CIT_OK);
- if (CC->upload_type == UPL_NET) {
+ if (CCC->upload_type == UPL_NET) {
char final_filename[PATH_MAX];
snprintf(final_filename, sizeof final_filename,
"%s/%s.%04lx.%04x",
ctdl_netin_dir,
- CC->net_node,
+ CCC->net_node,
(long)getpid(),
++seq
);
- if (link(CC->upl_path, final_filename) == 0) {
- syslog(LOG_INFO, "UCLS: updoaded %s\n",
+ if (link(CCC->upl_path, final_filename) == 0) {
+ CTDL_syslog(LOG_INFO, "UCLS: updoaded %s",
final_filename);
- unlink(CC->upl_path);
+ unlink(CCC->upl_path);
}
else {
- syslog(LOG_ALERT, "Cannot link %s to %s: %s\n",
- CC->upl_path, final_filename, strerror(errno)
+ CTDL_syslog(LOG_INFO, "Cannot link %s to %s: %s",
+ CCC->upl_path, final_filename, strerror(errno)
);
}
/* FIXME ... here we need to trigger a network run */
}
- CC->upload_type = UPL_FILE;
+ CCC->upload_type = UPL_FILE;
return;
}
if (!strcasecmp(cmd, "1")) {
- cprintf("%d File '%s' saved.\n", CIT_OK, CC->upl_path);
- fp = fopen(CC->upl_filedir, "a");
+ cprintf("%d File '%s' saved.\n", CIT_OK, CCC->upl_path);
+ fp = fopen(CCC->upl_filedir, "a");
if (fp == NULL) {
- fp = fopen(CC->upl_filedir, "w");
+ fp = fopen(CCC->upl_filedir, "w");
}
if (fp != NULL) {
- fprintf(fp, "%s %s %s\n", CC->upl_file,
- CC->upl_mimetype,
- CC->upl_comment);
+ fprintf(fp, "%s %s %s\n", CCC->upl_file,
+ CCC->upl_mimetype,
+ CCC->upl_comment);
fclose(fp);
}
- /* put together an upload notice */
- snprintf(upload_notice, sizeof upload_notice,
- "NEW UPLOAD: '%s'\n %s\n%s\n",
- CC->upl_file,
- CC->upl_comment,
- CC->upl_mimetype);
- quickie_message(CC->curr_user, NULL, NULL, CC->room.QRname,
- upload_notice, 0, NULL);
+ if ((CCC->room.QRflags2 & QR2_NOUPLMSG) == 0) {
+ /* put together an upload notice */
+ snprintf(upload_notice, sizeof upload_notice,
+ "NEW UPLOAD: '%s'\n %s\n%s\n",
+ CCC->upl_file,
+ CCC->upl_comment,
+ CCC->upl_mimetype);
+ quickie_message(CCC->curr_user, NULL, NULL, CCC->room.QRname,
+ upload_notice, 0, NULL);
+ }
} else {
- abort_upl(CC);
- cprintf("%d File '%s' aborted.\n", CIT_OK, CC->upl_path);
+ abort_upl(CCC);
+ cprintf("%d File '%s' aborted.\n", CIT_OK, CCC->upl_path);
}
}
rc = fseek(CC->download_fp, start_pos, 0);
if (rc < 0) {
+ struct CitContext *CCC = CC;
cprintf("%d your file is smaller then %ld.\n", ERROR + ILLEGAL_VALUE, start_pos);
- syslog(LOG_ALERT, "your file %s is smaller then %ld. [%s]\n",
- CC->upl_path,
- start_pos,
- strerror(errno));
+ CTDL_syslog(LOG_ERR, "your file %s is smaller then %ld. [%s]\n",
+ CC->upl_path,
+ start_pos,
+ strerror(errno));
return;
}
*/
void cmd_writ(char *cmdbuf)
{
+ struct CitContext *CCC = CC;
int bytes;
char *buf;
int rv;
bytes = extract_int(cmdbuf, 0);
- if (CC->upload_fp == NULL) {
+ if (CCC->upload_fp == NULL) {
cprintf("%d You don't have an upload file open.\n", ERROR + RESOURCE_NOT_OPEN);
return;
}
cprintf("%d %d\n", SEND_BINARY, bytes);
buf = malloc(bytes + 1);
client_read(buf, bytes);
- rv = fwrite(buf, bytes, 1, CC->upload_fp);
+ rv = fwrite(buf, bytes, 1, CCC->upload_fp);
if (rv == -1) {
- syslog(LOG_EMERG, "Couldn't write: %s\n",
- strerror(errno));
+ CTDL_syslog(LOG_EMERG, "Couldn't write: %s\n",
+ strerror(errno));
}
free(buf);
}
*/
void cmd_ndop(char *cmdbuf)
{
+ struct CitContext *CCC = CC;
char pathname[256];
struct stat statbuf;
- if (IsEmptyStr(CC->net_node)) {
+ if (IsEmptyStr(CCC->net_node)) {
cprintf("%d Not authenticated as a network node.\n",
ERROR + NOT_LOGGED_IN);
return;
}
- if (CC->download_fp != NULL) {
+ if (CCC->download_fp != NULL) {
cprintf("%d You already have a download file open.\n",
ERROR + RESOURCE_BUSY);
return;
snprintf(pathname, sizeof pathname,
"%s/%s",
ctdl_netout_dir,
- CC->net_node);
+ CCC->net_node);
/* first open the file in append mode in order to create a
* zero-length file if it doesn't already exist
*/
- CC->download_fp = fopen(pathname, "a");
- if (CC->download_fp != NULL)
- fclose(CC->download_fp);
+ CCC->download_fp = fopen(pathname, "a");
+ if (CCC->download_fp != NULL)
+ fclose(CCC->download_fp);
/* now open it */
- CC->download_fp = fopen(pathname, "r");
- if (CC->download_fp == NULL) {
+ CCC->download_fp = fopen(pathname, "r");
+ if (CCC->download_fp == NULL) {
cprintf("%d cannot open %s: %s\n",
ERROR + INTERNAL_ERROR, pathname, strerror(errno));
return;
/* set this flag so other routines know that the download file
* currently open is a network spool file
*/
- CC->dl_is_net = 1;
+ CCC->dl_is_net = 1;
stat(pathname, &statbuf);
- CC->download_fp_total = statbuf.st_size;
+ CCC->download_fp_total = statbuf.st_size;
cprintf("%d %ld\n", CIT_OK, (long)statbuf.st_size);
}
}
+/*
+ * help_subst() - support routine for help file viewer
+ */
+void help_subst(char *strbuf, char *source, char *dest)
+{
+ char workbuf[SIZ];
+ int p;
+
+ while (p = pattern2(strbuf, source), (p >= 0)) {
+ strcpy(workbuf, &strbuf[p + strlen(source)]);
+ strcpy(&strbuf[p], dest);
+ strcat(strbuf, workbuf);
+ }
+}
+
+void do_help_subst(char *buffer)
+{
+ char buf2[16];
+
+ help_subst(buffer, "^nodename", CtdlGetConfigStr("c_nodename"));
+ help_subst(buffer, "^humannode", CtdlGetConfigStr("c_humannode"));
+ help_subst(buffer, "^fqdn", CtdlGetConfigStr("c_fqdn"));
+ help_subst(buffer, "^username", CC->user.fullname);
+ snprintf(buf2, sizeof buf2, "%ld", CC->user.usernum);
+ help_subst(buffer, "^usernum", buf2);
+ help_subst(buffer, "^sysadm", CtdlGetConfigStr("c_sysadm"));
+ help_subst(buffer, "^variantname", CITADEL);
+ help_subst(buffer, "^maxsessions", CtdlGetConfigStr("c_maxsessions")); // yes it's numeric but str is ok here
+ help_subst(buffer, "^bbsdir", ctdl_message_dir);
+}
+
+
+typedef const char *ccharp;
+/*
+ * display system messages or help
+ */
+void cmd_mesg(char *mname)
+{
+ FILE *mfp;
+ char targ[256];
+ char buf[256];
+ char buf2[256];
+ char *dirs[2];
+ DIR *dp;
+ struct dirent *d;
+
+ extract_token(buf, mname, 0, '|', sizeof buf);
+
+ dirs[0] = strdup(ctdl_message_dir);
+ dirs[1] = strdup(ctdl_hlp_dir);
+
+ snprintf(buf2, sizeof buf2, "%s.%d.%d",
+ buf, CC->cs_clientdev, CC->cs_clienttyp);
+
+ /* If the client requested "?" then produce a listing */
+ if (!strcmp(buf, "?")) {
+ cprintf("%d %s\n", LISTING_FOLLOWS, buf);
+ dp = opendir(dirs[1]);
+ if (dp != NULL) {
+ while (d = readdir(dp), d != NULL) {
+ if (d->d_name[0] != '.') {
+ cprintf(" %s\n", d->d_name);
+ }
+ }
+ closedir(dp);
+ }
+ cprintf("000\n");
+ free(dirs[0]);
+ free(dirs[1]);
+ return;
+ }
+
+ /* Otherwise, look for the requested file by name. */
+ else {
+ mesg_locate(targ, sizeof targ, buf2, 2, (const ccharp*)dirs);
+ if (IsEmptyStr(targ)) {
+ snprintf(buf2, sizeof buf2, "%s.%d",
+ buf, CC->cs_clientdev);
+ mesg_locate(targ, sizeof targ, buf2, 2,
+ (const ccharp*)dirs);
+ if (IsEmptyStr(targ)) {
+ mesg_locate(targ, sizeof targ, buf, 2,
+ (const ccharp*)dirs);
+ }
+ }
+ }
+
+ free(dirs[0]);
+ free(dirs[1]);
+
+ if (IsEmptyStr(targ)) {
+ cprintf("%d '%s' not found. (Searching in %s and %s)\n",
+ ERROR + FILE_NOT_FOUND,
+ mname,
+ ctdl_message_dir,
+ ctdl_hlp_dir
+ );
+ return;
+ }
+
+ mfp = fopen(targ, "r");
+ if (mfp==NULL) {
+ cprintf("%d Cannot open '%s': %s\n",
+ ERROR + INTERNAL_ERROR, targ, strerror(errno));
+ return;
+ }
+ cprintf("%d %s\n", LISTING_FOLLOWS,buf);
+
+ while (fgets(buf, (sizeof buf - 1), mfp) != NULL) {
+ buf[strlen(buf)-1] = 0;
+ do_help_subst(buf);
+ cprintf("%s\n",buf);
+ }
+
+ fclose(mfp);
+ cprintf("000\n");
+}
+
+
+/*
+ * enter system messages or help
+ */
+void cmd_emsg(char *mname)
+{
+ FILE *mfp;
+ char targ[256];
+ char buf[256];
+ char *dirs[2];
+ int a;
+
+ unbuffer_output();
+
+ if (CtdlAccessCheck(ac_aide)) return;
+
+ extract_token(buf, mname, 0, '|', sizeof buf);
+ for (a=0; !IsEmptyStr(&buf[a]); ++a) { /* security measure */
+ if (buf[a] == '/') buf[a] = '.';
+ }
+
+ dirs[0] = strdup(ctdl_message_dir);
+ dirs[1] = strdup(ctdl_hlp_dir);
+
+ mesg_locate(targ, sizeof targ, buf, 2, (const ccharp*)dirs);
+ free(dirs[0]);
+ free(dirs[1]);
+
+ if (IsEmptyStr(targ)) {
+ snprintf(targ, sizeof targ,
+ "%s/%s",
+ ctdl_hlp_dir, buf);
+ }
+
+ mfp = fopen(targ,"w");
+ if (mfp==NULL) {
+ cprintf("%d Cannot open '%s': %s\n",
+ ERROR + INTERNAL_ERROR, targ, strerror(errno));
+ return;
+ }
+ cprintf("%d %s\n", SEND_LISTING, targ);
+
+ while (client_getln(buf, sizeof buf) >=0 && strcmp(buf, "000")) {
+ fprintf(mfp, "%s\n", buf);
+ }
+
+ fclose(mfp);
+}
/*****************************************************************************/
/* MODULE INITIALIZATION STUFF */
CtdlRegisterProtoHook(cmd_nuop, "NUOP", "Open a network spool file for upload");
CtdlRegisterProtoHook(cmd_oimg, "OIMG", "Open an image file for download");
CtdlRegisterProtoHook(cmd_uimg, "UIMG", "Upload an image file");
+
+ CtdlRegisterProtoHook(cmd_mesg, "MESG", "fetch system banners");
+ CtdlRegisterProtoHook(cmd_emsg, "EMSG", "submit system banners");
}
/* return our Subversion id for the Log */
return "file_ops";