<?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( );