1<?php 2 3/** 4 * DokuWiki Plugin imgpaste (Action Component) 5 * 6 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 7 * @author Andreas Gohr <gohr@cosmocode.de> 8 */ 9class action_plugin_imgpaste extends DokuWiki_Action_Plugin 10{ 11 12 protected $tempdir = ''; 13 protected $tempfile = ''; 14 15 /** 16 * Clean up on destruction 17 */ 18 public function __destruct() 19 { 20 $this->clean(); 21 } 22 23 /** @inheritdoc */ 24 public function register(Doku_Event_Handler $controller) 25 { 26 $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjaxUpload'); 27 } 28 29 /** 30 * Creates a new file from the given data URL 31 * 32 * @param Doku_Event $event AJAX_CALL_UNKNOWN 33 */ 34 public function handleAjaxUpload(Doku_Event $event) 35 { 36 if ($event->data != 'plugin_imgpaste') return; 37 global $lang; 38 39 // get data 40 global $INPUT; 41 $data = $INPUT->post->str('data'); 42 list($type, $data) = explode(';', $data); 43 if (!$data) $this->fail(400, $this->getLang('e_nodata')); 44 45 // process data encoding 46 $type = strtolower(substr($type, 5)); // strip 'data:' prefix 47 $data = substr($data, 7); // strip 'base64,' prefix 48 $data = base64_decode($data); 49 50 // check for supported mime type 51 $mimetypes = array_flip(getMimeTypes()); 52 if (!isset($mimetypes[$type])) $this->fail(415, $lang['uploadwrong']); 53 54 // prepare file names 55 $tempname = $this->storetemp($data); 56 $filename = $this->createFileName($INPUT->post->str('id'), $mimetypes[$type], $_SERVER['REMOTE_USER']); 57 58 // check ACLs 59 $auth = auth_quickaclcheck($filename); 60 if ($auth < AUTH_UPLOAD) $this->fail(403, $lang['uploadfail']); 61 62 // do the actual saving 63 $result = media_save( 64 [ 65 'name' => $tempname, 66 'mime' => $type, 67 'ext' => $mimetypes[$type], 68 ], 69 $filename, 70 false, 71 $auth, 72 'copy' 73 ); 74 if (is_array($result)) $this->fail(500, $result[0]); 75 76 //Still here? We had a successful upload 77 $this->clean(); 78 header('Content-Type: application/json'); 79 echo json_encode([ 80 'message' => $lang['uploadsucc'], 81 'id' => $result, 82 'mime' => $type, 83 'ext' => $mimetypes[$type], 84 'url' => ml($result), 85 ]); 86 87 $event->preventDefault(); 88 $event->stopPropagation(); 89 } 90 91 /** 92 * Create the filename for the new file 93 * 94 * @param string $pageid the original page the paste event happend on 95 * @param string $ext the extension of the file 96 * @param string $user the currently logged in user 97 * @return string 98 */ 99 protected function createFileName($pageid, $ext, $user) 100 { 101 $filename = $this->getConf('filename'); 102 $filename = str_replace( 103 [ 104 '@NS@', 105 '@ID@', 106 '@USER@', 107 '@PAGE@', 108 ], 109 [ 110 getNS($pageid), 111 $pageid, 112 $user, 113 noNS($pageid), 114 ], 115 $filename 116 ); 117 $filename = strftime($filename); 118 $filename .= '.' . $ext; 119 return cleanID($filename); 120 } 121 122 /** 123 * Create a temporary file from the given data 124 * 125 * exits if an error occurs 126 * 127 * @param $data 128 * @return string 129 */ 130 protected function storetemp($data) 131 { 132 // store in temporary file 133 $this->tempdir = io_mktmpdir(); 134 if (!$this->tempdir) $this->fail(500); 135 $this->tempfile = $this->tempdir . '/' . md5($data); 136 if (!io_saveFile($this->tempfile, $data)) $this->fail(500); 137 return $this->tempfile; 138 } 139 140 /** 141 * remove temporary file and directory 142 */ 143 protected function clean() 144 { 145 if ($this->tempfile && file_exists($this->tempfile)) @unlink($this->tempfile); 146 if ($this->tempdir && is_dir($this->tempdir)) @rmdir($this->tempdir); 147 $this->tempfile = ''; 148 $this->tempdir = ''; 149 } 150 151 /** 152 * End the execution with a HTTP error code 153 * 154 * Calls clean 155 * 156 * @param int $status HTTP status code 157 * @param string $text 158 */ 159 protected function fail($status, $text = '') 160 { 161 $this->clean(); 162 http_status($status, $text); 163 exit; 164 } 165 166} 167