Files
selima-perl/lib/php/monica/xfileio.inc.php
2026-03-10 21:31:43 +08:00

174 lines
4.8 KiB
PHP

<?php
// File name: xfileio.inc.php
// Description: Extended PHP subroutine to read from/write to a file
// Date: 2002-04-16
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2009 Pristine Communications
// xfread: Read from file
// Input: the file path $file
// Output: the file content
function xfread($file)
{
$size = filesize($file);
// fread() does not allow reading of 0 bytes now
if ($size == 0) {
return "";
}
$fp = fopen($file, "r");
flock($fp, LOCK_SH);
$content = fread($fp, $size);
flock($fp, LOCK_UN);
fclose($fp);
return $content;
}
// xfwrite: Write to a file
// Input: the file path $file and the file content $content
// Output: none
function xfwrite($file, $content)
{
$fp = fopen($file, "w");
flock($fp, LOCK_EX);
fwrite($fp, $content);
flock($fp, LOCK_UN);
fclose($fp);
return;
}
// xfappend: Append to a file
// Input: the file path $file and the file content $content
// Output: none
function xfappend($file, $content)
{
// File not exists - create it with xfwrite()
if (!file_exists($file)) {
return xfwrite($file, $content);
}
$fp = fopen($file, "a");
flock($fp, LOCK_EX);
fwrite($fp, $content);
flock($fp, LOCK_UN);
fclose($fp);
return;
}
// xfupdate: Update a file
// Input: the file path $file and the file content $newcontent
// Output: none
function xfupdate($file, $newcontent)
{
// Write as a new file if the old file does not exist
if (!file_exists($file) || filesize($file) != strlen($newcontent)) {
xfwrite($file, $newcontent);
// Old file exists -- compare the content and update only if necessary
} else {
$size = filesize($file);
$fp = fopen($file, "r+");
flock($fp, LOCK_EX);
// fread() does not allow reading of 0 bytes now
if ($size == 0) {
$oldcontent = "";
} else {
$oldcontent = fread($fp, $size);
}
if ($oldcontent != $newcontent) {
fseek($fp, 0, SEEK_SET);
ftruncate($fp, 0);
fwrite($fp, $newcontent);
}
flock($fp, LOCK_UN);
fclose($fp);
}
// Clear the stat cache to avoid future mistakes like MIME types.
clearstatcache();
return;
}
// xfupdate_template: Update a file comparing with a template
// Input: the file path $file, the new content template $tmpl
// and its replacements $rep
// Output: none
function xfupdate_template($file, $tmpl, $rep = null)
{
// Obtain the replacements
if (is_null($rep)) {
$rep = function_exists("page_replacements")? page_replacements():
array();
}
// Write as a new file if the old file does not exist
if (!file_exists($file)) {
$new = $tmpl;
foreach (array_keys($rep) as $key) {
$new = str_replace("<!--monica:$key-->", $rep[$key]["content"], $new);
}
xfwrite($file, $new);
// Old file exists -- compare the content and update only if necessary
} else {
$size = filesize($file);
$fp = fopen($file, "r+");
flock($fp, LOCK_EX);
if ($size == 0) {
$old = "";
} else {
$old = fread($fp, filesize($file));
}
// Not matched
if (_xfileio_template_updated($old, $tmpl, $rep)) {
$new = $tmpl;
foreach (array_keys($rep) as $key) {
$new = str_replace("<!--monica:$key-->", $rep[$key]["content"], $new);
}
fseek($fp, 0, SEEK_SET);
ftruncate($fp, 0);
fwrite($fp, $new);
}
flock($fp, LOCK_UN);
fclose($fp);
}
return;
}
// _xfileio_template_updated: If a page is updated comparing to the template
function _xfileio_template_updated($old, $tmpl, $rep)
{
// Process piece by piece
while (preg_match("/^(.*?)(<!--monica:(.+?)-->)(.*)$/s", $tmpl, $m)) {
$plain = $m[1];
$repsec = $m[2];
$key = $m[3];
$tmpl = $m[4];
// Try to match the plain text part
if (substr($old, 0, strlen($plain)) != $plain) {
return true;
}
$old = substr($old, strlen($plain));
// A valid replacement is found -- try to match the pattern
if (array_key_exists($key, $rep)) {
if (!preg_match("/^" . $rep[$key]["pattern"] . "(.*)$/s", $old, $m)) {
return true;
}
$old = $m[1];
// Not a valid replacement -- treat it as a plain text part
} else {
if (substr($old, 0, strlen($repsec)) != $repsec) {
return true;
}
$old = substr($old, strlen($plain));
}
}
// Check the remains as a plain text part
if ($old != $tmpl) {
return true;
}
return false;
}
?>