Example #1
0
function do_post_savepage($formatter, $options)
{
    global $DBInfo;
    if ($_SERVER['REQUEST_METHOD'] != 'POST' || !$DBInfo->security->writable($options)) {
        $options['title'] = _("Page is not writable");
        $options['button_preview'] = 1;
        // force preview
    }
    if (isset($_FILES['upfile']) and is_array($_FILES) or isset($options['MYFILES']) and is_array($options['MYFILES'])) {
        $retstr = false;
        $options['retval'] =& $retstr;
        include_once 'plugin/UploadFile.php';
        do_uploadfile($formatter, $options);
    }
    $savetext = $options['savetext'];
    $datestamp = $options['datestamp'];
    $hash = $options['hash'];
    $button_preview = !empty($options['button_preview']) ? 1 : 0;
    if ($button_preview) {
        $formatter->preview = 1;
    }
    $button_merge = !empty($options['button_merge']) ? 1 : 0;
    $button_merge = !empty($options['manual_merge']) ? 2 : $button_merge;
    $button_merge = !empty($options['force_merge']) ? 3 : $button_merge;
    $button_diff = !empty($options['button_changes']) ? 1 : 0;
    if ($button_diff) {
        $button_preview = 1;
    }
    $savetext = preg_replace("/\r\n|\r/", "\n", $savetext);
    $savetext = _stripslashes($savetext);
    $comment = _stripslashes($options['comment']);
    $comment = trim($comment);
    $section_savetext = '';
    if (isset($options['section'])) {
        if ($formatter->page->exists()) {
            $sections = _get_sections($formatter->page->get_raw_body());
            if ($sections[$options['section']]) {
                if (substr($savetext, -1) != "\n") {
                    $savetext .= "\n";
                }
                $sections[$options['section']] = $savetext;
            }
            $section_savetext = $savetext;
            $savetext = implode('', $sections);
        }
    }
    if ($savetext and $savetext[strlen($savetext) - 1] != "\n") {
        $savetext .= "\n";
    }
    $new = md5($savetext);
    $menu = $formatter->link_to("#editor", _("Goto Editor"), ' class="preview-anchor"');
    $diff = '';
    if ($formatter->page->exists()) {
        # check difference
        $body = $formatter->page->get_raw_body();
        $body = preg_replace("/\r\n|\r/", "\n", $body);
        $orig = md5($body);
        if ($orig == $new) {
            // same text. just update datestamp
            unset($options['datestamp']);
            $datestamp = $formatter->page->mtime();
        }
        # check datestamp
        if ($formatter->page->mtime() > $datestamp) {
            $options['msg'] = sprintf(_("Someone else saved the page while you edited %s"), $formatter->link_tag($formatter->page->urlname, "", _html_escape($options['page'])));
            $options['preview'] = 1;
            $options['conflict'] = 1;
            if ($button_merge) {
                $options['msg'] = sprintf(_("%s is merged with latest contents."), $formatter->link_tag($formatter->page->urlname, "", _html_escape($options['page'])));
                $options['title'] = sprintf(_("%s is merged successfully"), _html_escape($options['page']));
                $merge = $formatter->get_merge($savetext);
                if (preg_grep('/^<<<<<<<$/', explode("\n", $merge))) {
                    $options['conflict'] = 2;
                    $options['title'] = sprintf(_("Merge conflicts are detected for %s !"), _html_escape($options['page']));
                    $options['msg'] = sprintf(_("Merge cancelled on %s."), $formatter->link_tag($formatter->page->urlname, "", _html_escape($options['page'])));
                    $merge = preg_replace('/^>>>>>>>$/m', "=== /!\\ >>>>>>> " . _("NEW") . ' ===', $merge);
                    $merge = preg_replace('/^<<<<<<<$/m', "=== /!\\ <<<<<<< " . _("OLD") . ' ===', $merge);
                    $merge = preg_replace('/^=======$/m', "=== ======= ===", $merge);
                    if ($button_merge > 1) {
                        unset($options['datestamp']);
                        unset($options['section']);
                        unset($section_savetext);
                        $datestamp = $formatter->page->mtime();
                        $options['conflict'] = 0;
                        if ($button_merge == 2) {
                            $options['title'] = sprintf(_("Get merge conflicts for %s"), _html_escape($options['page']));
                            $options['msg'] = sprintf(_("Please resolve conflicts manually."));
                            if ($merge) {
                                $savetext = $merge;
                            }
                        } else {
                            $options['title'] = sprintf(_("Force merging for %s !"), _html_escape($options['page']));
                            $options['msg'] = sprintf(_("Please be careful, you could damage useful information."));
                        }
                    }
                } else {
                    $options['conflict'] = 0;
                    if ($merge) {
                        // successfully merged. reset datestamp
                        $savetext = $merge;
                        unset($options['datestamp']);
                        $datestamp = $formatter->page->mtime();
                    }
                }
                $button_preview = 1;
            } else {
                $options['title'] = _("Conflict error!");
                $button_preview = 1;
            }
            if ($options['conflict'] and !empty($merge)) {
                $diff = $formatter->get_diff($merge);
            } else {
                $diff = $formatter->get_diff($savetext);
            }
            // get diff
        } else {
            if ($datestamp > time()) {
                $options['msg'] = sprintf(_("Go back or return to %s"), $formatter->link_tag($formatter->page->urlname, "", _html_escape($options['page'])));
                $formatter->send_header("", $options);
                $formatter->send_title(_("Invalid access"), "", $options);
                $formatter->send_footer();
                return;
            } else {
                if (!empty($DBInfo->use_savepage_hash)) {
                    // check hash
                    $ticket = getTicket($datestamp . $DBInfo->user->id, $_SERVER['REMOTE_ADDR']);
                    if ($hash != md5($ticket)) {
                        $formatter->send_header("", $options);
                        $formatter->send_title(_("Invalid access"), "", $options);
                        $formatter->send_footer();
                        return;
                    }
                }
            }
        }
    }
    if (empty($button_preview) && !empty($orig) && $orig == $new) {
        $options['msg'] = sprintf(_("Go back or return to %s"), $formatter->link_tag($formatter->page->urlname, "", _html_escape($options['page'])));
        $formatter->send_header("", $options);
        $formatter->send_title(_("No difference found"), "", $options);
        $formatter->send_footer();
        return;
    }
    if ($comment && (function_exists('mb_strlen') and mb_strlen($comment, $DBInfo->charset) > 256) or strlen($comment) > 256) {
        //$options['msg']=sprintf(_("Go back or return to %s"),$formatter->link_tag($formatter->page->urlname,"",_html_escape($options['page'])));
        $options['title'] = _("Too long Comment");
        $button_preview = 1;
    }
    // XXX captcha
    $use_any = 0;
    if (!empty($DBInfo->use_textbrowsers)) {
        if (is_string($DBInfo->use_textbrowsers)) {
            $use_any = preg_match('/' . $DBInfo->use_textbrowsers . '/', $_SERVER['HTTP_USER_AGENT']) ? 1 : 0;
        } else {
            $use_any = preg_match('/Lynx|w3m|links/', $_SERVER['HTTP_USER_AGENT']) ? 1 : 0;
        }
    }
    $ok_ticket = 0;
    if (!$button_preview and !$use_any and !empty($DBInfo->use_ticket) and $options['id'] == 'Anonymous') {
        if ($options['__seed'] and $options['check']) {
            $mycheck = getTicket($options['__seed'], $_SERVER['REMOTE_ADDR'], 4);
            if ($mycheck == $options['check']) {
                $ok_ticket = 1;
            } else {
                $options['msg'] = _("Invalid ticket !");
                $button_preview = 1;
            }
        } else {
            if (!$button_preview) {
                $options['msg'] = _("You need a ticket !");
            }
            $button_preview = 1;
        }
    } else {
        $ok_ticket = 1;
    }
    // XXX
    if (!$button_preview and $DBInfo->spam_filter) {
        $text = $savetext;
        $fts = preg_split('/(\\||,)/', $DBInfo->spam_filter);
        foreach ($fts as $ft) {
            $text = $formatter->filter_repl($ft, $text, $options);
        }
        if ($text != $savetext) {
            $button_preview = 1;
            $options['msg'] = _("Sorry, can not save page because some messages are blocked in this wiki.");
        } else {
            if ($options['id'] == 'Anonymous' and !empty($comment) and !empty($DBInfo->spam_comment_filter)) {
                // comment filter for anonymous users
                $cmt = $comment;
                $fts = preg_split('/(\\||,)/', $DBInfo->spam_comment_filter);
                // bad comments file
                $options['.badcontents'] = !empty($DBInfo->comments_badcontents) ? $DBInfo->comments_badcontents : null;
                foreach ($fts as $ft) {
                    $cmt = $formatter->filter_repl($ft, $cmt, $options);
                }
                if ($cmt != $comment) {
                    $button_preview = 1;
                    $options['msg'] = _("Sorry, can not save page because some messages are blocked in this wiki.");
                }
            }
        }
    }
    $formatter->page->set_raw_body($savetext);
    // check license agreement
    $ok_agreement = true;
    if (!empty($DBInfo->use_agreement)) {
        if ($options['id'] != 'Anonymous') {
            $ok_agreement = !empty($DBInfo->user->info['join_agreement']) && $DBInfo->user->info['join_agreement'] == 'agree';
            if ($ok_agreement && !empty($DBInfo->agreement_version)) {
                $ok_agreement = $DBInfo->user->info['join_agreement_version'] == $DBInfo->agreement_version;
            }
        } else {
            $ok_agreement = false;
        }
    }
    if (empty($button_preview) && !$ok_agreement && empty($options['license_agree'])) {
        $button_preview = 1;
        if ($options['id'] == 'Anonymous') {
            $options['msg'] = _("Anonymous user have to agree the contribution agreement for this wiki.");
        } else {
            $options['msg'] = _("Sorry, you have to agree the contribution agreement or the join agreement of this wiki.");
        }
    }
    // check full permission to edit
    $full_permission = true;
    if (!empty($DBInfo->no_full_edit_permission) or $options['id'] == 'Anonymous' && !empty($DBInfo->anonymous_no_full_edit_permission)) {
        $full_permission = false;
    }
    // members always have full permission to edit
    if (in_array($options['id'], $DBInfo->members)) {
        $full_permission = true;
    }
    $minorfix = false;
    $options['editinfo'] = array();
    if (!$full_permission || !empty($DBInfo->use_abusefilter)) {
        // get diff
        if (!isset($diff[0])) {
            $diff = $formatter->get_diff($savetext);
        }
        // get total line numbers
        // test \n or \r or \r\n
        $crlf = "\n";
        if (preg_match("/(\r|\r\n|\n)\$/", $body, $match)) {
            $crlf = $match[1];
        }
        // count crlf
        $nline = substr_count($body, $crlf);
        // count diff lines, chars
        $changes = diffcount_lines($diff, $DBInfo->charset);
        // set return values
        $added = $changes[0];
        $deleted = $changes[1];
        $added_chars = $changes[2];
        $deleted_chars = $changes[3];
        // check minorfix
        $minorfix = $changes[4];
        $editinfo = array('add_lines' => $added, 'del_lines' => $deleted, 'add_chars' => $added_chars, 'del_chars' => $deleted_chars);
        $options['editinfo'] = $editinfo;
        if (!$button_diff) {
            $diff = '';
        }
    }
    if (!$full_permission) {
        $restricted = false;
        $delete_lines_restricted_ratio = !empty($DBInfo->allowed_max_lines_delete_ratio) ? $DBInfo->allowed_max_lines_delete_ratio : 0.5;
        if ($deleted > 0 && $deleted / $nline > $delete_lines_restricted_ratio) {
            $restricted = true;
        }
        // check the maximum number of characters allowed to add/delete
        $max_chars_add = !empty($DBInfo->allowed_max_chars_add) ? $DBInfo->allowed_max_chars_add : 300;
        $max_chars_del = !empty($DBInfo->allowed_max_chars_delete) ? $DBInfo->allowed_max_chars_delete : 180;
        if (!$restricted && ($added_chars > $max_chars_add || $deleted_chars > $max_chars_del)) {
            $restricted = true;
        }
        if ($restricted) {
            $options['title'] = _("You do not have full permission to edit this page on this wiki.");
            if ($options['id'] == 'Anonymous') {
                $options['msg'] = _("Anonymous user is restricted to delete a lot amount of page on this wiki.");
            } else {
                $options['msg'] = _("You are restricted to delete a lot amount of page on this wiki.");
            }
            $button_preview = true;
        }
    }
    if ($button_preview) {
        if (empty($options['title'])) {
            $options['title'] = sprintf(_("Preview of %s"), _html_escape($options['page']));
        }
        // http://stackoverflow.com/questions/1547884
        $header = '';
        if (!empty($DBInfo->preview_no_xss_protection)) {
            $header = 'X-XSS-Protection: 0';
        }
        $formatter->send_header($header, $options);
        $formatter->send_title("", "", $options);
        $options['preview'] = 1;
        $options['datestamp'] = $datestamp;
        $savetext = $section_savetext ? $section_savetext : $savetext;
        $options['savetext'] = $savetext;
        $formatter->preview = 1;
        $has_form = false;
        $options['has_form'] =& $has_form;
        $options['.minorfix'] = $minorfix;
        print '<div id="editor_area_wrap">' . macro_EditText($formatter, '', $options);
        echo $formatter->get_javascripts();
        if ($has_form and !empty($DBInfo->use_jsbuttons)) {
            $msg = _("Save");
            $onclick = ' onclick="submit_all_forms()"';
            $onclick1 = ' onclick="check_uploadform(this)"';
            echo "<div id='save-buttons'>\n";
            echo "<button type='button'{$onclick} tabindex='10'><span>{$msg}</span></button>\n";
            echo "<button type='button'{$onclick1} tabindex='11' name='button_preview' value='1'><span>" . _("Preview") . '</span></button>';
            if ($formatter->page->exists()) {
                echo "\n<button type='button'{$onclick1} tabindex='12' name='button_changes' value='1'><span>" . _("Show changes") . '</span></button>';
            }
            if ($button_preview) {
                echo ' ' . $formatter->link_to('#preview', _("Skip to preview"), ' class="preview-anchor"');
            }
            echo "</div>\n";
        }
        print '</div>';
        # XXX
        print $DBInfo->hr;
        print $menu;
        if ($button_diff and !isset($diff[0])) {
            $diff = $formatter->get_diff($options['section'] ? implode('', $sections) : $savetext);
            // get diff
            // strip diff header
            if (($p = strpos($diff, '@@')) !== false) {
                $diff = substr($diff, $p);
            }
        }
        if (isset($diff[0])) {
            echo "<div id='wikiDiffPreview'>\n";
            echo $formatter->processor_repl('diff', $diff, $options);
            //echo $formatter->macro_repl('Diff','',array('text'=>$diff,'type'=>'fancy'));
            echo "</div>\n";
        }
        print "<div id='wikiPreview'>\n";
        #$formatter->preview=1;
        $formatter->send_page($savetext);
        $formatter->preview = 0;
        print $DBInfo->hr;
        print "</div>\n";
        print $menu;
    } else {
        // check minorfix
        $options['.minorfix'] = $minorfix;
        if (empty($DBInfo->use_autodetect_minoredit)) {
            unset($options['.minorfix']);
        }
        if (!empty($options['category'])) {
            $savetext .= "----\n[[" . $options['category'] . "]]\n";
        }
        $options['minor'] = !empty($DBInfo->use_minoredit) ? $options['minor'] : 0;
        if ($options['minor']) {
            $user = $DBInfo->user;
            # get from COOKIE VARS
            if ($DBInfo->owners and in_array($user->id, $DBInfo->owners)) {
                $options['minor'] = 1;
            } else {
                $options['minor'] = 0;
            }
        }
        $formatter->page->write($savetext);
        $retval = array();
        $options['retval'] =& $retval;
        $ret = $DBInfo->savePage($formatter->page, $comment, $options);
        if ($ret != -1 and $DBInfo->notify and $options['minor'] != 1) {
            $options['noaction'] = 1;
            if (!function_exists('mail')) {
                $options['msg'] = sprintf(_("mail does not supported by default.")) . "<br />";
            } else {
                $ret2 = wiki_notify($formatter, $options);
                if ($ret2) {
                    $options['msg'] = sprintf(_("Sent notification mail.")) . "<br />";
                } else {
                    $options['msg'] = sprintf(_("No subscribers found.")) . "<br />";
                }
            }
        }
        if ($ret == -1) {
            if (!empty($options['retval']['msg'])) {
                $msg = $options['retval']['msg'];
            } else {
                $msg = sprintf(_("%s is not editable"), $formatter->link_tag($formatter->page->urlname, "", _html_escape($options['page'])));
            }
            $options['title'] = $msg;
        } else {
            $options['title'] = sprintf(_("%s is saved"), $formatter->link_tag($formatter->page->urlname, "?action=show", _html_escape($options['page'])));
        }
        $myrefresh = '';
        if (!empty($DBInfo->use_save_refresh)) {
            $lnk = $formatter->link_url($formatter->page->urlname, "?action=show");
            if (!empty($options['section'])) {
                $lnk .= '#sect-' . $options['section'];
            }
            if ($DBInfo->use_save_refresh > 0 || $ret == -1) {
                $sec = $DBInfo->use_save_refresh - 1;
                if ($sec < 0) {
                    $sec = 3;
                }
                $myrefresh = 'Refresh: ' . $sec . '; url=' . qualifiedURL($lnk);
            } else {
                $myrefresh = array('Status: 302', 'Location: ' . qualifiedURL($lnk));
            }
        }
        $formatter->send_header($myrefresh, $options);
        if (is_array($myrefresh)) {
            return;
        }
        $formatter->send_title("", "", $options);
        $opt['pagelinks'] = 1;
        $opt['refresh'] = 1;
        $formatter->page->pi = null;
        // call get_instruction() again
        # re-generates pagelinks
        print "<div id='wikiContent'>\n";
        $formatter->send_page("", $opt);
        print "</div>\n";
    }
    $args['editable'] = 0;
    $formatter->send_footer($args, $options);
}
Example #2
0
 function _savePage($pagename, $body, $options = array())
 {
     $keyname = $this->_getPageKey($pagename);
     $filename = $this->text_dir . '/' . $keyname;
     $dir = dirname($filename);
     if (!is_dir($dir)) {
         $om = umask(~$this->umask);
         _mkdir_p($dir, 0777);
         umask($om);
     }
     $is_new = false;
     if (!file_exists($filename)) {
         $is_new = true;
     }
     $fp = @fopen($filename, "a+b");
     if (!is_resource($fp)) {
         return -1;
     }
     flock($fp, LOCK_EX);
     // XXX
     ftruncate($fp, 0);
     fwrite($fp, $body);
     flock($fp, LOCK_UN);
     fclose($fp);
     $ret = 0;
     if (!empty($this->version_class)) {
         $om = umask(~$this->umask);
         $ver = $this->lazyLoad('version', $this);
         // get diff
         if (!$is_new) {
             $diff = $ver->diff($pagename);
             // count diff lines, chars
             $changes = diffcount_lines($diff, $this->charset);
             // set return values
             $retval =& $options['retval'];
             $retval['add'] = $changes[0];
             $retval['del'] = $changes[1];
             $retval['add_chars'] = $changes[2];
             $retval['del_chars'] = $changes[3];
         } else {
             // new file.
             // set return values
             $retval =& $options['retval'];
             $retval['add'] = get_file_lines($filename);
             $retval['del'] = 0;
             $retval['add_chars'] = mb_strlen($body, $this->charset);
             $retval['del_chars'] = 0;
         }
         $force = $is_new || $options['.force'];
         // FIXME fix for revert+create cases for clear
         if ($is_new && preg_match('@;;{REVERT}@', $options['log'])) {
             $tmp = preg_replace('@;;{REVERT}:@', ';;{CREATE}{REVERT}:', $options['log']);
             if ($tmp !== null) {
                 $options['log'] = $tmp;
             }
         }
         $ret = $ver->_ci($filename, $options['log'], $force);
         if ($ret == -1) {
             $options['retval']['msg'] = _("Fail to save version information");
         }
         chmod($filename, 0666 & $this->umask);
         umask($om);
     }
     return $ret;
 }