1 <?php
2 3 4 5 6 7 8
9
10 defined('JPATH_PLATFORM') or die;
11
12 jimport('joomla.filesystem.folder');
13
14 15 16 17 18
19 class JInstallerAdapterFile extends JInstallerAdapter
20 {
21 22 23 24 25 26
27 protected $scriptElement = null;
28
29 30 31 32 33 34 35 36
37 protected $supportsDiscoverInstall = false;
38
39 40 41 42 43 44 45 46
47 protected function copyBaseFiles()
48 {
49
50 $this->populateFilesAndFolderList();
51
52
53 foreach ($this->folderList as $folder)
54 {
55 if (!JFolder::exists($folder))
56 {
57 if (!$created = JFolder::create($folder))
58 {
59 throw new RuntimeException(
60 JText::sprintf('JLIB_INSTALLER_ABORT_FILE_INSTALL_FAIL_SOURCE_DIRECTORY', $folder)
61 );
62 }
63
64
65
66 if ($created)
67 {
68 $this->parent->pushStep(array('type' => 'folder', 'path' => $folder));
69 }
70 }
71 }
72
73
74 $this->parent->copyFiles($this->fileList);
75 }
76
77 78 79 80 81 82 83 84
85 protected function finaliseInstall()
86 {
87
88 $update = JTable::getInstance('update');
89
90 $uid = $update->find(
91 array(
92 'element' => $this->element,
93 'type' => $this->type,
94 )
95 );
96
97 if ($uid)
98 {
99 $update->delete($uid);
100 }
101
102
103 $manifest = array();
104 $manifest['src'] = $this->parent->getPath('manifest');
105 $manifest['dest'] = JPATH_MANIFESTS . '/files/' . basename($this->parent->getPath('manifest'));
106
107 if (!$this->parent->copyFiles(array($manifest), true))
108 {
109
110 throw new RuntimeException(JText::_('JLIB_INSTALLER_ABORT_FILE_INSTALL_COPY_SETUP'));
111 }
112
113
114 if ($this->manifest_script)
115 {
116
117 if (!file_exists($this->parent->getPath('extension_root')))
118 {
119 JFolder::create($this->parent->getPath('extension_root'));
120 }
121
122 $path['src'] = $this->parent->getPath('source') . '/' . $this->manifest_script;
123 $path['dest'] = $this->parent->getPath('extension_root') . '/' . $this->manifest_script;
124
125 if ($this->parent->isOverwrite() || !file_exists($path['dest']))
126 {
127 if (!$this->parent->copyFiles(array($path)))
128 {
129
130 throw new RuntimeException(
131 JText::sprintf(
132 'JLIB_INSTALLER_ABORT_MANIFEST',
133 JText::_('JLIB_INSTALLER_' . strtoupper($this->route))
134 )
135 );
136 }
137 }
138 }
139 }
140
141 142 143 144 145 146 147 148 149
150 public function getElement($element = null)
151 {
152 if (!$element)
153 {
154 $manifestPath = JPath::clean($this->parent->getPath('manifest'));
155 $element = preg_replace('/\.xml/', '', basename($manifestPath));
156 }
157
158 return $element;
159 }
160
161 162 163 164 165 166 167 168 169
170 public function loadLanguage($path)
171 {
172 $extension = 'files_' . strtolower(str_replace('files_', '', $this->getElement()));
173
174 $this->doLoadLanguage($extension, $path, JPATH_SITE);
175 }
176
177 178 179 180 181 182 183
184 protected function parseOptionalTags()
185 {
186
187 $this->parent->parseLanguages($this->getManifest()->languages);
188 }
189
190 191 192 193 194 195 196
197 protected function setupInstallPaths()
198 {
199
200 if ($this->name === 'files_joomla')
201 {
202
203 $this->parent->setPath('extension_root', JPATH_ROOT);
204 }
205 else
206 {
207 $this->parent->setPath('extension_root', JPATH_MANIFESTS . '/files/' . $this->element);
208 }
209 }
210
211 212 213 214 215 216 217 218
219 protected function storeExtension()
220 {
221 if ($this->currentExtensionId)
222 {
223
224 $this->extension->load($this->currentExtensionId);
225
226
227 $this->extension->name = $this->name;
228
229
230 $this->extension->manifest_cache = $this->parent->generateManifestCache();
231
232 if (!$this->extension->store())
233 {
234
235 throw new RuntimeException(
236 JText::sprintf(
237 'JLIB_INSTALLER_ABORT_ROLLBACK',
238 JText::_('JLIB_INSTALLER_' . strtoupper($this->route)),
239 $this->extension->getError()
240 )
241 );
242 }
243 }
244 else
245 {
246
247 $this->extension->name = $this->name;
248 $this->extension->type = 'file';
249 $this->extension->element = $this->element;
250
251
252 $this->extension->folder = '';
253 $this->extension->enabled = 1;
254 $this->extension->protected = 0;
255 $this->extension->access = 0;
256 $this->extension->client_id = 0;
257 $this->extension->params = '';
258 $this->extension->system_data = '';
259 $this->extension->manifest_cache = $this->parent->generateManifestCache();
260 $this->extension->custom_data = '';
261
262 if (!$this->extension->store())
263 {
264
265 throw new RuntimeException(
266 JText::sprintf(
267 'JLIB_INSTALLER_ABORT_ROLLBACK',
268 JText::_('JLIB_INSTALLER_' . strtoupper($this->route)),
269 $this->extension->getError()
270 )
271 );
272 }
273
274
275
276 $this->parent->pushStep(array('type' => 'extension', 'extension_id' => $this->extension->extension_id));
277 }
278 }
279
280 281 282 283 284 285 286 287 288
289 public function uninstall($id)
290 {
291 $row = JTable::getInstance('extension');
292
293 if (!$row->load($id))
294 {
295 JLog::add(JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_LOAD_ENTRY'), JLog::WARNING, 'jerror');
296
297 return false;
298 }
299
300 if ($row->protected)
301 {
302 JLog::add(JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_WARNCOREFILE'), JLog::WARNING, 'jerror');
303
304 return false;
305 }
306
307 308 309 310
311 if ($row->package_id && !$this->parent->isPackageUninstall() && !$this->canUninstallPackageChild($row->package_id))
312 {
313 JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_CANNOT_UNINSTALL_CHILD_OF_PACKAGE', $row->name), JLog::WARNING, 'jerror');
314
315 return false;
316 }
317
318 $retval = true;
319 $manifestFile = JPATH_MANIFESTS . '/files/' . $row->element . '.xml';
320
321
322 if (file_exists($manifestFile))
323 {
324
325 $this->parent->setPath('extension_root', JPATH_MANIFESTS . '/files/' . $row->element);
326
327 $xml = simplexml_load_file($manifestFile);
328
329
330 if (!$xml)
331 {
332 JLog::add(JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_LOAD_MANIFEST'), JLog::WARNING, 'jerror');
333
334 return false;
335 }
336
337
338 if ($xml->getName() !== 'extension')
339 {
340 JLog::add(JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_INVALID_MANIFEST'), JLog::WARNING, 'jerror');
341
342 return false;
343 }
344
345 $this->setManifest($xml);
346
347
348 $this->scriptElement = $this->getManifest()->scriptfile;
349 $manifestScript = (string) $this->getManifest()->scriptfile;
350
351 if ($manifestScript)
352 {
353 $manifestScriptFile = $this->parent->getPath('extension_root') . '/' . $manifestScript;
354
355
356 $classname = $row->element . 'InstallerScript';
357
358 JLoader::register($classname, $manifestScriptFile);
359
360 if (class_exists($classname))
361 {
362
363 $this->parent->manifestClass = new $classname($this);
364
365
366 $this->set('manifest_script', $manifestScript);
367 }
368 }
369
370 ob_start();
371 ob_implicit_flush(false);
372
373
374 if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'uninstall'))
375 {
376 $this->parent->manifestClass->uninstall($this);
377 }
378
379 $msg = ob_get_contents();
380 ob_end_clean();
381
382 if ($msg != '')
383 {
384 $this->parent->set('extension_message', $msg);
385 }
386
387 $db = JFactory::getDbo();
388
389
390 $result = $this->parent->parseSQLFiles($this->getManifest()->uninstall->sql);
391
392 if ($result === false)
393 {
394
395 JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_SQL_ERROR', $db->stderr(true)), JLog::WARNING, 'jerror');
396 $retval = false;
397 }
398
399
400 $query = $db->getQuery(true)
401 ->delete('#__schemas')
402 ->where('extension_id = ' . $row->extension_id);
403 $db->setQuery($query);
404 $db->execute();
405
406
407 foreach ($xml->fileset->files as $eFiles)
408 {
409 $target = (string) $eFiles->attributes()->target;
410
411
412 if (empty($target))
413 {
414 $targetFolder = JPATH_ROOT;
415 }
416 else
417 {
418 $targetFolder = JPATH_ROOT . '/' . $target;
419 }
420
421 $folderList = array();
422
423
424 if (count($eFiles->children()) > 0)
425 {
426
427 foreach ($eFiles->children() as $eFileName)
428 {
429 if ($eFileName->getName() === 'folder')
430 {
431 $folderList[] = $targetFolder . '/' . $eFileName;
432 }
433 else
434 {
435 $fileName = $targetFolder . '/' . $eFileName;
436 JFile::delete($fileName);
437 }
438 }
439 }
440
441
442 foreach ($folderList as $folder)
443 {
444 $files = JFolder::files($folder);
445
446 if (!count($files))
447 {
448 JFolder::delete($folder);
449 }
450 }
451 }
452
453 JFile::delete($manifestFile);
454
455
456 $folder = $this->parent->getPath('extension_root');
457
458 if (JFolder::exists($folder))
459 {
460 JFolder::delete($folder);
461 }
462 }
463 else
464 {
465 JLog::add(JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_INVALID_NOTFOUND_MANIFEST'), JLog::WARNING, 'jerror');
466
467
468 $row->delete();
469
470 return false;
471 }
472
473 $this->parent->removeFiles($xml->languages);
474
475 $row->delete();
476
477 return $retval;
478 }
479
480 481 482 483 484 485 486 487 488
489 protected function extensionExistsInSystem($extension = null)
490 {
491
492 $db = $this->parent->getDbo();
493
494 $query = $db->getQuery(true)
495 ->select($db->quoteName('extension_id'))
496 ->from($db->quoteName('#__extensions'))
497 ->where($db->quoteName('type') . ' = ' . $db->quote('file'))
498 ->where($db->quoteName('element') . ' = ' . $db->quote($extension));
499 $db->setQuery($query);
500
501 try
502 {
503 $db->execute();
504 }
505 catch (RuntimeException $e)
506 {
507
508 $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_FILE_ROLLBACK', $db->stderr(true)));
509
510 return false;
511 }
512 $id = $db->loadResult();
513
514 if (empty($id))
515 {
516 return false;
517 }
518
519 return true;
520 }
521
522 523 524 525 526 527 528
529 protected function populateFilesAndFolderList()
530 {
531
532 $this->folderList = array();
533 $this->fileList = array();
534
535
536 $packagePath = $this->parent->getPath('source');
537 $jRootPath = JPath::clean(JPATH_ROOT);
538
539
540 foreach ($this->getManifest()->fileset->files as $eFiles)
541 {
542
543 $folder = (string) $eFiles->attributes()->folder;
544 $target = (string) $eFiles->attributes()->target;
545
546
547 $arrList = preg_split("#/|\\/#", $target);
548
549 $folderName = $jRootPath;
550
551 foreach ($arrList as $dir)
552 {
553 if (empty($dir))
554 {
555 continue;
556 }
557
558 $folderName .= '/' . $dir;
559
560
561 if (!JFolder::exists($folderName))
562 {
563 $this->folderList[] = $folderName;
564 }
565 }
566
567
568 $sourceFolder = empty($folder) ? $packagePath : $packagePath . '/' . $folder;
569 $targetFolder = empty($target) ? $jRootPath : $jRootPath . '/' . $target;
570
571
572 if (!JFolder::exists($sourceFolder))
573 {
574 JLog::add(JText::sprintf('JLIB_INSTALLER_ABORT_FILE_INSTALL_FAIL_SOURCE_DIRECTORY', $sourceFolder), JLog::WARNING, 'jerror');
575
576
577 $this->parent->abort();
578
579 return false;
580 }
581
582
583 if (count($eFiles->children()))
584 {
585
586 foreach ($eFiles->children() as $eFileName)
587 {
588 $path['src'] = $sourceFolder . '/' . $eFileName;
589 $path['dest'] = $targetFolder . '/' . $eFileName;
590 $path['type'] = 'file';
591
592 if ($eFileName->getName() === 'folder')
593 {
594 $folderName = $targetFolder . '/' . $eFileName;
595 $this->folderList[] = $folderName;
596 $path['type'] = 'folder';
597 }
598
599 $this->fileList[] = $path;
600 }
601 }
602 else
603 {
604 $files = JFolder::files($sourceFolder);
605
606 foreach ($files as $file)
607 {
608 $path['src'] = $sourceFolder . '/' . $file;
609 $path['dest'] = $targetFolder . '/' . $file;
610
611 $this->fileList[] = $path;
612 }
613 }
614 }
615 }
616
617 618 619 620 621 622 623
624 public function refreshManifestCache()
625 {
626
627 $manifestPath = JPATH_MANIFESTS . '/files/' . $this->parent->extension->element . '.xml';
628 $this->parent->manifest = $this->parent->isManifest($manifestPath);
629 $this->parent->setPath('manifest', $manifestPath);
630
631 $manifest_details = JInstaller::parseXMLInstallFile($this->parent->getPath('manifest'));
632 $this->parent->extension->manifest_cache = json_encode($manifest_details);
633 $this->parent->extension->name = $manifest_details['name'];
634
635 try
636 {
637 return $this->parent->extension->store();
638 }
639 catch (RuntimeException $e)
640 {
641 JLog::add(JText::_('JLIB_INSTALLER_ERROR_PACK_REFRESH_MANIFEST_CACHE'), JLog::WARNING, 'jerror');
642
643 return false;
644 }
645 }
646 }
647
648 649 650 651 652 653 654
655 class JInstallerFile extends JInstallerAdapterFile
656 {
657 }
658