X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmodules%2Fwiki%2Fserv_wiki.c;h=07e5eed41e231aca188764b375681559b62d8692;hb=ea4755777549c692b9c72503cd13acf8fd5df27c;hp=73c9151aa8b9d13f822889cd9ef52b492d939d3e;hpb=aadf6fbc8305a9a178a6b1d81c2e3230f7d6ebe3;p=citadel.git diff --git a/citadel/modules/wiki/serv_wiki.c b/citadel/modules/wiki/serv_wiki.c index 73c9151aa..07e5eed41 100644 --- a/citadel/modules/wiki/serv_wiki.c +++ b/citadel/modules/wiki/serv_wiki.c @@ -1,23 +1,15 @@ /* - * $Id$ - * * Server-side module for Wiki rooms. This handles things like version control. * - * Copyright (c) 2009 by the citadel.org team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. + * Copyright (c) 2009-2012 by the citadel.org team * - * 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. + * 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. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * 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" @@ -53,7 +45,6 @@ #include "config.h" #include "control.h" #include "user_ops.h" -#include "policy.h" #include "database.h" #include "msgbase.h" #include "euidindex.h" @@ -86,6 +77,7 @@ int wiki_upload_beforesave(struct CtdlMessage *msg) { struct CtdlMessage *history_msg = NULL; char diff_old_filename[PATH_MAX]; char diff_new_filename[PATH_MAX]; + char diff_out_filename[PATH_MAX]; char diff_cmd[PATH_MAX]; FILE *fp; int rv; @@ -93,7 +85,6 @@ int wiki_upload_beforesave(struct CtdlMessage *msg) { char boundary[256]; char prefixed_boundary[258]; char buf[1024]; - int nbytes = 0; char *diffbuf = NULL; size_t diffbuf_len = 0; char *ptr = NULL; @@ -119,7 +110,7 @@ int wiki_upload_beforesave(struct CtdlMessage *msg) { if ( (strlen(msg->cm_fields['E']) >= 9) && (!strcasecmp(&msg->cm_fields['E'][strlen(msg->cm_fields['E'])-9], "_HISTORY_")) ) { - CtdlLogPrintf(CTDL_DEBUG, "History page not being historied\n"); + syslog(LOG_DEBUG, "History page not being historied\n"); return(0); } @@ -157,6 +148,7 @@ int wiki_upload_beforesave(struct CtdlMessage *msg) { */ CtdlMakeTempFileName(diff_old_filename, sizeof diff_old_filename); CtdlMakeTempFileName(diff_new_filename, sizeof diff_new_filename); + CtdlMakeTempFileName(diff_out_filename, sizeof diff_out_filename); if (old_msg != NULL) { fp = fopen(diff_old_filename, "w"); @@ -169,29 +161,37 @@ int wiki_upload_beforesave(struct CtdlMessage *msg) { rv = fwrite(msg->cm_fields['M'], strlen(msg->cm_fields['M']), 1, fp); fclose(fp); - diffbuf_len = 0; - diffbuf = NULL; snprintf(diff_cmd, sizeof diff_cmd, - "diff -u %s %s", + DIFF " -u %s %s >%s", diff_new_filename, - ((old_msg != NULL) ? diff_old_filename : "/dev/null") + ((old_msg != NULL) ? diff_old_filename : "/dev/null"), + diff_out_filename ); - fp = popen(diff_cmd, "r"); + syslog(LOG_DEBUG, "diff cmd: %s", diff_cmd); + rv = system(diff_cmd); + syslog(LOG_DEBUG, "diff cmd returned %d", rv); + + diffbuf_len = 0; + diffbuf = NULL; + fp = fopen(diff_out_filename, "r"); + if (fp == NULL) { + fp = fopen("/dev/null", "r"); + } if (fp != NULL) { - do { - diffbuf = realloc(diffbuf, diffbuf_len + 1025); - nbytes = fread(&diffbuf[diffbuf_len], 1, 1024, fp); - diffbuf_len += nbytes; - } while (nbytes == 1024); + fseek(fp, 0L, SEEK_END); + diffbuf_len = ftell(fp); + fseek(fp, 0L, SEEK_SET); + diffbuf = malloc(diffbuf_len + 1); + fread(diffbuf, diffbuf_len, 1, fp); diffbuf[diffbuf_len] = 0; - if (pclose(fp) != 0) { - CtdlLogPrintf(CTDL_ERR, "pclose() returned an error - diff failed\n"); - } + fclose(fp); } - CtdlLogPrintf(CTDL_DEBUG, "diff length is %d bytes\n", diffbuf_len); + + syslog(LOG_DEBUG, "diff length is "SIZE_T_FMT" bytes", diffbuf_len); unlink(diff_old_filename); unlink(diff_new_filename); + unlink(diff_out_filename); /* Determine whether this was a bogus (empty) edit */ if ((diffbuf_len = 0) && (diffbuf != NULL)) { @@ -242,6 +242,7 @@ int wiki_upload_beforesave(struct CtdlMessage *msg) { */ if (history_msg->cm_fields['I'] != NULL) { free(history_msg->cm_fields['I']); + history_msg->cm_fields['I'] = NULL; } /* Figure out the boundary string. We do this even when we generated the @@ -274,7 +275,8 @@ int wiki_upload_beforesave(struct CtdlMessage *msg) { } } while ( (IsEmptyStr(boundary)) && (*ptr != 0) ); - /* Now look for the first boundary. That is where we need to insert our fun. + /* + * Now look for the first boundary. That is where we need to insert our fun. */ if (!IsEmptyStr(boundary)) { snprintf(prefixed_boundary, sizeof prefixed_boundary, "--%s", boundary); @@ -284,16 +286,15 @@ int wiki_upload_beforesave(struct CtdlMessage *msg) { ptr = bmstrcasestr(history_msg->cm_fields['M'], prefixed_boundary); if (ptr != NULL) { char *the_rest_of_it = strdup(ptr); - char uuid[32]; + char uuid[64]; char memo[512]; - char encoded_memo[768]; + char encoded_memo[1024]; generate_uuid(uuid); snprintf(memo, sizeof memo, "%s|%ld|%s|%s", uuid, time(NULL), CCC->user.fullname, config.c_nodename - /* no longer logging CCC->cs_inet_email */ ); CtdlEncodeBase64(encoded_memo, memo, strlen(memo), 0); sprintf(ptr, "--%s\n" @@ -313,12 +314,14 @@ int wiki_upload_beforesave(struct CtdlMessage *msg) { } history_msg->cm_fields['T'] = realloc(history_msg->cm_fields['T'], 32); - snprintf(history_msg->cm_fields['T'], 32, "%ld", time(NULL)); + if (history_msg->cm_fields['T'] != NULL) { + snprintf(history_msg->cm_fields['T'], 32, "%ld", time(NULL)); + } CtdlSubmitMsg(history_msg, NULL, "", 0); } else { - CtdlLogPrintf(CTDL_ALERT, "Empty boundary string in history message. No history!\n"); + syslog(LOG_ALERT, "Empty boundary string in history message. No history!\n"); } free(diffbuf); @@ -422,10 +425,10 @@ void wiki_rev_callback(char *name, char *filename, char *partnum, char *disp, CtdlDecodeBase64(memo, filename, strlen(filename)); extract_token(this_rev, memo, 0, '|', sizeof this_rev); - CtdlLogPrintf(CTDL_DEBUG, "callback found rev: %s\n", this_rev); + striplt(this_rev); /* Perform the patch */ - fp = popen("patch -f -s -p0 --global-reject-file=/dev/null >/dev/null 2>/dev/null", "w"); + fp = popen(PATCH " -f -s -p0 -r /dev/null >/dev/null 2>/dev/null", "w"); if (fp) { /* Replace the filenames in the patch with the tempfilename we're actually tweaking */ fprintf(fp, "--- %s\n", hecbd->tempfilename); @@ -446,13 +449,13 @@ void wiki_rev_callback(char *name, char *filename, char *partnum, char *disp, } } while ((*ptr != 0) && (ptr < ((char*)content + length))); if (pclose(fp) != 0) { - CtdlLogPrintf(CTDL_ERR, "pclose() returned an error - patch failed\n"); + syslog(LOG_ERR, "pclose() returned an error - patch failed\n"); } } if (!strcasecmp(this_rev, hecbd->stop_when)) { /* Found our target rev. Tell any subsequent callbacks to suppress processing. */ - CtdlLogPrintf(CTDL_DEBUG, "Target revision has been reached -- stop patching.\n"); + syslog(LOG_DEBUG, "Target revision has been reached -- stop patching.\n"); hecbd->done = 1; } } @@ -487,6 +490,14 @@ void wiki_rev(char *pagename, char *rev, char *operation) return; } + if (!strcasecmp(operation, "revert")) { + r = CtdlDoIHavePermissionToPostInThisRoom(temp, sizeof temp, NULL, POST_LOGGED_IN, 0); + if (r != 0) { + cprintf("%d %s\n", r, temp); + return; + } + } + /* Begin by fetching the current version of the page. We're going to patch * backwards through the diffs until we get the one we want. */ @@ -517,7 +528,7 @@ void wiki_rev(char *pagename, char *rev, char *operation) fclose(fp); } else { - CtdlLogPrintf(CTDL_ALERT, "Cannot open %s: %s\n", temp, strerror(errno)); + syslog(LOG_ALERT, "Cannot open %s: %s\n", temp, strerror(errno)); } CtdlFreeMessage(msg); @@ -549,6 +560,7 @@ void wiki_rev(char *pagename, char *rev, char *operation) memset(&hecbd, 0, sizeof(struct HistoryEraserCallBackData)); hecbd.tempfilename = temp; hecbd.stop_when = rev; + striplt(hecbd.stop_when); mime_parser(msg->cm_fields['M'], NULL, *wiki_rev_callback, NULL, NULL, (void *)&hecbd, 0); CtdlFreeMessage(msg); @@ -575,7 +587,7 @@ void wiki_rev(char *pagename, char *rev, char *operation) fseek(fp, 0L, SEEK_SET); msg->cm_fields['M'] = malloc(len + 1); rv = fread(msg->cm_fields['M'], len, 1, fp); - CtdlLogPrintf(CTDL_DEBUG, "\033[32mdid %d blocks of %d bytes\033[0m\n", rv, len); + syslog(LOG_DEBUG, "did %d blocks of %ld bytes\n", rv, len); msg->cm_fields['M'][len] = 0; fclose(fp); } @@ -586,6 +598,24 @@ void wiki_rev(char *pagename, char *rev, char *operation) msg->cm_fields['A'] = strdup("Citadel"); CtdlCreateRoom(wwm, 5, "", 0, 1, 1, VIEW_BBS); /* Not an error if already exists */ msgnum = CtdlSubmitMsg(msg, NULL, wwm, 0); /* Store the revision here */ + + /* + * WARNING: VILE SLEAZY HACK + * This will avoid the 'message xxx is not in this room' security error, + * but only if the client fetches the message we just generated immediately + * without first trying to perform other fetch operations. + */ + if (CC->cached_msglist != NULL) { + free(CC->cached_msglist); + CC->cached_msglist = NULL; + CC->cached_num_msgs = 0; + } + CC->cached_msglist = malloc(sizeof(long)); + if (CC->cached_msglist != NULL) { + CC->cached_num_msgs = 1; + CC->cached_msglist[0] = msgnum; + } + } else if (!strcasecmp(operation, "revert")) { snprintf(timestamp, sizeof timestamp, "%ld", time(NULL)); @@ -662,6 +692,6 @@ CTDL_MODULE_INIT(wiki) CtdlRegisterProtoHook(cmd_wiki, "WIKI", "Commands related to Wiki management"); } - /* return our Subversion id for the Log */ - return "$Id$"; + /* return our module name for the log */ + return "wiki"; }