<?php /* LabWiki 1.2.1, 22 August 2012, by Santosh Patnaik, MD, PhD. Based on QwikiWiki 1.5 of David Barrett */ include( "_global.php" ); //////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// Disable Caching ////////////////////////////// //////////////////////////////////////////////////////////////////////////////// QWDisableCaching( ); //////////////////////////////////////////////////////////////////////////////// ////////////////////////// Force Links to Open New Window ////////////////////// //////////////////////////////////////////////////////////////////////////////// $QW['hrefTarget'] = ' onclick="window.open(this.href); return false;" onkeypress="window.open(this.href); return false;"'; //////////////////////////////////////////////////////////////////////////////// ////////////////////////// Guard Against Orphan Pages ////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Verify this page either exists, or is being spawned from a page that exists, // or the user is the admin if( !$QW['userIsAuthenticated'] && !is_file( $QW['pagePath'] ) && (!is_file( $QW['fromPagePath'] ) || is_file( $QW['fromPassPath'] )) ) { // Prompt to login QWRedirect( "login.php" ); exit; } //////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// Access Control /////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Verify there's actually a page set if( !$QW['requestPage'] ) { // Must first log onto this page -- QWRedirect to login QWRedirect( "index.php" ); exit; } // A pasword for this page exists, see if we can authenticate to it if( QWHoldsLockfile( $QW['globalLockPath'], $QW['lockPath'], $_SERVER['REMOTE_ADDR'] ) ) { // Already authenticated and owns the lock } else if( !$QW['pageIsProtected'] || $QW['userIsAuthenticated'] ) { // Authenticated (or not needed), try to get the edit lockfile if( QWCreateLockfile( $QW['globalLockPath'], $QW['lockPath'], $_SERVER['REMOTE_ADDR'] ) ) { // Now authenticated and with the lockfile } else { // Authenticated, but someone else is editing -- QWRedirect to index QWRedirect( "index.php?page=".htmlspecialchars($QW['page']).$QW['URLSuffix']); exit; } } else { // Not authenticated QWRedirect( "login.php?page=".htmlspecialchars($QW['page']).$QW['URLSuffix']); exit; } // IP-based restriction - ; note that this overrides other parallel restrictive measures such as through .htaccess files because the script 'exits.' Can be reset in _config.php if ($QW_CONFIG['ipRestrictsEditing'] == 'yes') // set to 'yes' { if(empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {$IP=$_SERVER["REMOTE_ADDR"];} else {$IP=$_SERVER["HTTP_X_FORWARDED_FOR"];} $lh = gethostbyaddr($_SERVER['REMOTE_ADDR']); $test=$IP.".".$lh; if(!(in_array($test, $QW_CONFIG['ipArray']) || in_array($IP, $QW_CONFIG['ipArray']))) {QWRedirect( "index.php?page=".$QW['page'].$QW['URLSuffix']); exit;} } //////////////////////////////////////////////////////////////////////////////// /////////////////////////////// Process Actions //////////////////////////////// //////////////////////////////////////////////////////////////////////////////// $wikiData = ""; if( $QW['requestAction'] == "Save" || $QW['requestAction'] == "Done" ) { // Update the checked value if( $QW['userIsAuthenticated'] && $QW['requestProtect'] != $QW['pageIsProtected'] ) { // Create or delete the .pass file for this page if( $QW['requestProtect'] ) touch( $QW['passPath'] ); else if( is_file( $QW['passPath'] ) ) unlink( $QW['passPath'] ); $QW['pageIsProtected'] = $QW['requestProtect']; } // Save the page, if there's any data, else delete it if( strlen( $QW['requestWikiData'] ) ) { // // Strip out forbidden HTML $wikiData = strip_tags( $QW['requestWikiData'], $QW_CONFIG['acceptableHTMLTags'] ); // Save the updated data $fp = fopen( $QW['pagePath'], "wb" ); fwrite( $fp, $wikiData, strlen( $wikiData ) ); fclose( $fp ); } else { // Just delete the file, and any associated password if( is_file( $QW['pagePath'] ) ) unlink( $QW['pagePath'] ); if( is_file( $QW['passPath'] ) ) unlink( $QW['passPath'] ); } } if( $QW['requestAction'] == "Done" || $QW['requestAction'] == "Cancel" ) { // Make a backup of the latest version $backupDir = 'backups/'.$QW['page'].'/'; QWVerifyDirectory( $backupDir ); chmod ($backupDir, 0755); $c = 0; do { // Increment the version number $backupPath = sprintf( $backupDir.'/'.$QW['page'].'.%04d.qwiki', $c++ ); } while( is_file( $backupPath ) ); if( is_file( $QW['pagePath'] ) ) copy( $QW['pagePath'], $backupPath ); // Notify the mailing list, if requested if( $QW_CONFIG['emailEnable'] && $QW['requestNotify'] && $QW['requestAction'] == "Done" ) { // Mailing list patterns // **NOTE** If you add more match/replace patterns, be sure put longer matching patterns // before shorter (such as QW_PAGELINK before QW_PAGE) $matchPatternArray = array( '/QW_HOMELINK/', '/QW_PAGELINK/', '/QW_PAGE/', '/QW_UNSUBSCRIBELINK/', '/QW_RESUBSCRIBELINK/', '/QW_BODYTEXT/', '/QW_BODYHTML/', '/QW_CSS/', '/QW_ADMINSIG/', '/QW_TITLE/' ); $replacePatternArray = array( $QW['homeLink'], "$QW[homeLink]/index.php?page=$QW[page]", $QW['page'], "$QW[homeLink]/mailinglist.php?page=$QW[page]&action=unsubscribe&email=QW_MAILINGLISTEMAIL", "$QW[homeLink]/mailinglist.php?page=$QW[page]&action=subscribe&email=QW_MAILINGLISTEMAIL", strip_tags( QWGetFileContents( $QW['pagePath'] ) ), QWFormatQwikiFile( $QW['pagePath'] ), QWGetFileContents( $QW_CONFIG['stylesheetFilename'] ), $QW_CONFIG['adminSig'], $QW_CONFIG['title'] ); // Compose the HTML and text messages $subject = preg_replace( $matchPatternArray, $replacePatternArray, $QW_CONFIG['emailChangedSubject'] ); $textBody = preg_replace( $matchPatternArray, $replacePatternArray, QWGetFileContents( $QW_CONFIG['emailChangedBodyTextFilename'] ) ); $htmlBody = preg_replace( $matchPatternArray, $replacePatternArray, QWGetFileContents( $QW_CONFIG['emailChangedBodyHTMLFilename'] ) ); QWMailMailingList( $QW['mailPath'], $QW_CONFIG['emailFrom'], $subject, $textBody, $htmlBody ); } // Delete the lock file if( file_exists( $QW['lockPath'] ) ) unlink( $QW['lockPath'] ); QWRedirect( "index.php?page=$QW[page]$QW[URLSuffix]" ); exit; } else if( ini_get( 'file_uploads' ) && $QW_CONFIG['enableAttach'] && $QW['requestAction'] == "Attach" ) { // Verify the correct user is attempting to upload a file to this page if( QWHoldsLockfile( $QW['globalLockPath'], $QW['lockPath'], $_SERVER['REMOTE_ADDR'] ) ) { // Verfify there is a file, it's not too big if( $_FILES[ 'userfile' ][ 'size' ] != 0 && $_FILES[ 'userfile' ][ 'size' ] <= $QW_CONFIG['maxUploadSize'] ) { // Verify it's an accepted filetype $pathParts = pathinfo( $_FILES[ 'userfile' ][ 'name' ] ); $extension = $pathParts['extension']; $accept = false; foreach( $QW_CONFIG['acceptableExtensions'] as $testExtension ) if( !strcasecmp( $testExtension, $extension ) ) { // Accept this file $accept = true; break; } // If it's acceptable, copy the file if( $accept ) { // Create this page's attachement directory if( !($errorHTML = QWVerifyDirectory( $QW['attachDir'] )) ) { // Move the uploaded file into the directory $tempFilename= $_FILES[ 'userfile' ][ 'tmp_name' ]; $destFilename = $QW['attachDir'] . "/" . $_FILES[ 'userfile' ][ 'name' ]; move_uploaded_file( $tempFilename, $destFilename ); chmod( $destFilename, 0644 ); } } else { // Invalid extension $errorHTML = "Error - Attachment failed because <em>'.".htmlspecialchars($extension)."'</em> is a blocked extension. Only <em>" . QWCollapseArray( $QW_CONFIG['acceptableExtensions'], ", ", "or " ) . "</em> are allowed." ; } } } } else if( ini_get( 'file_uploads' ) && $QW_CONFIG['enableAttach'] && $QW['requestAction'] == "deletefile" ) { // Verify the correct user is attempting to upload a file to this page if( QWHoldsLockfile( $QW['globalLockPath'], $QW['lockPath'], $_SERVER['REMOTE_ADDR'] ) ) { // Remove any paths added to the string $pathParts = pathinfo( $QW['requestFilename'] ); $path = "$QW[attachDir]/$pathParts[basename]"; if( is_file( $path ) ) { // Delete the file unlink( $path ); } } } //////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// Output Page ////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Attempt to load the existing file $titlePrefix = ""; if( file_exists( $QW['pagePath'] ) ) { // Load the file, if need be if( !$wikiData ) { // Load the data $fp = fopen( $QW['pagePath'], "rb" ); $wikiData = fread( $fp, filesize( $QW['pagePath'] ) ); fclose( $fp ); } $titlePrefix = "Editing document: "; } else { // Set the title $titlePrefix = "Creating document: "; } //////////////////////////////////////////////////////////////////////////////// //////////////////////////// Define Template Functions ///////////////////////// //////////////////////////////////////////////////////////////////////////////// // QWTEditFormatTitle $QW_TEMPLATE['getTitle'] = "QWTEditFormatTitle"; function QWTEditFormatTitle( ) { // Output a title global $titlePrefix, $QW; return $titlePrefix . QWCleanQwikiPageName( $QW['page'] ); } // QWTEditInjectBody $QW_TEMPLATE['injectBody'] = "QWTEditInjectBody"; function QWTEditInjectBody( ) { echo ('<div style="align: center; text-align: center; margin: auto;">'); global $QW, $wikiData, $QW_CONFIG, $errorHTML; // Output the error, if there is any if( $errorHTML ) echo QWFormatMessage( $errorHTML ); ?> <form class="QWForm" id="to_edit" method="post" action="edit.php"> <table class="QWInnerSection"> <tr class="QWInnerSectionTitle"><td>Edit source</td></tr> <tr><td align="center"> <input type="hidden" name="page" value="<?php echo htmlspecialchars($QW['page']); ?>" /> <input type="hidden" name="from" value="<?php echo htmlspecialchars($QW['requestFrom']); ?>" /> <input type="hidden" name="debug" value="<?php echo htmlspecialchars($QW['requestDebug']); ?>" /> <input type="hidden" name="help" value="<?php echo htmlspecialchars($QW['requestHelp']); ?>" /> <textarea name="wikidata" cols="80" rows="30"><?php echo htmlentities( $wikiData ); ?></textarea></td></tr> <tr><td align="center"><em>Done</em> to save and exit; <em>save</em> to save but not exit and preview changes below<br /><input type="submit" name="action" value="Done" /><input type="submit" name="action" value="Save" /><input type="submit" name="action" value="Cancel" /></td></tr> <?php if( is_file( $QW['mailPath'] ) && !empty($QW_CONFIG['emailEnable'])) { ?> <tr><td align='center'><input type="checkbox" name="notify" checked="checked" /> Notify the <strong><?php echo htmlspecialchars($QW['page']); ?></strong> mailing list when done</td></tr> <?php } ?> <?php if( $QW['userIsAuthenticated'] ) { if( $QW_CONFIG['globalEditLock'] ) { // Page cannot be individually locked due to global edit lock ?> <tr><td align="center"> <input type="hidden" name="protect" id="protect" value="<?php echo $QW['pageIsProtected']; ?>" />Only an administrator can edit <em><?php echo htmlspecialchars($QW['page']); ?></em> because global edit locking is <strong>enabled</strong>! </td></tr> <?php } else { // Allow the page to be individually locked $isChecked = ( $QW['pageIsProtected'] ? 'checked = "checked"' : '' ); ?><tr><td align="center"><input <?php echo $isChecked; ?> type="checkbox" name="protect" /> Prevent non-administrator users from editing the <em><?php echo htmlspecialchars($QW['page']); ?></em> page</td></tr><?php } } ?> </table> </form> <?php QWFormatHelp( "To edit the page, modify the text in the edit box above. See " . QWFormatQwikiPageName('Adding_or_editing_content') . " for instructions on how to autoformat your source text using wiki syntax rules, or use the following HTML tags: <br /><br />" . htmlspecialchars( wordwrap( $QW_CONFIG['acceptableHTMLTags'] , 50, '<br />', 1) ) . "<br /><br /> Click <strong>Save</strong> to save your changes and show them in the preview box below. When finished, click <strong>Done</strong> to save your changes and return to the page. Do NOT click the <em>Back</em> button on your web browser. Instead, if you are done editing, click <strong>Done</strong> or <strong>Cancel</strong>. If you click <em>Back</em>, you will leave the page locked and will not be able to edit again until the lock expires.<br />" . ($QW_CONFIG['emailEnable'] && is_file( $QW['mailPath'] ) ? "<br />Be sure to check the <strong>Notify</strong> checkbox if you want to notify people on the mailing list that the page has changed.<br />" : "" ) .( $QW['userIsAuthenticated'] ? "<br />Check <em>Prevent non-administraor users from editing</em> to require logging-in with the administrator password before allowing editing.<br />" : "" ) . ( ini_get( 'file_uploads' ) && $QW_CONFIG['enableAttach'] ? "<br />To add a <em>" . QWCollapseArray( $QW_CONFIG['acceptableExtensions'], ", ", "or " ) . "</em> file attachment to this page, click <strong>Choose File</strong> to select the file from your hard drive, and then click <strong>Attach</strong> to attach it to the page. To delete a file attachment, click <strong>Delete</strong> next to the attachment to delete.<br />" : "" ), "edit.php?page=$QW[page]" ); ?> <hr /> <table class="QWInnerSection"> <tr class="QWInnerSectionTitle"><td align="center">Attachments</td></tr> </table> <hr /> <?php if( ini_get( 'file_uploads' ) && $QW_CONFIG['enableAttach'] ) { ?> <form class="QWForm" id="for_files" method="post" enctype="multipart/form-data" action="edit.php"> <table class="QWInnerSection"> <tr class="QWInnerSectionTitle"><td align="left">Filename</td><td align="center">Filesize</td><td align="right">Action</td></tr> <?php $numLines = 0; if( is_dir( $QW['attachDir'] ) ) { $attachDir = dir( $QW['attachDir'] ); while( $filename = $attachDir->read( ) ) { if( $filename != "." && $filename != ".." ) { ++$numLines; $attachPath = $QW['attachDir'].'/'.$filename; $nameHTML = '<a href="'.htmlspecialchars($attachPath).'" '.$QW['hrefTarget'].'>'.htmlspecialchars($filename).'</a>'; $sizeHTML = QWFormatFilesize( filesize( $attachPath ) ); $commandHTML = '<a href="edit.php?page=' . htmlspecialchars($QW['page']) . '&action=deletefile&filename=' . htmlspecialchars($filename) . '">delete</a>'; echo '<tr><td align="left">'.$nameHTML.'</td><td align="center">'.$sizeHTML.'</td><td align="right">'.$commandHTML.'</td></tr>'; } } $attachDir->close( ); } if( !$numLines ) { // Output that there are no attachments echo '<tr><td align="center" colspan="2">No attached files.<br />To attach a file, <em>choose file</em> and <em>attach</em></td></tr>'; }?> <tr><td align='center' colspan="3"> <input type="hidden" name="page" value="<?php echo htmlspecialchars($QW['page']); ?>" /> <input type="hidden" name="from" value="<?php echo htmlspecialchars($QW['requestFrom']); ?>" /> <input type="hidden" name="debug" value="<?php echo htmlspecialchars($QW['requestDebug']); ?>" /> <input type="hidden" name="MAX_FILE_size" value="<?php echo $QW_CONFIG['maxUploadSize']; ?>" /> <input size="40" type="file" name="userfile" /> <input type="submit" name="action" value="Attach" /></td></tr> </table> </form> <br /> <?php } ?> <hr /> <div style="align: center; text-align: center; margin: auto;"> <table class="QWInnerSection"> <tr class="QWInnerSectionTitle"><td>Preview formatted</td></tr> </table> </div> <hr /> <?php echo QWFormatQwikiFile( $QW['pagePath'] ); ?> </div> <?php } //////////////////////////////////////////////////////////////////////////////// ////////////////////////////// Fill Template /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Include the template include( $QW_CONFIG['templateFilename'] ); // Output debugging, if requested if( $QW_CONFIG['enableDebugging'] && $QW['requestDebug'] ) echo QWFormatDebug( );