5 Jappix - An open social platform
6 These are the PHP functions for Jappix manager
8 -------------------------------------------------
11 Authors: Vanaryon, Mathieui, olivierm, Vinilox
12 Last revision: 15/01/12
16 // The function to check an user is admin
17 function isAdmin($user, $password) {
18 // Read the users.xml file
25 // Our user is set and valid?
26 if(isset($array[$user]) && ($array[$user] == $password))
33 // Checks if a file is a valid image
34 function isImage($file) {
36 if(preg_match('/^(.+)(\.)(png|jpg|jpeg|gif|bmp)$/i', $file))
42 // Puts a marker on the current opened manager tab
43 function currentTab($current, $page) {
45 echo ' class="tab-active"';
48 // Checks all the storage folders are writable
49 function storageWritable() {
50 // Read the directory content
51 $dir = JAPPIX_BASE.'/store/';
52 $scan = scandir($dir);
57 // Check that each folder is writable
58 foreach($scan as $current) {
60 $folder = $dir.$current;
62 // A folder is not writable?
63 if(!preg_match('/^\.(.+)/', $current) && !is_writable($folder)) {
64 // Try to change the folder rights
68 if(!is_writable($folder))
76 // Removes a given directory (with all sub-elements)
77 function removeDir($dir) {
79 if(!$dh = @opendir($dir))
82 // Loop the current dir to remove its content
83 while(false !== ($obj = readdir($dh))) {
84 // Not a "real" directory
85 if(($obj == '.') || ($obj == '..'))
88 // Not a file, remove this dir
89 if(!@unlink($dir.'/'.$obj))
90 removeDir($dir.'/'.$obj);
93 // Close the dir and remove it!
98 // Copies a given directory (with all sub-elements)
99 function copyDir($source, $destination) {
100 // This is a directory
101 if(is_dir($source)) {
102 // Create the target directory
103 @mkdir($destination);
104 $directory = dir($source);
106 // Append the source directory content into the target one
107 while(FALSE !== ($readdirectory = $directory->read())) {
108 if(($readdirectory == '.') || ($readdirectory == '..'))
111 $PathDir = $source.'/'.$readdirectory;
114 if(is_dir($PathDir)) {
115 copyDir($PathDir, $destination.'/'.$readdirectory);
120 copy($PathDir, $destination.'/'.$readdirectory);
123 // Close the source directory
129 copy($source, $destination);
132 // Gets the total size of a directory
133 function sizeDir($dir) {
136 foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)) as $file)
137 $size += $file->getSize();
142 // Set the good unity for a size in bytes
143 function numericToMonth($id) {
153 9 => T_("September"),
155 11 => T_("November"),
162 // Extracts the version number with a version ID
163 function versionNumber($id) {
164 // First, extract the number string from the [X]
165 $extract = preg_replace('/^(.+)\[(\S+)\]$/', '$2', $id);
168 // Second extract: ~ (when this is a special version, like ~dev)
169 if(strrpos($extract, '~') !== false) {
171 $extract = preg_replace('/^([^~])~(.+)$/', '$1', $extract);
174 // Convert [X.X.X] into a full number
175 $extract = preg_replace('/[^0-9]/', '', $extract);
177 // Add missing items to [X.X.X]
178 $missing = 3 - strlen($extract.'');
180 $extract = $extract.(str_repeat('0', $missing));
182 // Allows updates for dev versions
184 $extract = $extract - 1;
186 return intval($extract);
189 // Checks for new Jappix updates
190 function newUpdates($force) {
191 // No need to check if developer mode
195 $cache_path = JAPPIX_BASE.'/store/updates/version.xml';
197 // No cache, obsolete one or refresh forced
198 if(!file_exists($cache_path) || (file_exists($cache_path) && (time() - (filemtime($cache_path)) >= 86400)) || $force) {
200 $last_version = read_url('http://codingteam.net/project/jappix/upload/briefcase/version.xml');
203 file_put_contents($cache_path, $last_version);
206 // Read from the cache
208 $last_version = file_get_contents($cache_path);
211 $xml = @simplexml_load_string($last_version);
217 // Get the version numbers
218 $current_version = getVersion();
219 $last_version = $xml->id;
221 // Check if we have the latest version
222 $current_version = versionNumber($current_version);
223 $last_version = versionNumber($last_version);
225 if($current_version < $last_version)
231 // Gets the Jappix update informations
232 function updateInformations() {
233 // Get the XML file content
234 $data = file_get_contents(JAPPIX_BASE.'/store/updates/version.xml');
236 // Transform the XML content into an array
243 $xml = new SimpleXMLElement($data);
245 // Parse the XML to add it to the array
246 foreach($xml->children() as $this_child) {
248 $current_name = $this_child->getName();
250 // Push it to the array, with a basic HTML encoding
251 $array[$current_name] = str_replace('\n', '<br />', $this_child);
258 // Processes the Jappix update from an external package
259 function processUpdate($url) {
261 $name = md5($url).'.zip';
262 $update_dir = $dir_base.'store/updates/';
263 $path = JAPPIX_BASE.'/store/updates/'.$name;
264 $extract_to = $update_dir.'jappix/';
265 $store_tree = JAPPIX_BASE.'/php/store-tree.php';
267 // We must get the archive from the server
268 if(!file_exists($path)) {
269 echo('<p>» '.T_("Downloading package...").'</p>');
272 $local = fopen($path, 'w');
273 $remote = fopen($url, 'r');
275 // Could not open a socket?!
277 echo('<p>» '.T_("Aborted: socket error!").'</p>');
279 // Remove the broken local archive
286 while(!feof($remote)) {
288 $buffer = fread($remote, 1024);
291 if($buffer == 'Error.') {
292 echo('<p>» '.T_("Aborted: buffer error!").'</p>');
294 // Remove the broken local archive
300 // Write the buffer to the file
301 fwrite($local, $buffer);
303 // Flush the current buffer
313 // Then, we extract the archive
314 echo('<p>» '.T_("Extracting package...").'</p>');
317 $zip = new ZipArchive;
318 $zip_open = $zip->open($path);
320 if($zip_open === TRUE) {
321 $zip->extractTo($update_dir);
326 echo('<p>» '.T_("Aborted: could not extract the package!").'</p>');
328 // Remove the broken source folder
329 removeDir($to_remove);
335 // PHP does not provide Zip archives support
336 catch(Exception $e) {
337 echo('<p>» '.T_("Aborted: could not extract the package!").'</p>');
339 // Remove the broken source folder
340 removeDir($to_remove);
345 // Remove the ./store dir from the source directory
346 removeDir($extract_to.'store/');
348 // Then, we remove the Jappix system files
349 echo('<p>» '.T_("Removing current Jappix system files...").'</p>');
351 // Open the general directory
352 $dir_base = JAPPIX_BASE.'/';
353 $scan = scandir($dir_base);
355 // Filter the scan array
356 $scan = array_diff($scan, array('.', '..', '.svn', 'store'));
358 // Check all the files are writable
359 foreach($scan as $scanned) {
361 $scanned_current = $dir_base.$scanned;
363 // Element not writable
364 if(!is_writable($scanned_current)) {
365 // Try to change the element rights
366 chmod($scanned_current, 0777);
369 if(!is_writable($scanned_current)) {
370 echo('<p>» '.T_("Aborted: everything is not writable!").'</p>');
377 // Process the files deletion
378 foreach($scan as $current) {
379 $to_remove = $dir_base.$current;
382 if(is_dir($to_remove))
383 removeDir($to_remove);
390 // Move the extracted files to the base
391 copyDir($extract_to, $dir_base);
393 // Remove the source directory
394 removeDir($extract_to);
396 // Regenerates the store tree
397 if(file_exists($store_tree)) {
398 echo('<p>» '.T_("Regenerating storage folder tree...").'</p>');
400 // Call the special regeneration script
401 include($store_tree);
404 // Remove the version package
407 // The new version is now installed!
408 echo('<p>» '.T_("Jappix is now up to date!").'</p>');
413 // Returns an array with the biggest share folders
414 function shareStats() {
415 // Define some stuffs
416 $path = JAPPIX_BASE.'/store/share/';
419 // Open the directory
420 $scan = scandir($path);
422 // Loop the share files
423 foreach($scan as $current) {
424 if(is_dir($path.$current) && !preg_match('/^(\.(.+)?)$/i', $current))
425 array_push($array, $current);
431 // Returns the largest share folders
432 function largestShare($array, $number) {
433 // Define some stuffs
434 $path = JAPPIX_BASE.'/store/share/';
435 $size_array = array();
437 // Push the results in an array
438 foreach($array as $current)
439 $size_array[$current] = sizeDir($path.$current);
444 // Select the first biggest values
445 $size_array = array_slice($size_array, 0, $number);
450 // Returns the others statistics array
451 function otherStats() {
452 // Fill the array with the values
453 $others_stats = array(
454 T_("Backgrounds") => sizeDir(JAPPIX_BASE.'/store/backgrounds/'),
455 T_("Cache") => sizeDir(JAPPIX_BASE.'/store/cache/'),
456 T_("Logs") => sizeDir(JAPPIX_BASE.'/store/logs/'),
457 T_("Music") => sizeDir(JAPPIX_BASE.'/store/music/'),
458 T_("Share") => sizeDir(JAPPIX_BASE.'/store/share/'),
459 T_("Send") => sizeDir(JAPPIX_BASE.'/store/send/'),
460 T_("Updates") => sizeDir(JAPPIX_BASE.'/store/updates/')
464 arsort($others_stats);
466 return $others_stats;
469 // Gets the array of the visits stats
470 function getVisits() {
481 $data = readXML('access', 'total');
485 // Initialize the visits reading
486 $xml = new SimpleXMLElement($data);
488 // Get the XML values
489 $array['total'] = intval($xml->total);
490 $array['stamp'] = intval($xml->stamp);
492 // Get the age of the stats
493 $age = time() - $array['stamp'];
495 // Generate the time-dependant values
499 'monthly' => 2678400,
503 foreach($timed as $timed_key => $timed_value) {
504 if($age >= $timed_value)
505 $array[$timed_key] = intval($array['total'] / ($age / $timed[$timed_key])).'';
507 $array[$timed_key] = $array['total'].'';
514 // Gets the array of the monthly visits
515 function getMonthlyVisits() {
520 $data = readXML('access', 'months');
522 // Get the XML file values
524 // Initialize the visits reading
525 $xml = new SimpleXMLElement($data);
527 // Loop the visit elements
528 foreach($xml->children() as $child) {
529 // Get the current month ID
530 $current_id = intval(preg_replace('/month_([0-9]+)/i', '$1', $child->getName()));
532 // Get the current month name
533 $current_name = numericToMonth($current_id);
536 $array[$current_name] = intval($child);
543 // Purges the target folder content
544 function purgeFolder($folder) {
545 // Array of the folders to purge
548 // We must purge all the folders?
549 if($folder == 'everything')
550 array_push($array, 'cache', 'logs', 'send', 'updates');
552 array_push($array, $folder);
554 // All right, now we can empty it!
555 foreach($array as $current_folder) {
556 // Scan the current directory
557 $directory = JAPPIX_BASE.'/store/'.$current_folder.'/';
558 $scan = scandir($directory);
559 $scan = array_diff($scan, array('.', '..', '.svn', 'index.html'));
561 // Process the files deletion
562 foreach($scan as $current) {
563 $remove_this = $directory.$current;
566 if(is_dir($remove_this))
567 removeDir($remove_this);
571 unlink($remove_this);
576 // Returns folder browsing informations
577 function browseFolder($folder, $mode) {
578 // Scan the target directory
579 $directory = JAPPIX_BASE.'/store/'.$folder;
580 $scan = scandir($directory);
581 $scan = array_diff($scan, array('.', '..', '.svn', 'index.html'));
582 $keep_get = keepGet('(s|b|k)', false);
587 // Not in the root folder: show previous link
588 if(strpos($folder, '/') != false) {
589 // Filter the folder name
590 $previous_folder = substr($folder, 0, strrpos($folder, '/'));
592 echo('<div class="one-browse previous manager-images"><a href="./?b='.$mode.'&s='.urlencode($previous_folder).$keep_get.'">'.T_("Previous").'</a></div>');
595 // Empty or non-existing directory?
596 if(!count($scan) || !is_dir($directory)) {
597 echo('<div class="one-browse '.$marker.' alert manager-images">'.T_("The folder is empty.").'</div>');
602 // Echo the browsing HTML code
603 foreach($scan as $current) {
604 // Generate the item path$directory
605 $path = $directory.'/'.$current;
606 $file = $folder.'/'.$current;
611 $href = './?b='.$mode.'&s='.urlencode($file).$keep_get;
617 $type = getFileType(getFileExt($path));
619 $target = ' target="_blank"';
622 echo('<div class="one-browse '.$marker.' '.$type.' manager-images"><a href="'.$href.'"'.$target.'>'.htmlspecialchars($current).'</a><input type="checkbox" name="element_'.md5($file).'" value="'.htmlspecialchars($file).'" /></div>');
634 // Removes selected elements (files/folders)
635 function removeElements() {
636 // Initialize the match
637 $elements_removed = false;
638 $elements_remove = array();
640 // Try to get the elements to remove
641 foreach($_POST as $post_key => $post_value) {
643 if(preg_match('/^element_(.+)$/i', $post_key) && isSafe($post_value)) {
645 $elements_removed = true;
648 $post_element = JAPPIX_BASE.'/store/'.$post_value;
650 // Remove the current element
651 if(is_dir($post_element))
652 removeDir($post_element);
653 else if(file_exists($post_element))
654 unlink($post_element);
658 // Show a notification message
659 if($elements_removed)
660 echo('<p class="info smallspace success">'.T_("The selected elements have been removed.").'</p>');
662 echo('<p class="info smallspace fail">'.T_("You must select elements to remove!").'</p>');
665 // Returns users browsing informations
666 function browseUsers() {
673 // Echo the browsing HTML code
674 foreach($array as $user => $password) {
675 // Filter the username
676 $user = htmlspecialchars($user);
679 echo('<div class="one-browse '.$marker.' user manager-images"><span>'.$user.'</span><input type="checkbox" name="admin_'.md5($user).'" value="'.$user.'" /><div class="clear"></div></div>');
689 // Generates the logo form field
690 function logoFormField($id, $name) {
691 if(file_exists(JAPPIX_BASE.'/store/logos/'.$name.'.png'))
692 echo '<span class="logo_links"><a class="remove manager-images" href="./?k='.urlencode($name).keepGet('k', false).'" title="'.T_("Remove this logo").'"></a><a class="view manager-images" href="./store/logos/'.$name.'.png" target="_blank" title="'.T_("View this logo").'"></a></span>';
694 echo '<input id="logo_own_'.$id.'_location" type="file" name="logo_own_'.$id.'_location" accept="image/*" />';
699 // Reads the background configuration
700 function readBackground() {
701 // Read the background configuration XML
702 $background_data = readXML('conf', 'background');
704 // Get the default values
705 $background_default = defaultBackground();
708 $background_conf = array();
710 // Read the stored values
711 if($background_data) {
712 // Initialize the background configuration XML data
713 $background_xml = new SimpleXMLElement($background_data);
715 // Loop the notice configuration elements
716 foreach($background_xml->children() as $background_child)
717 $background_conf[$background_child->getName()] = $background_child;
720 // Checks no value is missing in the stored configuration
721 foreach($background_default as $background_name => $background_value) {
722 if(!isset($background_conf[$background_name]) || empty($background_conf[$background_name]))
723 $background_conf[$background_name] = $background_default[$background_name];
726 return $background_conf;
729 // Writes the background configuration
730 function writeBackground($array) {
731 // Generate the XML data
734 foreach($array as $key => $value)
735 $xml .= "\n".' <'.$key.'>'.stripslashes(htmlspecialchars($value)).'</'.$key.'>';
738 writeXML('conf', 'background', $xml);
741 // Generates a list of the available background images
742 function getBackgrounds() {
743 // Initialize the result array
746 // Scan the background directory
747 $scan = scandir(JAPPIX_BASE.'/store/backgrounds/');
749 foreach($scan as $current) {
750 if(isImage($current))
751 array_push($array, $current);
757 // Writes the notice configuration
758 function writeNotice($type, $simple) {
759 // Generate the XML data
761 '<type>'.$type.'</type>
762 <notice>'.stripslashes(htmlspecialchars($simple)).'</notice>'
766 writeXML('conf', 'notice', $xml);