*/ /* * Copyright (C) Michael Kirchner * * This file is part of the GuardTime dokuwiki plugin. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // must be run within Dokuwiki if (!defined('DOKU_INC')) die(); if (!defined('DOKU_LF')) define('DOKU_LF', "\n"); if (!defined('DOKU_TAB')) define('DOKU_TAB', "\t"); if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); // error_reporting(E_ALL); // ini_set('display_errors', 'On'); require_once DOKU_PLUGIN.'action.php'; require_once(DOKU_INC.'inc/pluginutils.php'); class action_plugin_gtime_timestamp extends DokuWiki_Action_Plugin { // todo: // Button to download zip with file and timestamp data // include setup variables into dokuwiki setup public function register(Doku_Event_Handler &$controller) { $Timestamper_URL=$this->getConf('Timestamper_URL'); //The URL of the service for creating timestamps. $Extender_URL=$this->getConf('Extender_URL'); //The URL of the service for connecting timestamps to Integrity Codes. $Publications_URL=$this->getConf('Publications_URL'); //The URL where the GuardTime publications file can be downloaded. $Publications_TTL=$this->getConf('Publications_TTL'); //Time of life for Publicationsfile in minutes $controller->register_hook('IO_WIKIPAGE_WRITE', 'AFTER', $this, 'handle_io_wikipage_write'); $controller->register_hook('TPL_ACT_RENDER', 'AFTER', $this, 'handle_tpl_act_render'); } /** * Logs exception and stack trace to error log. * * @param $exception the exception to log * @return void */ function gt_log_exception($exception) { error_log($exception->getMessage()); error_log($exception->getTraceAsString()); } /** * Gets publications file. * * This method uses gt_publications_file to cache the file for * publications_ttl minutes in tmp. * * @return GTPublicationsFile cached or freshly downloaded publications file */ function gt_publications_file() { $Publications_URL=$this->getConf('Publications_URL'); //The URL where the GuardTime publications file can be downloaded. if (empty($Publications_URL)) { return null; } $Publications_TTL=$this->getConf('Publications_TTL'); //Time of life for Publicationsfile in minutes if (!is_integer($Publications_TTL)) { $ttl = 60; } $Publications_TTL = $Publications_TTL * 60 ; $filename = DOKU_INC.'/data/tmp/publications.bin'; if (file_exists($filename)) { $filetime = filemtime($filename); } if (empty($filetime) || ($filetime + $Publications_TTL) < time()) { try { $newFile = GTHttpClient::getPublicationsFile($Publications_URL); $result = $newFile->verify(); if ($result->isValid()) { $newFile->save($filename); return $newFile; } else { return null; } } catch (GTException $e) { gt_log_exception($e); } } try { return GTPublicationsFile::load($filename); } catch (GTException $e) { gt_log_exception($e); } } /** * Extends GuardTime timestamp. * * @param $timestamp * @param $INFO * @return void */ function gt_extend($timestamp,$INFO) { $Publications_URL=$this->getConf('Publications_URL'); //The URL where the GuardTime publications file can be downloaded. if ($timestamp->isExtended()) { return; } $Extender_URL=$this->getConf('Extender_URL'); if (empty($Extender_URL)) { return; } $publicationsFile = $this->gt_publications_file(); if (empty($publicationsFile)) { return; } if (!$timestamp->isExtendable($publicationsFile)) { return; // What does that mean? only PKI signed? } try { GTHttpClient::extend($timestamp, $Extender_URL); } catch (GTException $e) { $this->gt_log_exception($e); } if ($timestamp->isExtended()) { $timestamp->save($INFO['filepath'].'.gtts'); } } /** * Main Handle for Timestamping. * * @param $event * @param $param * @return void */ public function handle_io_wikipage_write(Doku_Event &$event, $param) { // This routine is called when a file is written in pages or attic. // Whenever we do this, a timestamp is created and stored with the file with extension gtts. // (The exception is when the file is deleted with empty content, then no new timestamp is // needed and the old timestampfile is deleted.) // While this is also done on the aktual pages, it is also done on the attic. This is // actually more important, as the attic is always kept. Be aware that when using compression // the timestamp will be on the compressed files! require_once(DOKU_INC.'lib/plugins/gtime/gtlib/guardtime.php'); $Timestamper_URL=$this->getConf('Timestamper_URL'); //The URL of the service for creating timestamps. $data = $event->data; // For debugging: // $finfo = ""; // if ($data[0][1]=="") $finfo = " Empty"; // if (!file_exists($data[0][0])) { $finfo .= " New"; } else { $finfo .= " Exists" ;}; // error_log("Filename: ".$data[0][0].$finfo." NS: ".$data[1]." ID: ".$data[2]." Rev: ".$data[3]); if ($data[0][1]=="") { // No content means the file is deleted // so the Timestamp should be deleted too, otherwise we clutter the dir unlink ($data[0][0].'.gtts'); } else { // hash the data file (not content!) using the default algorithm (currently SHA-256) $dataHash = new GTDataHash(GTHashAlgorithm::getByName('DEFAULT')); $dataHash->updateFile($data[0][0]); $dataHash->close(); // request a timestamp for the hash value try { $timestamp = GTHttpClient::create($dataHash, $Timestamper_URL); } catch (GTException $e) { $this->gt_log_exception($e); } // save the timestamp for archiving it along with the data file $timestamp->save($data[0][0].'.gtts'); } } /** * Handle for Output of Timestamping information at the page bottom. * * @param $event * @param $param * @return void */ public function handle_tpl_act_render(Doku_Event &$event, $param) { global $ID; global $REV; global $INFO; global $conf; global $ACT; global $mylang; $this->setupLocale(); $mylang=$this->lang; require_once(DOKU_INC.'lib/plugins/gtime/gtlib/guardtime.php'); $Publications_URL=$this->getConf('Publications_URL'); //The URL where the GuardTime publications file can be downloaded. //only when show action, page exists and its ID matches with settings if ($ACT == 'show' && $INFO['exists'] ){ if (file_exists($INFO['filepath'].".gtts") ) { // load the timestamp // error_log("Info-Filepath: ".$INFO['filepath']); $timestamp = GTTimestamp::load($INFO['filepath'].".gtts"); // Extend timestamp if (!$timestamp->isExtended()) { $this->gt_extend($timestamp,$INFO); } // hash the data file using the algorithm from the timestamp $dataHash = new GTDataHash($timestamp->getHashAlgorithm()); $dataHash->updateFile($INFO['filepath']); $dataHash->close(); // load the publications file // we assume it's trusted local copy and skip verification here $publicationsFile = $this->gt_publications_file(); try { // verify against the publications file $result = GTHttpClient::verify($timestamp, $dataHash, null, $publicationsFile); } catch (GTException $e) { $this->gt_log_exception($e); } if ($result->isValid()) { $invalid_warning =""; } else { $invalid_warning =''.$mylang['Validation_failed'].''; } //This, by some reason does not work with caching $link_to_download = exportlink($ID,"gtime",$REV==true ? "rev=$REV,purge=true": "purge=true"); $valid_summary=<< Timestamped by GuardTime $invalid_warning {$mylang['pagesign']} {$timestamp->getProperty(GTTimestamp::REGISTERED_TIME)} {$mylang['Details_Button']} {$mylang['Download_Button']}
EOT; $valid_details=<<