write($data, $m[2]); return; } else { error('Invalid remote server: ' . $m[1]); } } if (!$fp = fopen($path, $simple ? 'w' : 'c')) { error('Unable to open file for writing: ' . $path); } // File locking if (!$simple && !flock($fp, LOCK_EX)) { error('Unable to lock file: ' . $path); } // Truncate file if (!$simple && !ftruncate($fp, 0)) { error('Unable to truncate file: ' . $path); } // Write data if (($bytes = fwrite($fp, $data)) === false) { error('Unable to write to file: ' . $path); } // Unlock if (!$simple) { flock($fp, LOCK_UN); } // Close if (!fclose($fp)) { error('Unable to close file: ' . $path); } /** * Create gzipped file. * * When writing into a file foo.bar and the size is larger or equal to 1 * KiB, this also produces the gzipped version foo.bar.gz * * This is useful with nginx with gzip_static on. */ if ($config['gzip_static']) { $gzpath = "$path.gz"; // if ($bytes >= 1024) if ($bytes & ~0x3ff) { if (file_put_contents($gzpath, gzencode($data), $simple ? 0 : LOCK_EX) === false) { error("Unable to write to file: $gzpath"); } } else { @unlink($gzpath); } } if (!$skip_purge && isset($config['purge'])) { // Purge cache if (basename($path) == $config['file_index']) { // Index file (/index.html); purge "/" as well $uri = dirname($path); // root if ($uri == '.') { $uri = ''; } else { $uri .= '/'; } purge($uri); } purge($path); } if ($config['debug']) { $debug['write'][] = $path . ': ' . $bytes . ' bytes'; } event('write', $path); } function file_unlink($path) { global $config, $debug; if ($config['debug']) { if (!isset($debug['unlink'])) { $debug['unlink'] = array(); } $debug['unlink'][] = $path; } $ret = @unlink($path); if ($config['gzip_static']) { $gzpath = "$path.gz"; @unlink($gzpath); } if (isset($config['purge']) && $path[0] != '/' && isset($_SERVER['HTTP_HOST'])) { // Purge cache if (basename($path) == $config['file_index']) { // Index file (/index.html); purge "/" as well $uri = dirname($path); // root if ($uri == '.') { $uri = ''; } else { $uri .= '/'; } purge($uri); } purge($path); } event('unlink', $path); return $ret; } function purge($uri) { global $config, $debug; // Fix for Unicode $uri = rawurlencode($uri); $noescape = "/!~*()+:"; $noescape = preg_split('//', $noescape); $noescape_url = array_map("rawurlencode", $noescape); $uri = str_replace($noescape_url, $noescape, $uri); if (preg_match($config['referer_match'], $config['root']) && isset($_SERVER['REQUEST_URI'])) { $uri = (str_replace('\\', '/', dirname($_SERVER['REQUEST_URI'])) == '/' ? '/' : str_replace('\\', '/', dirname($_SERVER['REQUEST_URI'])) . '/') . $uri; } else { $uri = $config['root'] . $uri; } if ($config['debug']) { $debug['purge'][] = $uri; } foreach ($config['purge'] as &$purge) { $host = &$purge[0]; $port = &$purge[1]; $http_host = isset($purge[2]) ? $purge[2] : (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost'); $request = "PURGE {$uri} HTTP/1.1\r\nHost: {$http_host}\r\nUser-Agent: Tinyboard\r\nConnection: Close\r\n\r\n"; if ($fp = fsockopen($host, $port, $errno, $errstr, $config['purge_timeout'])) { fwrite($fp, $request); fclose($fp); } else { // Cannot connect? error('Could not PURGE for ' . $host); } } } /** * Recursively delete a directory with it's content. */ function rrmdir($dir) { if (is_dir($dir)) { $objects = scandir($dir); foreach ($objects as $object) { if ($object != "." && $object != "..") { if (filetype($dir."/".$object) == "dir") { rrmdir($dir."/".$object); } else { file_unlink($dir."/".$object); } } } reset($objects); rmdir($dir); } }