Changeset 287
- Timestamp:
- 01/26/10 12:24:06 (11 years ago)
- Location:
- trunk/server/www/app
- Files:
-
- 1 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server/www/app/controllers/jobs_controller.php
r256 r287 349 349 $job = array_shift($jobs); 350 350 351 $file = $this->Request->Behaviors->File->settings['directory'] . DS . $job['Request']['path']; 351 $this->Request->id = $job['Request']['id']; 352 $file = $this->Request->getPath(); 352 353 if (!file_exists($file) || !is_readable($file)) { 353 354 // Something went wrong. Expire the entire request 354 $this->Request->id = $job['Request']['id'];355 355 $this->Request->saveField('expire', date('Y-m-d H:i:s', time() -1)); 356 356 return array('faultCode' => 2, 'faultString' => 'Job document could not be read. Please poll again.'); … … 445 445 $job = $this->Job->find('first', array( 446 446 'conditions' => array('Job.id' => $job_id), 447 'contain' => array('Request', 'Request.Format') 447 'contain' => array( 448 'Request', 449 'Request.Format', 450 'Application', 451 'Platform', 452 ) 448 453 )); 449 454 … … 475 480 } 476 481 482 // Find out where to store the result 483 $path = $job['Request']['root'] . DS; 484 $path .= Inflector::slug($job['Application']['name']) . '_'; 485 $path .= Inflector::slug($job['Job']['version']) . '_'; 486 $path .= Inflector::slug($job['Platform']['name']); 487 477 488 // Create the Result 478 489 $this->Job->Result->create(); 479 490 $this->Job->Result->set(array( 480 491 'format_id' => $format['Format']['id'], 481 'factory_id' => $factory['Factory']['id'] 492 'factory_id' => $factory['Factory']['id'], 493 'path' => $path 482 494 )); 483 495 -
trunk/server/www/app/controllers/requests_controller.php
r286 r287 204 204 } 205 205 206 // Create a new request 206 // Set some extra data 207 $this->data['Request']['user_id'] = (string) $this->AuthCert->user('id'); 208 $this->data['Request']['ip_address'] = inet_ptod($this->RequestHandler->getClientIP()); 209 $this->data['Request']['expire'] = date('Y-m-d H:i:s', time() + Configure::read('Request.expire')); 210 $this->data['Request']['state'] = Request::STATE_PREPROCESSOR_QUEUED; 211 212 213 // Create the request 207 214 $this->Request->create(); 208 $this->data['Request']['user_id'] = (string) $this->AuthCert->user('id'); 209 $this->data['Request']['ip_address'] = inet_ptod($this->RequestHandler->getClientIP()); 215 if (!$this->Request->save($this->data)) { 216 $this->Session->setFlash(__('The request could not be saved', true)); 217 $this->redirect(array('action'=>'add')); 218 } 219 220 // Set root and path based on the ID 221 $this->Request->read(); 222 $this->Request->set(array( 223 'root' => 'requests' . DS . $this->Request->id, 224 'path' => 'requests' . DS . $this->Request->id . DS . 'source', 225 )); 226 227 // Add the file upload 228 $errors = array(); 229 if (!$this->Request->addUpload($this->data, $errors)) { 230 $this->Request->delete(); 231 $this->Session->setFlash(implode("<br />\n", $errors)); 232 $this->redirect(array('action'=>'add')); 233 } 210 234 211 235 // Add the jobs to the request 236 $jobs = array(); 212 237 foreach ($this->data['Request']['App'] as $app) { 213 238 list($platform_id, $doctype_code, $application_id, $version) = explode('_', $app); 214 $ this->data['Request']['Job'][] = compact('platform_id', 'doctype_code', 'application_id', 'version');215 } 216 217 // Save the request218 $errors = array();219 if (!$this->Request->add($this->data, $errors)) {220 $this->Session->setFlash( implode("<br />\n", $errors));239 $jobs[] = compact('platform_id', 'application_id', 'version'); 240 } 241 242 $this->Request->read(); 243 if ($this->Request->addJobs($jobs) == 0) { 244 $this->Request->delete(); 245 $this->Session->setFlash(__('None of the jobs could be created. The request has been cancelled.', true)); 221 246 $this->redirect(array('action'=>'add')); 222 247 } 223 248 224 if (sizeof($errors)) { 225 $this->Session->setFlash(implode("<br />\n", $errors)); 226 } 227 249 // Add ODF Validators 250 $this->Request->addValidators(); 251 252 // Queue the preprocessor 253 if (!$this->Request->defer('run', 'Preprocessor')) { 254 $errors[] = __('Failed to queue the request for the virus scanner. Please contact system administration.', true); 255 } 256 257 // All done! 228 258 $this->redirect(array('action' => 'view', 'id' => $this->Request->id)); 229 259 } … … 247 277 $doctypes = $this->Worker->Application->Doctype->find('all'); 248 278 $formats = $this->Request->Format->find('list'); 249 // $formatmap = $this->Request->Format->find('list', array('fields' => array('Format.id', 'Format.code')));250 279 $mimetypes = $this->Mimetype->find('all'); 251 280 … … 273 302 274 303 // This is the tricky bit. Set the highest version for every application/platform combo as default 275 // This requires the workers array to be sorted my platform, app, version304 // This requires the workers array to be sorted by platform, app, version 276 305 $short_id = false; 277 306 $platform_id = ''; … … 310 339 $this->view = 'Media'; 311 340 $this->set(array( 312 'id' => $ filename,313 'name' => substr($filename, 0, strrpos($filename, '.')),341 'id' => $id, 342 'name' => $filename, 314 343 'download' => true, 315 344 'extension' => 'zip', -
trunk/server/www/app/controllers/results_controller.php
r281 r287 120 120 121 121 $result = $this->_getResult($id); 122 $extpos = strrpos($result['Result']['filename'], '.'); 123 $filename = substr($result['Result']['filename'], 0, $extpos); 124 $extension = substr($result['Result']['filename'], $extpos + 1); 125 $directory = $this->Result->Behaviors->File->settings['directory']; 122 $path = $this->Result->getPath(); 123 $filename = basename($path); 124 $extpos = strrpos($filename, '.'); 125 $name = substr($filename, 0, $extpos); 126 $extension = substr($filename, $extpos + 1); 126 127 127 128 $this->view = 'Media'; 128 129 $this->set(array( 129 'id' => $ result['Result']['path'],130 'name' => $ filename,130 'id' => $filename, 131 'name' => $name, 131 132 'download' => true, 132 133 'extension' => $extension, 133 'path' => $directory. DS,134 'path' => dirname($path) . DS, 134 135 // NOTE: This short-circuits CakePHP's crude filetype check 135 136 'mimeType' => array($extension => $result['Mimetype']['name']), -
trunk/server/www/app/models/behaviors/file.php
r286 r287 66 66 67 67 if (!is_writeable($this->settings['directory'])) { 68 $this->errors[] = __('File storage directory does not exist.', true);69 return;70 }71 72 if (!is_writeable($this->settings['directory'])) {73 68 $this->errors[] = __('File storage directory is not writeable.', true); 74 69 return; … … 127 122 } 128 123 129 $destination = $this->_generatePath($file['name']); 130 if (!move_uploaded_file($file['tmp_name'], $this->settings['directory'] . DS . $destination)) { 124 $destination = $this->settings['directory'] . DS . $model->data[$model->name][$this->settings['fields']['path']] . DS . $file['name']; 125 if (!mkdir(dirname($destination), 0775, true)) { 126 $this->errors[] = __('Could not create the destination directory.', true); 127 return false; 128 } 129 130 if (!move_uploaded_file($file['tmp_name'], $destination)) { 131 131 $this->errors[] = __('The uploaded file cannot be moved.', true); 132 132 return false; … … 136 136 $this->settings['fields']['filename'] => $file['name'], 137 137 $this->settings['fields']['mimetype_id'] => $mimetype['Mimetype']['id'], 138 $this->settings['fields']['path'] => $destination139 138 )); 140 139 141 140 return true; 142 }143 144 /**145 * Set the file records to any file146 *147 * @param object $model A reference to the model148 * @param string $path full path to the file149 * @param boolean $move True if the file should be moved, false if it should be copied.150 * @return boolean True on success or false on failure151 */152 public function setFile(&$model, $path = false, $move = false)153 {154 if (!$path) {155 $this->errors[] = __('There was no file', true);156 return false;157 }158 159 if (!is_readable($path)) {160 $this->errors[] = __('The file cannot be read.', true);161 return false;162 }163 164 $mimestring = '';165 if (!$mimetype = $this->_getMimetype($model, $path, $mimestring)) {166 $this->errors[] = sprintf(__('Invalid mimetype %s detected for file', true), $mimestring);167 return false;168 }169 170 if (!$this->_checkMimetype($mimetype)) {171 $this->errors[] = __('Illegal mimetype.', true);172 return false;173 }174 175 $filename = basename($path);176 $destination = $this->_generatePath($filename);177 if ($move) {178 $result = rename($path, $this->settings['directory'] . DS . $destination);179 } else {180 $result = copy($path, $this->settings['directory'] . DS . $destination);181 }182 183 if (!$result) {184 $this->errors = __('The file could not be copied or moved.');185 return false;186 }187 188 $model->set(array(189 $this->settings['fields']['filename'] => $filename,190 $this->settings['fields']['mimetype_id'] => $mimetype['Mimetype']['id'],191 $this->settings['fields']['path'] => $destination192 ));193 194 return True;195 141 } 196 142 … … 205 151 public function setFileBuffer(&$model, &$buffer, $filename, $filters = false) 206 152 { 207 $destination_file = $this->_generatePath($filename); 208 $destination_path = $this->settings['directory'] . DS . $destination_file; 209 210 if (!$file = fopen($destination_path, 'w')) { 153 $destination = $this->settings['directory'] . DS . $model->data[$model->name][$this->settings['fields']['path']] . DS . $filename; 154 155 if (!file_exists(dirname($destination)) && !mkdir(dirname($destination), 0775, true)) { 156 $this->errors[] = __('Could not create the destination directory.', true); 157 return false; 158 } 159 160 161 if (!$file = fopen($destination, 'w')) { 211 162 $this->errors[] = __('Cannot write file from buffer.', true); 212 163 return false; … … 227 178 228 179 $mimestring = ''; 229 if (!$mimetype = $this->_getMimetype($model, $destination _path, $mimestring)) {180 if (!$mimetype = $this->_getMimetype($model, $destination, $mimestring)) { 230 181 $this->errors[] = sprintf(__('Invalid mimetype %s detected for file buffer', true), $mimestring); 231 unlink($destination _path);182 unlink($destination); 232 183 return false; 233 184 } … … 235 186 if (!$this->_checkMimetype($mimetype)) { 236 187 $this->errors[] = __('Illegal mimetype.', true); 237 unlink($destination _path);188 unlink($destination); 238 189 return false; 239 190 } … … 242 193 $this->settings['fields']['filename'] => $filename, 243 194 $this->settings['fields']['mimetype_id'] => $mimetype['Mimetype']['id'], 244 $this->settings['fields']['path'] => $destination_file245 195 )); 246 196 … … 260 210 } 261 211 262 $path = $model->field('path'); 263 if (!$path && !is_file($this->settings['directory'] . DS . $path)) { 212 if (($path = $this->getPath($model)) == false) { 264 213 return true; // There is no file 265 214 } 266 215 267 if (!is_writeable($ this->settings['directory'] . DS . $path)) {216 if (!is_writeable($path)) { 268 217 $this->errors[] = __('The file cannot be deleted.', true); 269 218 return false; 270 219 } 271 220 272 return unlink($ this->settings['directory'] . DS . $path);221 return unlink($path); 273 222 } 274 223 … … 285 234 } 286 235 287 $path = $model->field('path'); 288 if (!$path && !is_file($this->settings['directory'] . DS . $path)) { 289 return null; // There is no file 290 } 291 292 return file_get_contents($this->settings['directory'] . DS . $path); 236 if ($path = $this->getPath($model)) { 237 return file_get_contents($this->settings['directory'] . DS . $path); 238 } 239 240 return null; 293 241 } 294 242 … … 302 250 { 303 251 if ($model->id) { 304 $path = $model->field($this->settings['fields']['path']); 252 // Load the data from the database 253 $path = $model->field($this->settings['fields']['path']); 254 $filename = $model->field($this->settings['fields']['filename']); 305 255 } elseif (isset($model->data[$model->name][$this->settings['fields']['path']])) { 306 $path = $model->data[$model->name][$this->settings['fields']['path']]; 256 // Get the data from the currently assigned model data 257 $path = $model->data[$model->name][$this->settings['fields']['path']]; 258 $filename = $model->data[$model->name][$this->settings['fields']['filename']]; 307 259 } else { 308 return false; 309 } 310 311 if (!$path || !is_file($this->settings['directory'] . DS . $path)) { 260 // Can't retrieve data 261 return false; 262 } 263 264 if (!$path || !$filename || !is_file($this->settings['directory'] . DS . $path . DS . $filename)) { 312 265 return false; // There is no file 313 266 } 314 267 315 return $this->settings['directory'] . DS . $path; 316 } 317 318 /** 319 * Generate a new full path to write to 320 */ 321 protected function _generatePath($filename) 322 { 323 $path = String::uuid(); 324 325 $this->log('_generatePath: uuid is ' . $path, LOG_DEBUG); 326 $this->log('_generatePath: filename is ' . $filename, LOG_DEBUG); 327 if ($filename) { 328 $ext = strrchr($filename, '.'); 329 $this->log('_generatePath: ext is ' . $ext, LOG_DEBUG); 330 if ($ext !== false) { 331 $path .= $ext; 332 } 333 } 334 335 return $path; 268 return $this->settings['directory'] . DS . $path . DS . $filename; 336 269 } 337 270 … … 382 315 public function beforeSave(&$model) 383 316 { 384 if (!isset($model->data[$model->name][$this->settings['fields'][' path']])) {317 if (!isset($model->data[$model->name][$this->settings['fields']['filename']])) { 385 318 return true; // No file is being saved 386 319 } 387 320 388 $filename = $model->data[$model->name][$this->settings['fields']['path']]; 389 390 if ($filename && !file_exists($this->settings['directory'] . DS . $filename)) { 321 $path = $this->getPath($model); 322 if ($path && !file_exists($path)) { 391 323 $this->errors[] = __('The filename field is set but the file does not exist', true); 392 324 } … … 407 339 public function beforeDelete(&$model) 408 340 { 409 $ filename = $this->settings['directory'] . DS . $model->field($this->settings['fields']['path']);410 if (file_exists($ filename)) {411 if (!unlink($ filename)) {341 $path = $this->getPath($model); 342 if (file_exists($path)) { 343 if (!unlink($path)) { 412 344 $this->errors[] = __('The file could not be deleted.', true); 413 345 } -
trunk/server/www/app/models/request.php
r286 r287 53 53 'Containable', 54 54 'BeanStalk.Deferrable', 55 'File' => 'files /requests',55 'File' => 'files', 56 56 'Pipeline' => 'Preprocessor', 57 57 ); … … 75 75 76 76 /** 77 * Create a new request with underlying jobs77 * Add an upload to the request 78 78 * 79 79 * If the add fails, &$errors contains the error messages … … 83 83 * @return boolean Success 84 84 */ 85 public function add ($data, &$errors = array())85 public function addUpload($data, $anonymise = false, &$errors = array()) 86 86 { 87 87 if (empty($data)) { … … 89 89 return false; 90 90 } 91 $this->set($data);92 $this->set(array(93 'expire' => date('Y-m-d H:i:s', time() + Configure::read('Request.expire')),94 'state' => self::STATE_PREPROCESSOR_QUEUED95 ));96 91 97 92 // Check that we have a file and jobs 98 if ((!isset($data['Request']['FileUpload']) || !is_array($data['Request']['FileUpload'])) && !isset($data['Request']['File']) && !isset($data['Request']['FileBuffer'])) {93 if ((!isset($data['Request']['FileUpload']) || !is_array($data['Request']['FileUpload']))) { 99 94 $errors[] = __('You did not submit a file.', true); 100 95 return false; 101 96 } 102 97 103 if (!isset($data['Request']['Job']) || !is_array($data['Request']['Job']) || empty($data['Request']['Job'])) { 104 $errors[] = __('You did not select any valid applications', true); 105 return false; 106 } 107 108 // Add the file 109 if (isset($data['Request']['FileUpload'])) { 110 if (!$this->setFileUpload($data['Request']['FileUpload'])) { 111 $errors[] = __('The file upload failed. Please try again.', true); 112 $errors = array_merge($errors, $this->Behaviors->File->errors); 113 return false; 114 } 115 } elseif (isset($data['Request']['File'])) { 116 if (!$this->setFile($data['Request']['File'])) { 117 $errors[] = __('Adding the file failed. Please try again.', true); 118 $errors = array_merge($errors, $this->Behaviors->File->errors); 119 return false; 120 } 121 } else { 122 if (!$this->setFileBuffer($data['Request']['FileBuffer']['contents'], $data['Request']['FileBuffer']['filename'])) { 123 $errors[] = __('Adding the file buffer failed. Please try again.', true); 124 $errors = array_merge($errors, $this->Behaviors->File->errors); 125 return false; 126 } 98 if (!$this->setFileUpload($data['Request']['FileUpload'])) { 99 $errors[] = __('The file upload failed. Please try again.', true); 100 $errors = array_merge($errors, $this->Behaviors->File->errors); 101 return false; 127 102 } 128 103 129 104 // Run the ODF anonymiser if requested 130 if ($ this->data['Request']['anonymise']) {105 if ($data['Request']['anonymise']) { 131 106 if (!$this->anonymise()) { 107 $this->deleteFile(); 132 108 $errors[] = __('The Anonymiser failed to run', true); 133 109 return false; 134 110 } 135 111 } 136 unset($this->data['Request']['anonymise']); 137 138 // Save the request 139 if (($this->data = $this->save()) === false) { 140 $this->deleteFile(); 141 $errors[] = __('The request could not be saved.', true); 142 return false; 143 } 112 unset($data['Request']['anonymise']); 113 114 return $this->save(); 115 } 116 117 /** 118 * Add jobs to this request 119 * 120 * @param array $jobs An array of jobs 121 * @return int The number of jobs created 122 */ 123 public function addJobs($jobs = array()) 124 { 125 // Load the Application model. We need that below. 126 $Application = ClassRegistry::init('Application'); 144 127 145 128 // Find the Mimetype associated with the request … … 149 132 ))); 150 133 151 // Create jobs for this request 152 $jobErrors = 0; 153 foreach ($data['Request']['Job'] as $job) { 134 $jobCount = 0; 135 foreach ($jobs as $job) { 154 136 $job['request_id'] = $this->id; 155 137 156 // If the job contains a doctype_code, check it 157 if ($job['doctype_code']) { 158 if ($job['doctype_code'] != $mimetype['Doctype']['code']) { 159 $jobErrors++; 160 continue; 161 } 138 // Check the request mimetype against the supported doctype 139 $count = $Application->find('count', array( 140 'contain' => array( 141 'Application.id' => $job['application_id'], 142 'Doctype.code' => $mimetype['Doctype']['code'] 143 ), 144 )); 145 146 if ($count == 0) { 147 continue; 162 148 } 163 149 164 150 $this->Job->create(); 165 if (!$this->Job->save(array('Job' => $job))) { 166 $jobErrors++; 167 } 168 } 169 170 if ($jobErrors == sizeof($data['Request']['Job'])) { 171 $this->delete(); 172 $errors[] = __('None of the jobs could be created. The request has been cancelled.', true); 173 return false; 174 } 175 176 if ($jobErrors) { 177 $errors[] = __('Not all jobs could be created.', true); 178 } 179 180 // Create validators for this request 151 if ($this->Job->save(array('Job' => $job))) { 152 $jobCount++; 153 } 154 } 155 156 return $jobCount; 157 } 158 159 /** 160 * Add ODF validators for the request 161 */ 162 public function addValidators() 163 { 181 164 $validators = Configure::read('Validator'); 182 165 foreach ($validators as $validator_name => $validator_config) { … … 191 174 ))); 192 175 } 193 194 // Schedule the preprocessor to run195 if (!$this->defer('run', 'Preprocessor')) {196 $errors[] = __('Failed to queue the request for the virus scanner. Please contact system administration.', true);197 }198 199 return true;200 176 } 201 177 … … 236 212 * Generate a zipfile containing the original request and all results 237 213 * 238 * @return array an array containing the directory and filename of the zipfileor null214 * @return array an array containing the directory, id and filename of the zipfile to be used by the media view, or null 239 215 */ 240 216 public function createZip() … … 244 220 } 245 221 246 $ directory = $this->Behaviors->File->settings['directory'];222 $root = $this->Behaviors->File->settings['directory'] . DS . $this->field('root'); 247 223 $filename = $this->field('filename'); 248 $zipdir = 'officeshots-' . substr($filename, 0, strrpos($filename, '.')); 249 $filename = $zipdir . '.zip'; 250 251 if (file_exists($directory . DS . $filename)) { 252 unlink($directory . DS . $filename); 253 } 254 $zip = new ZipArchive(); 255 $zip->open($directory . DS . $filename, ZIPARCHIVE::CREATE); 256 $zip->addFromString($zipdir . '/' . $this->field('filename'), $this->getContents()); 257 258 $jobs = $this->Job->find('all', array( 259 'conditions' => array( 260 'Job.request_id' => $this->id, 261 'Job.result_id <>' => '', 262 ) 263 )); 264 265 foreach ($jobs as $job) { 266 $appname = $job['Application']['name'] . '_' 267 . $job['Job']['version'] 268 . '_' . $job['Platform']['name']; 269 $appname = preg_replace('/[^a-z0-9._-]/', '_', low($appname)); 270 $appname = preg_replace('/_{2,}/', '_', $appname); 271 272 $this->Job->Result->id = $job['Result']['id']; 273 $extension = substr($job['Result']['filename'], strrpos($job['Result']['filename'], '.') + 1); 274 $zip->addFromString($zipdir . '/' . $appname . '.' . $extension, $this->Job->Result->getContents()); 275 } 276 $zip->close(); 277 278 return compact('directory', 'filename'); 224 $filename = substr($filename, 0, strrpos($filename, '.')); 225 $directory = TMP . 'zips'; 226 $id = $this->id . '.zip'; 227 228 if (file_exists($directory . DS . $id)) { 229 unlink($directory . DS . $id); 230 } 231 232 $cwd = getcwd(); 233 chdir($root); 234 shell_exec('cd "' . $root . '" && zip -r "' . $directory . DS . $id . '" .'); 235 chdir($cwd); 236 237 return compact('id', 'directory', 'filename'); 279 238 } 280 239 -
trunk/server/www/app/models/result.php
r279 r287 55 55 'Containable', 56 56 'BeanStalk.Deferrable', 57 'File' => 'files /results',57 'File' => 'files', 58 58 'Pipeline' => 'Postprocessor', 59 59 );
Note: See TracChangeset
for help on using the changeset viewer.