PageRenderTime 38ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/libs/Chat/src/containers/file.class.php

https://code.google.com/
PHP | 301 lines | 209 code | 44 blank | 48 comment | 47 complexity | 79af252cc3a55b8d1d2f5d7281650ec7 MD5 | raw file
Possible License(s): Apache-2.0, GPL-2.0
  1. <?php
  2. /**
  3. * file.class.php
  4. *
  5. * Copyright ??? 2006 Stephane Gully <stephane.gully@gmail.com>
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the
  19. * Free Software Foundation, 51 Franklin St, Fifth Floor,
  20. * Boston, MA 02110-1301 USA
  21. */
  22. require_once dirname(__FILE__)."/../pfccontainerinterface.class.php";
  23. /**
  24. * pfcContainer_File is a concret container which stock data into files
  25. *
  26. * @author Stephane Gully <stephane.gully@gmail.com>
  27. */
  28. class pfcContainer_File extends pfcContainerInterface
  29. {
  30. var $_users = array("nickid" => array(),
  31. "timestamp" => array());
  32. var $_meta = array();
  33. function pfcContainer_File()
  34. {
  35. pfcContainerInterface::pfcContainerInterface();
  36. }
  37. function loadPaths(&$c)
  38. {
  39. if (!isset($c->container_cfg_chat_dir) || $c->container_cfg_chat_dir == '')
  40. $c->container_cfg_chat_dir = $c->data_private_path."_chat";
  41. if (!isset($c->container_cfg_server_dir) || $c->container_cfg_server_dir == '')
  42. $c->container_cfg_server_dir = $c->container_cfg_chat_dir."_s_".$c->serverid;
  43. }
  44. function getDefaultConfig()
  45. {
  46. $cfg = pfcContainerInterface::getDefaultConfig();
  47. $cfg["chat_dir"] = ''; // will be generated from the other parameters into the init step
  48. $cfg["server_dir"] = ''; // will be generated from the other parameters into the init step
  49. return $cfg;
  50. }
  51. function init(&$c)
  52. {
  53. $errors = pfcContainerInterface::init($c);
  54. // generate the container parameters from other config parameters
  55. $this->loadPaths($c);
  56. $errors = array_merge($errors, @test_writable_dir($c->container_cfg_chat_dir, "container_cfg_chat_dir"));
  57. $errors = array_merge($errors, @test_writable_dir($c->container_cfg_server_dir, "container_cfg_chat_dir/serverid"));
  58. // test the filemtime php function because it doesn't work on special filesystem
  59. // example : NFS, VZFS
  60. $filename = $c->data_private_path.'_filemtime.test';
  61. $timetowait = 2;
  62. if (is_writable(dirname($filename)))
  63. {
  64. file_put_contents($filename,'some-data1-'.time());
  65. clearstatcache();
  66. $time1 = filemtime($filename);
  67. sleep($timetowait);
  68. file_put_contents($filename,'some-data2-'.time());
  69. clearstatcache();
  70. $time2 = filemtime($filename);
  71. unlink($filename);
  72. if ($time2-$time1 != $timetowait)
  73. $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.";
  74. }
  75. // test the LOCK_EX feature because it doesn't work on special filsystem like NFS
  76. $filename = $c->data_private_path.'_filemtime.test';
  77. if (is_writable(dirname($filename)))
  78. {
  79. $data1 = time();
  80. file_put_contents($filename, $data1, LOCK_EX);
  81. $data2 = file_get_contents($filename);
  82. if ($data1 != $data2)
  83. $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.";
  84. }
  85. return $errors;
  86. }
  87. function setMeta($group, $subgroup, $leaf, $leafvalue = NULL)
  88. {
  89. $c =& pfcGlobalConfig::Instance();
  90. // create directories
  91. $dir_base = $c->container_cfg_server_dir;
  92. $dir = $dir_base.'/'.$group.'/'.$subgroup;
  93. if (!is_dir($dir)) mkdir_r($dir);
  94. // create or replace metadata file
  95. $leaffilename = $dir."/".$leaf;
  96. $leafexists = file_exists($leaffilename);
  97. if ($leafvalue == NULL)
  98. {
  99. @unlink($leaffilename);
  100. touch($leaffilename);
  101. }
  102. else
  103. {
  104. file_put_contents($leaffilename, $leafvalue, LOCK_EX);
  105. }
  106. // store the value in the memory cache
  107. //@todo
  108. // $this->_meta[$enc_type][$enc_subtype][$enc_key] = $value;
  109. if ($leafexists)
  110. return 1; // value overwritten
  111. else
  112. return 0; // value created
  113. }
  114. function getMeta($group, $subgroup = null, $leaf = null, $withleafvalue = false)
  115. {
  116. $c =& pfcGlobalConfig::Instance();
  117. // read data from metadata file
  118. $ret = array();
  119. $ret["timestamp"] = array();
  120. $ret["value"] = array();
  121. $dir_base = $c->container_cfg_server_dir;
  122. $dir = $dir_base.'/'.$group;
  123. if ($subgroup == NULL)
  124. {
  125. if (is_dir($dir))
  126. {
  127. $dh = opendir($dir);
  128. while (false !== ($file = readdir($dh)))
  129. {
  130. if ($file == "." || $file == "..") continue; // skip . and .. generic files
  131. $ret["timestamp"][] = filemtime($dir.'/'.$file);
  132. $ret["value"][] = $file;
  133. }
  134. closedir($dh);
  135. }
  136. return $ret;
  137. }
  138. $dir .= '/'.$subgroup;
  139. if ($leaf == NULL)
  140. {
  141. if (is_dir($dir))
  142. {
  143. $dh = opendir($dir);
  144. while (false !== ($file = readdir($dh)))
  145. {
  146. if ($file == "." || $file == "..") continue; // skip . and .. generic files
  147. $ret["timestamp"][] = filemtime($dir.'/'.$file);
  148. $ret["value"][] = $file;
  149. }
  150. closedir($dh);
  151. }
  152. return $ret;
  153. }
  154. $leaffilename = $dir."/".$leaf;
  155. if (!file_exists($leaffilename)) return $ret;
  156. if ($withleafvalue)
  157. $ret["value"][] = file_get_contents_flock($leaffilename);
  158. else
  159. $ret["value"][] = NULL;
  160. $ret["timestamp"][] = filemtime($leaffilename);
  161. return $ret;
  162. }
  163. function incMeta($group, $subgroup, $leaf)
  164. {
  165. $c =& pfcGlobalConfig::Instance();
  166. // create directories
  167. $dir_base = $c->container_cfg_server_dir;
  168. $dir = $dir_base.'/'.$group.'/'.$subgroup;
  169. if (!is_dir($dir)) mkdir_r($dir);
  170. // create or replace metadata file
  171. $leaffilename = $dir."/".$leaf;
  172. // create return array
  173. $ret = array();
  174. $ret["timestamp"] = array();
  175. $ret["value"] = array();
  176. // read and increment data from metadata file
  177. clearstatcache();
  178. if (file_exists($leaffilename))
  179. {
  180. $fh = fopen($leaffilename, 'r+');
  181. for($i = 0; $i < 10; $i++) // Try 10 times until an exclusive lock can be obtained
  182. {
  183. if (flock($fh, LOCK_EX))
  184. {
  185. $leafvalue = chop(fread($fh, filesize($leaffilename)));
  186. $leafvalue++;
  187. rewind($fh);
  188. fwrite($fh, $leafvalue);
  189. fflush($fh);
  190. ftruncate($fh, ftell($fh));
  191. flock($fh, LOCK_UN);
  192. break;
  193. }
  194. // If flock is working properly, this will never be reached
  195. $delay = rand(0, pow(2, ($i+1)) - 1) * 5000; // Exponential backoff
  196. usleep($delay);
  197. }
  198. fclose($fh);
  199. }
  200. else
  201. {
  202. $leafvalue="1";
  203. file_put_contents($leaffilename, $leafvalue, LOCK_EX);
  204. }
  205. $ret["value"][] = $leafvalue;
  206. $ret["timestamp"][] = filemtime($leaffilename);
  207. return $ret;
  208. }
  209. function rmMeta($group, $subgroup = null, $leaf = null)
  210. {
  211. $c =& pfcGlobalConfig::Instance();
  212. $dir = $c->container_cfg_server_dir;
  213. if ($group == NULL)
  214. {
  215. rm_r($dir);
  216. return true;
  217. }
  218. $dir .= '/'.$group;
  219. if ($subgroup == NULL)
  220. {
  221. rm_r($dir);
  222. return true;
  223. }
  224. $dir .= '/'.$subgroup;
  225. if ($leaf == NULL)
  226. {
  227. rm_r($dir);
  228. return true;
  229. }
  230. $leaffilename = $dir.'/'.$leaf;
  231. if (!file_exists($leaffilename)) return false;
  232. unlink($leaffilename);
  233. // check that the directory is empty or not
  234. // remove it if it doesn't contains anything
  235. $dh = opendir($dir);
  236. readdir($dh); readdir($dh); // skip . and .. directories
  237. $isnotempty = readdir($dh);
  238. closedir($dh);
  239. if ($isnotempty === false) rmdir($dir);
  240. return true;
  241. }
  242. /**
  243. * Used to encode UTF8 strings to ASCII filenames
  244. */
  245. function encode($str)
  246. {
  247. return urlencode($str);
  248. }
  249. /**
  250. * Used to decode ASCII filenames to UTF8 strings
  251. */
  252. function decode($str)
  253. {
  254. return urldecode($str);
  255. }
  256. }
  257. ?>