/common/libraries/plugin/phpfreechat/src/containers/file.class.php
PHP | 314 lines | 215 code | 46 blank | 53 comment | 45 complexity | f88ce855b154d3806c2b34d83e5900cb MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, LGPL-3.0, GPL-3.0, MIT
- <?php
- /**
- * file.class.php
- *
- * Copyright ??? 2006 Stephane Gully <stephane.gully@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
- require_once dirname(__FILE__) . "/../pfccontainerinterface.class.php";
-
- /**
- * pfcContainer_File is a concret container which stock data into files
- *
- * @author Stephane Gully <stephane.gully@gmail.com>
- */
- class pfcContainer_File extends pfcContainerInterface
- {
- var $_users = array("nickid" => array(), "timestamp" => array());
- var $_meta = array();
-
- function __construct()
- {
- pfcContainerInterface :: __construct();
- }
-
- function loadPaths(&$c)
- {
- if (! isset($c->container_cfg_chat_dir) || $c->container_cfg_chat_dir == '')
- $c->container_cfg_chat_dir = $c->data_private_path . "/chat";
- if (! isset($c->container_cfg_server_dir) || $c->container_cfg_server_dir == '')
- $c->container_cfg_server_dir = $c->container_cfg_chat_dir . "/s_" . $c->serverid;
- }
-
- function getDefaultConfig()
- {
- $cfg = pfcContainerInterface :: getDefaultConfig();
- $cfg["chat_dir"] = ''; // will be generated from the other parameters into the init step
- $cfg["server_dir"] = ''; // will be generated from the other parameters into the init step
- return $cfg;
- }
-
- function init(&$c)
- {
- $errors = pfcContainerInterface :: init($c);
-
- // generate the container parameters from other config parameters
- $this->loadPaths($c);
-
- $errors = array_merge($errors, @test_writable_dir($c->container_cfg_chat_dir, "container_cfg_chat_dir"));
- $errors = array_merge($errors, @test_writable_dir($c->container_cfg_server_dir, "container_cfg_chat_dir/serverid"));
-
- // test the filemtime php function because it doesn't work on special filesystem
- // example : NFS, VZFS
- $filename = $c->data_private_path . '/filemtime.test';
- $timetowait = 2;
- if (is_writable(dirname($filename)))
- {
- file_put_contents($filename, 'some-data1-' . time());
- clearstatcache();
- $time1 = filemtime($filename);
- sleep($timetowait);
- file_put_contents($filename, 'some-data2-' . time());
- clearstatcache();
- $time2 = filemtime($filename);
- unlink($filename);
- if ($time2 - $time1 != $timetowait)
- $errors[] = "filemtime php fuction is not usable on your filesystem. Please do not use the 'file' container (try the 'mysql' container) or swith to another filesystem type.";
- }
-
- // test the LOCK_EX feature because it doesn't work on special filsystem like NFS
- $filename = $c->data_private_path . '/filemtime.test';
- if (is_writable(dirname($filename)))
- {
- $data1 = time();
- //file_put_contents($filename, $data1, LOCK_EX);
- file_put_contents($filename, $data1);
- $data2 = file_get_contents($filename);
- if ($data1 != $data2)
- {
- }
-
- //$errors[] = "LOCK_EX feature is not usable on your filesystem. Please do not use the 'file' container (try the 'mysql' container) or swith to another filesystem type.";
- }
-
- return $errors;
- }
-
- function setMeta($group, $subgroup, $leaf, $leafvalue = NULL)
- {
- $c = & pfcGlobalConfig :: Instance();
-
- // create directories
- $dir_base = $c->container_cfg_server_dir;
- $dir = $dir_base . '/' . $group . '/' . $subgroup;
- if (! is_dir($dir))
- mkdir_r($dir);
-
- // create or replace metadata file
- $leaffilename = $dir . "/" . $leaf;
- $leafexists = file_exists($leaffilename);
- if ($leafvalue == NULL)
- {
- touch($leaffilename);
- }
- else
- {
- //file_put_contents($leaffilename, $leafvalue, LOCK_EX);
- file_put_contents($leaffilename, $leafvalue);
- }
-
- // store the value in the memory cache
- //@todo
- // $this->_meta[$enc_type][$enc_subtype][$enc_key] = $value;
-
-
- if ($leafexists)
- return 1; // value overwritten
- else
- return 0; // value created
- }
-
- function getMeta($group, $subgroup = null, $leaf = null, $withleafvalue = false)
- {
- $c = & pfcGlobalConfig :: Instance();
-
- // read data from metadata file
- $ret = array();
- $ret["timestamp"] = array();
- $ret["value"] = array();
- $dir_base = $c->container_cfg_server_dir;
-
- $dir = $dir_base . '/' . $group;
- if ($subgroup == NULL)
- {
- if (is_dir($dir))
- {
- $dh = opendir($dir);
- while (false !== ($file = readdir($dh)))
- {
- if ($file == "." || $file == "..")
- continue; // skip . and .. generic files
- $ret["timestamp"][] = filemtime($dir . '/' . $file);
- $ret["value"][] = $file;
- }
- closedir($dh);
- }
- return $ret;
- }
-
- $dir .= '/' . $subgroup;
-
- if ($leaf == NULL)
- {
- if (is_dir($dir))
- {
- $dh = opendir($dir);
- while (false !== ($file = readdir($dh)))
- {
- if ($file == "." || $file == "..")
- continue; // skip . and .. generic files
- $ret["timestamp"][] = filemtime($dir . '/' . $file);
- $ret["value"][] = $file;
- }
- closedir($dh);
- }
-
- return $ret;
- }
-
- $leaffilename = $dir . "/" . $leaf;
-
- if (! file_exists($leaffilename))
- return $ret;
- if ($withleafvalue)
- $ret["value"][] = file_get_contents_flock($leaffilename);
- else
- $ret["value"][] = NULL;
- $ret["timestamp"][] = filemtime($leaffilename);
-
- return $ret;
- }
-
- function incMeta($group, $subgroup, $leaf)
- {
- $c = & pfcGlobalConfig :: Instance();
-
- // create directories
- $dir_base = $c->container_cfg_server_dir;
- $dir = $dir_base . '/' . $group . '/' . $subgroup;
- if (! is_dir($dir))
- mkdir_r($dir);
-
- // create or replace metadata file
- $leaffilename = $dir . "/" . $leaf;
-
- // create return array
- $ret = array();
- $ret["timestamp"] = array();
- $ret["value"] = array();
-
- // read and increment data from metadata file
- clearstatcache();
- if (file_exists($leaffilename))
- {
- $fh = fopen($leaffilename, 'r+');
- for($i = 0; $i < 10; $i ++) // Try 10 times until an exclusive lock can be obtained
- {
- //if (flock($fh, LOCK_EX))
- {
- $leafvalue = chop(fread($fh, filesize($leaffilename)));
- $leafvalue ++;
- rewind($fh);
- fwrite($fh, $leafvalue);
- fflush($fh);
- ftruncate($fh, ftell($fh));
- flock($fh, LOCK_UN);
- break;
- }
- // If flock is working properly, this will never be reached
- $delay = rand(0, pow(2, ($i + 1)) - 1) * 5000; // Exponential backoff
- usleep($delay);
- }
- fclose($fh);
- }
- else
- {
- $leafvalue = "1";
- //file_put_contents($leaffilename, $leafvalue, LOCK_EX);
- file_put_contents($leaffilename, $leafvalue);
- }
-
- $ret["value"][] = $leafvalue;
- $ret["timestamp"][] = filemtime($leaffilename);
-
- return $ret;
- }
-
- function rmMeta($group, $subgroup = null, $leaf = null)
- {
- $c = & pfcGlobalConfig :: Instance();
-
- $dir = $c->container_cfg_server_dir;
-
- if ($group == NULL)
- {
- rm_r($dir);
- return true;
- }
-
- $dir .= '/' . $group;
-
- if ($subgroup == NULL)
- {
- rm_r($dir);
- return true;
- }
-
- $dir .= '/' . $subgroup;
-
- if ($leaf == NULL)
- {
- rm_r($dir);
- return true;
- }
-
- $leaffilename = $dir . '/' . $leaf;
- if (! file_exists($leaffilename))
- return false;
- unlink($leaffilename);
-
- // check that the directory is empty or not
- // remove it if it doesn't contains anything
- $dh = opendir($dir);
- readdir($dh);
- readdir($dh); // skip . and .. directories
- $isnotempty = readdir($dh);
- closedir($dh);
- if ($isnotempty === false)
- rmdir($dir);
-
- return true;
- }
-
- /**
- * Used to encode UTF8 strings to ASCII filenames
- */
- function encode($str)
- {
- return urlencode($str);
- }
-
- /**
- * Used to decode ASCII filenames to UTF8 strings
- */
- function decode($str)
- {
- return urldecode($str);
- }
- }
- ?>