and . //See http://www.tero.co.uk/scripts/onepagecms.php for more information //From 7/12/2009 this editor can also handle images! From 23/6/2010, you can login from a form. //From 25/8/2010 it uses TinyMCE's built-in image list //Specify which files are allowed to be edited. This accepts wildcards and can be an array, eg: //$ALLOWEDFILES = array ("home/*.php", "about/*.html"); $ALLOWEDFILES = '*.html'; //Directory where we should save backups every time a file is edited. Leave blank to disable this feature $BACKUPDIR = 'onepagecmsbackups/'; //Directory where images should be (or are already) stored. Leave blank to disable this feature. $IMAGEDIR = 'onepagecmsimages/'; //If we want to use the TinyMCE editor, pass in the theme. Can be blank for no editor, simple, or advanced. //Note that this uses the Javascript files from the TinyMCE server, with some extra code to allow popups //and inserting images to work. $HTMLEDITOR = 'advanced'; //leave blank to disable //User name and password. If this kind of login doesn't work, change PhpAuthLogin to FormLogin at the bottom $USERNAME = 'onepagecms'; $PASSWORD = 'uYadfIfJa'; /////////////////////////////// Helpful functions /////////////////////////////// //This gets all files matching $match. It looks recursively using glob or the find command. function GetMatchingFiles ($matches) { if (!is_array ($matches)) $matches = array ($matches); //the things to match $files = array(); //the array of files foreach ($matches as $match) { //if the glob function exists if (function_exists ("glob") && ($globfiles = glob ($match)) && is_array ($globfiles)) $files = array_merge ($files, $globfiles); //or else use the find function else if (function_exists ('exec') && exec ('find ' . dirname ($match) . ' -type f | grep "' . str_replace ('*', '.*', str_replace ('.', '\.', basename ($match))) . '"', $findfiles) && is_array ($findfiles)) $files = array_merge ($files, $findfiles); //or else loop through each one as if it were a directory, added 3/10/2010 else if (preg_match ('/\*/', $match) && ($dh = opendir ($filedir = dirname ($match)))) { $match = (str_replace ('*', '.*', str_replace ('.', '\.', "~$match~"))); while (false!==($file=readdir($dh))) if (is_file($file="$filedir/$file") && preg_match ($match,$file)) array_push ($files, $file); } //or else just add the file else array_push ($files, $match); } return $files; } //Get the image files from a directory and its subdirectories function GetImageFiles ($imagedir) { $imageendings = array ('gif', 'jpg', 'jpeg', 'png'); $a = array(); foreach ($imageendings as $ending) $a = array_merge ($a, GetMatchingFiles ("$imagedir*.$ending")); $images = array(); foreach ($a as $image) $images[$image] = preg_replace ("|^$imagedir|", '', $image); //with and without the directory return $images; } //This gets the editable areas from a file function GetEditableAreas ($file) { $areas = array(); //this is an array of editable areas $fc = file_get_contents ($file); //get the file conents //Get all the editable areas, s is so that . matches multiline, U is for ungreedy preg_match_all ('/(.*)/sU', $fc, $matches, PREG_SET_ORDER); //Loop through the matches and put them into an array, also removing any \r characters that might get entered foreach ($matches as $m) array_push ($areas, array (ucwords (str_replace ('-', ' ', $m[1])), $m[2])); //Return the editable areas which is an array of arrays each with 2 elements for the name and text return $areas; } //For saving a file function SaveFile ($file, $areas, $backupdir='') { //First check we can save the data if (!$areas) return "There is no data to save"; $fc = file_get_contents ($file); //get the file conents if (!$fc) return "Could not read the file $file"; //Now get allthe parts with tags $parts = preg_split ('/()/', $fc, -1, PREG_SPLIT_DELIM_CAPTURE); //split by the ONEPAGECMS tags if (count ($parts) != count ($areas) * 4 + 1) return "There are the wrong number of ONEPAGECMS tags in the file"; $newcontents = array_shift ($parts); //get the first bit before the first ONEPAGECMS tag //For each editable area, get the START tag, the editable area, the end tag, then the part after the END tag foreach ($areas as $i=>$area) //remove slashes and \r from the data being saved $newcontents .= $parts[$i*4] . "\n" . trim (stripSlashes (preg_replace ("/\r\n?/", "\n", $areas[$i]))) . "\n" . $parts[$i*4 + 2] . $parts[$i*4+3]; //Backup the file before saving it, and make the backup world writeable so it can be deleted via FTP $backupminutes = 5; //only backup files if they were last saved more than $backupminutes ago - eg don't backup for tiny quick changes if ($backupdir && is_file ($file) && ($backupstat = stat ($file)) && ($backupstat['mtime'] < time() - 60 * $backupminutes)) { if (!is_dir ($backupdir)) {mkdir ($backupdir); chmod ($backupdir, 0777);} copy ($file, $backupfile = $backupdir . '/' . str_replace ('/', '-', $file) . '.' . date ('Y-m-d-Hi') . '.backup'); if (file_exists ($backupfile)) chmod ($backupfile, 0666); } //Save the contents $fw = fopen ($file, 'w'); //try to open the file for writing if (!$fw) return "Could not write to the file $file. Please check the permissions."; //Save the file fwrite ($fw, $newcontents); fclose ($fw); return "File was saved successfully."; } //Saving the images function SaveImages ($imagedir) { $imageendings = array ('gif', 'jpg', 'jpeg', 'png'); $m = array(); if (!is_dir ($imagedir)) {mkdir ($imagedir); chmod ($imagedir, 0777);} //Check it's the right endings, etc if (isset ($_POST['remove'])) foreach ($_POST['remove'] as $image) if (preg_match ("~^$imagedir.+\." . join ('|', $imageendings) . '$~', $image)) {$m[] = "Removing $image"; unlink ($image);} else $m[] = "Cannot remove $image (perhaps because of the file ending)"; foreach ($_FILES as $formfield=>$filedata) { if (!$filedata['size']) continue; //nothing to upload $moveto = $imagedir . $filedata['name']; if ($filedata['error']) $m[] = "Could not upload $filedata[name] because of: $filedata[error]"; else if (!preg_match ('~\.' . join ('|', $imageendings) . '$~', $filedata['name'])) $m[] = "Cannot upload $filedata[name] (wrong ending)"; else {$m[] = "Saving $moveto"; move_uploaded_file ($filedata['tmp_name'], $moveto); chmod ($moveto, 0666);} } return join ('
', $m); } //Function for logging in using PhpAuth function PhpAuthLogin ($username, $password) { $u = isset ($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : ''; $p = isset ($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : ''; if ($username != $u || $password != $p) { header ('WWW-Authenticate: Basic realm="One Page CMS"'); header ("HTTP/1.0 401 Unauthorized"); print '

One Page CMS

You are not authorised to access this '; print 'One Page CMS. '; print 'Reload this page to try again,
'; print 'especially if you have just logged out, and want to log back in.'; exit; } } //Function for logging in from a form function FormLogin ($username, $password) { if (!isset ($_SESSION)) session_start(); //start the sessions if (isset ($_GET['logout'])) $_SESSION['AUTH_OK'] = ''; //logged out $u = isset ($_POST['AUTH_USER']) ? $_POST['AUTH_USER'] : ''; //from posted variable $p = isset ($_POST['AUTH_PW']) ? $_POST['AUTH_PW'] : ''; if ($username == $u && $password == $p) {$_SESSION['AUTH_OK'] = $u; return;} //successful login from the form if (isset ($_SESSION['AUTH_OK']) && $_SESSION['AUTH_OK']==$username) return; //previous login from the session echo '

One Page CMS

'; //not logged in if ($u || $p) echo '

Your login details were incorrect, please try again:

'; //previous unsuccessful login else echo '

Please enter your login details below:

'; echo '
'; //clears logout echo 'User name:
'; echo 'Password:
'; echo '

'; exit; } /////////////////////////////// Advanced editor /////////////////////////////// //This code helps make the advanced TinyMCE editor work. When using the advanced editor, all files required from the editor //are passed through onepagecms.php first. This means they will all appear to be coming from the local domain and avoids //Javascript security alerts and problems. It also means that I can hack the image inserter so that it shows a drop down //list of images from $IMAGEDIR. (Hack removed 25/8/2010 so it now uses externam_image_list_url which means it will work //even if you download your own copy of TinyMCE.) function ProcessEditor ($imagedir) { //If they just want the images, added 25/8/2010 to use external_image_list_url if (isset ($_GET['editorimages'])) { $ei=''; foreach (GetImageFiles ($imagedir) as $src=>$image) $ei .= "\n,['$image', '$src']"; //add the images to an array header ("Content-type: application/javascript"); //output the mime type header for a Javascript files echo 'var tinyMCEImageList = new Array (' . substr ($ei, 2) . ');'; //output the array exit; //exit } if (!preg_match ('|EDITOR/(.*)$|', $_SERVER['REQUEST_URI'], $ed)) return; if (preg_match ('/css$/', $ed[1])) header ("Content-type: text/css"); //output the mime type header for CSS files //If this has been requested before (or it's image.htm), then just return the Cached version //if (basename ($ed[1]) != 'image.htm' && isset ($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { //it's been requested before if (isset ($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { //it's been requested before header ("Expires: Sat, 6 Mar 1976 10:00:00 GMT"); //expire the page at some time in the past header ("Cache-Control: private, must-revalidate"); //let them cache it header ("Pragma: cache"); //override the default header to reallow caching header ("HTTP/1.0 304 Not Modified"); exit; } //Or else get the file contents over the Internet and return them $contents = file_get_contents ('http://tinymce.moxiecode.com/js/tinymce/' . rawurldecode ($ed[1])); //get the contents of the file //This was the hacky way of getting the image list into TinyMCE, I can now do this much more easily using external_image_list_url, 25/8/2010 //if (basename ($ed[1]) == 'image.htm' && ($idpos = strpos ($contents, 'id="src"'))) { //this is the image uploading HTML file // $select = ''; // $trpos = strpos ($contents, '', $idpos); // if ($images && $trpos) $contents = substr ($contents, 0, $trpos) . $select . substr ($contents, $trpos); //} else header ("Last-Modified: " . gmdate ("D, d M Y H:i:s")); //send now as the last modified date header ("Last-Modified: " . gmdate ("D, d M Y H:i:s")); //send now as the last modified date echo $contents; exit; } /////////////////////////////// Outputting the page /////////////////////////////// function OutputPage ($allowedfiles, $backupdir='', $htmleditor='', $imagedir='') { $me = basename ($_SERVER['PHP_SELF']); //my page name - SCRIPT_NAME didn't work on Windows servers $areawidth = 100; //the width in columns of the text area $filestoedit = GetMatchingFiles ($allowedfiles); //files I am allowed to edit $imagemanager = isset ($_GET['imagemanager']) ? $_GET['imagemanager'] : ''; //should we show the image manager $editfile = isset ($_GET['file']) ? $_GET['file'] : ''; //the file they want to edit if (!in_array ($editfile, $filestoedit)) $editfile = ''; //the file must be in the array of allowed files $editareas = $editfile ? GetEditableAreas ($editfile) : array(); //the areas to edit $saveimages = isset ($_POST['imagemanager']) ? $_POST['imagemanager'] : ''; //if there are images to save if ($saveimages) $imagemanager = true; //we should view the image manager if saving images $savefile = isset ($_POST['file']) ? $_POST['file'] : ''; //if there is a file to save if (!in_array ($savefile, $filestoedit)) $savefile = ''; //the file must be in the array of allowed files $saveareas = $savefile && isset ($_POST['areas']) ? $_POST['areas'] : array(); //areas of the page to save ?> One Page CMS

One Page CMS

Files you can edit

Welcome to the One Page CMS. These are the files which you are
allowed to edit. Close your browser or click here to log out.
If you find this script useful, please send a donation.

Saving the file

Saving the file (view). Any errors in saving will appear here...

Editing the file

Please edit the in the areas below and then click save. Sorry but $editfile does not have any editable areas.

"; ?> and in normal textarea ?>

'; ?>

Saving images

Saving the images. Any errors in saving will appear here...

Manage images

Use the links below to view, remove and upload images to .