1 <?php
2 3 4 5 6 7 8
9
10 defined('JPATH_PLATFORM') or die;
11
12 13 14 15 16
17 class JInstallerAdapterPackage extends JInstallerAdapter
18 {
19 20 21 22 23 24
25 private static $eventRegistered = false;
26
27 28 29 30 31 32
33 protected $installedIds = array();
34
35 36 37 38 39 40
41 protected $results = array();
42
43 44 45 46 47 48 49 50
51 protected $supportsDiscoverInstall = false;
52
53 54 55 56 57 58 59 60
61 protected function checkExtensionInFilesystem()
62 {
63
64 if (file_exists(JPATH_MANIFESTS . '/packages/' . basename($this->parent->getPath('manifest'))))
65 {
66
67 $updateElement = $this->manifest->update;
68
69
70 if ($updateElement || $this->parent->isUpgrade()
71 || ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'update')))
72 {
73
74 $this->parent->setOverwrite(true);
75 $this->parent->setUpgrade(true);
76
77 if ($this->currentExtensionId)
78 {
79
80 $this->setRoute('update');
81 }
82 }
83 elseif (!$this->parent->isOverwrite())
84 {
85
86 throw new RuntimeException(
87 JText::sprintf(
88 'JLIB_INSTALLER_ABORT_DIRECTORY',
89 JText::_('JLIB_INSTALLER_' . $this->route),
90 $this->type,
91 $this->parent->getPath('extension_root')
92 )
93 );
94 }
95 }
96 }
97
98 99 100 101 102 103 104 105
106 protected function copyBaseFiles()
107 {
108 $folder = (string) $this->getManifest()->files->attributes()->folder;
109 $source = $this->parent->getPath('source');
110
111 if ($folder)
112 {
113 $source .= '/' . $folder;
114 }
115
116
117 if (!count($this->getManifest()->files->children()))
118 {
119 throw new RuntimeException(
120 JText::sprintf('JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_FILES',
121 JText::_('JLIB_INSTALLER_' . strtoupper($this->route))
122 )
123 );
124 }
125
126
127 if (!self::$eventRegistered)
128 {
129 self::$eventRegistered = true;
130 JEventDispatcher::getInstance()->register('onExtensionAfterInstall', array($this, 'onExtensionAfterInstall'));
131 }
132
133 foreach ($this->getManifest()->files->children() as $child)
134 {
135 $file = $source . '/' . (string) $child;
136
137 if (is_dir($file))
138 {
139
140 $package = array();
141 $package['dir'] = $file;
142 $package['type'] = JInstallerHelper::detectType($file);
143 }
144 else
145 {
146
147 $package = JInstallerHelper::unpack($file);
148 }
149
150 $tmpInstaller = new JInstaller;
151 $installResult = $tmpInstaller->install($package['dir']);
152
153 if (!$installResult)
154 {
155 throw new RuntimeException(
156 JText::sprintf(
157 'JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION',
158 JText::_('JLIB_INSTALLER_' . strtoupper($this->route)),
159 basename($file)
160 )
161 );
162 }
163
164 $this->results[] = array(
165 'name' => (string) $tmpInstaller->manifest->name,
166 'result' => $installResult,
167 );
168 }
169 }
170
171 172 173 174 175 176 177 178
179 protected function createExtensionRoot()
180 {
181 182 183 184
185 }
186
187 188 189 190 191 192 193 194
195 protected function finaliseInstall()
196 {
197
198
199 $update = JTable::getInstance('update');
200 $uid = $update->find(
201 array(
202 'element' => $this->element,
203 'type' => $this->type,
204 )
205 );
206
207 if ($uid)
208 {
209 $update->delete($uid);
210 }
211
212
213 if (!empty($this->installedIds))
214 {
215 $db = $this->db;
216 $query = $db->getQuery(true)
217 ->update('#__extensions')
218 ->set($db->quoteName('package_id') . ' = ' . (int) $this->extension->extension_id)
219 ->where($db->quoteName('extension_id') . ' IN (' . implode(', ', $this->installedIds) . ')');
220
221 try
222 {
223 $db->setQuery($query)->execute();
224 }
225 catch (JDatabaseExceptionExecuting $e)
226 {
227 JLog::add(JText::_('JLIB_INSTALLER_ERROR_PACK_SETTING_PACKAGE_ID'), JLog::WARNING, 'jerror');
228 }
229 }
230
231
232 $manifest = array();
233 $manifest['src'] = $this->parent->getPath('manifest');
234 $manifest['dest'] = JPATH_MANIFESTS . '/packages/' . basename($this->parent->getPath('manifest'));
235
236 if (!$this->parent->copyFiles(array($manifest), true))
237 {
238
239 throw new RuntimeException(
240 JText::sprintf(
241 'JLIB_INSTALLER_ABORT_PACK_INSTALL_COPY_SETUP',
242 JText::_('JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_FILES')
243 )
244 );
245 }
246
247
248 if ($this->manifest_script)
249 {
250
251 if (!file_exists($this->parent->getPath('extension_root')))
252 {
253 if (!JFolder::create($this->parent->getPath('extension_root')))
254 {
255 throw new RuntimeException(
256 JText::sprintf(
257 'JLIB_INSTALLER_ABORT_CREATE_DIRECTORY',
258 JText::_('JLIB_INSTALLER_' . $this->route),
259 $this->parent->getPath('extension_root')
260 )
261 );
262 }
263
264 265 266 267 268
269
270 $this->parent->pushStep(
271 array(
272 'type' => 'folder',
273 'path' => $this->parent->getPath('extension_root'),
274 )
275 );
276 }
277
278 $path['src'] = $this->parent->getPath('source') . '/' . $this->manifest_script;
279 $path['dest'] = $this->parent->getPath('extension_root') . '/' . $this->manifest_script;
280
281 if ($this->parent->isOverwrite() || !file_exists($path['dest']))
282 {
283 if (!$this->parent->copyFiles(array($path)))
284 {
285
286 throw new RuntimeException(JText::_('JLIB_INSTALLER_ABORT_PACKAGE_INSTALL_MANIFEST'));
287 }
288 }
289 }
290 }
291
292 293 294 295 296 297 298 299 300
301 public function getElement($element = null)
302 {
303 if (!$element)
304 {
305
306 $element = (string) $this->getManifest()->packagename;
307
308
309 $element = 'pkg_' . JFilterInput::getInstance()->clean($element, 'cmd');
310 }
311
312 return $element;
313 }
314
315 316 317 318 319 320 321 322 323
324 public function loadLanguage($path)
325 {
326 $this->doLoadLanguage($this->getElement(), $path);
327 }
328
329 330 331 332 333 334 335 336 337 338
339 public function onExtensionAfterInstall(JInstaller $installer, $eid)
340 {
341 if ($eid !== false)
342 {
343 $this->installedIds[] = $eid;
344 }
345 }
346
347 348 349 350 351 352 353
354 protected function parseOptionalTags()
355 {
356 $this->parent->parseLanguages($this->getManifest()->languages);
357 }
358
359 360 361 362 363 364 365 366
367 protected function setupInstallPaths()
368 {
369 $packagepath = (string) $this->getManifest()->packagename;
370
371 if (empty($packagepath))
372 {
373 throw new RuntimeException(
374 JText::sprintf(
375 'JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_PACK',
376 JText::_('JLIB_INSTALLER_' . strtoupper($this->route))
377 )
378 );
379 }
380
381 $this->parent->setPath('extension_root', JPATH_MANIFESTS . '/packages/' . $packagepath);
382 }
383
384 385 386 387 388 389 390 391
392 protected function storeExtension()
393 {
394 if ($this->currentExtensionId)
395 {
396 if (!$this->parent->isOverwrite())
397 {
398
399 throw new RuntimeException(
400 JText::sprintf(
401 'JLIB_INSTALLER_ABORT_ALREADY_EXISTS',
402 JText::_('JLIB_INSTALLER_' . $this->route),
403 $this->name
404 )
405 );
406 }
407
408 $this->extension->load($this->currentExtensionId);
409 $this->extension->name = $this->name;
410 }
411 else
412 {
413 $this->extension->name = $this->name;
414 $this->extension->type = 'package';
415 $this->extension->element = $this->element;
416
417
418 $this->extension->folder = '';
419 $this->extension->enabled = 1;
420 $this->extension->protected = 0;
421 $this->extension->access = 1;
422 $this->extension->client_id = 0;
423
424
425 $this->extension->custom_data = '';
426 $this->extension->system_data = '';
427 $this->extension->params = $this->parent->getParams();
428 }
429
430
431 $this->extension->manifest_cache = $this->parent->generateManifestCache();
432
433 if (!$this->extension->store())
434 {
435
436 throw new RuntimeException(
437 JText::sprintf(
438 'JLIB_INSTALLER_ABORT_PACK_INSTALL_ROLLBACK',
439 $this->extension->getError()
440 )
441 );
442 }
443
444
445
446 $this->parent->pushStep(array('type' => 'extension', 'id' => $this->extension->extension_id));
447 }
448
449 450 451 452 453 454 455 456 457
458 protected function triggerManifestScript($method)
459 {
460 ob_start();
461 ob_implicit_flush(false);
462
463 if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, $method))
464 {
465 switch ($method)
466 {
467
468 case 'preflight':
469 if ($this->parent->manifestClass->$method($this->route, $this) === false)
470 {
471
472 throw new RuntimeException(
473 JText::sprintf(
474 'JLIB_INSTALLER_ABORT_INSTALL_CUSTOM_INSTALL_FAILURE',
475 JText::_('JLIB_INSTALLER_' . $this->route)
476 )
477 );
478 }
479
480 break;
481
482
483 case 'postflight':
484 $this->parent->manifestClass->$method($this->route, $this, $this->results);
485
486 break;
487
488
489 case 'install':
490 case 'uninstall':
491 case 'update':
492 if ($this->parent->manifestClass->$method($this) === false)
493 {
494 if ($method !== 'uninstall')
495 {
496
497 throw new RuntimeException(
498 JText::sprintf(
499 'JLIB_INSTALLER_ABORT_INSTALL_CUSTOM_INSTALL_FAILURE',
500 JText::_('JLIB_INSTALLER_' . $this->route)
501 )
502 );
503 }
504 }
505
506 break;
507 }
508 }
509
510
511 $this->extensionMessage .= ob_get_clean();
512
513
514 if (($method === 'uninstall' || $method === 'postflight') && $this->extensionMessage !== '')
515 {
516 $this->parent->set('extension_message', $this->extensionMessage);
517 }
518
519 return true;
520 }
521
522 523 524 525 526 527 528 529 530
531 public function uninstall($id)
532 {
533 $row = null;
534 $retval = true;
535
536 $row = JTable::getInstance('extension');
537 $row->load($id);
538
539 if ($row->protected)
540 {
541 JLog::add(JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_WARNCOREPACK'), JLog::WARNING, 'jerror');
542
543 return false;
544 }
545
546 547 548 549
550 if ($row->package_id && !$this->parent->isPackageUninstall() && !$this->canUninstallPackageChild($row->package_id))
551 {
552 JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_CANNOT_UNINSTALL_CHILD_OF_PACKAGE', $row->name), JLog::WARNING, 'jerror');
553
554 return false;
555 }
556
557 $manifestFile = JPATH_MANIFESTS . '/packages/' . $row->get('element') . '.xml';
558 $manifest = new JInstallerManifestPackage($manifestFile);
559
560
561 $this->parent->setPath('extension_root', JPATH_MANIFESTS . '/packages/' . $manifest->packagename);
562
563
564 if (!file_exists($manifestFile))
565 {
566
567 JLog::add(JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_MISSINGMANIFEST'), JLog::WARNING, 'jerror');
568
569 return false;
570 }
571
572 $xml = simplexml_load_file($manifestFile);
573
574
575 if (!$xml)
576 {
577 JLog::add(JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_LOAD_MANIFEST'), JLog::WARNING, 'jerror');
578
579 return false;
580 }
581
582
583 if ($xml->getName() !== 'extension')
584 {
585 JLog::add(JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_INVALID_MANIFEST'), JLog::WARNING, 'jerror');
586
587 return false;
588 }
589
590
591 $manifestScript = (string) $manifest->scriptfile;
592
593 if ($manifestScript)
594 {
595 $manifestScriptFile = $this->parent->getPath('extension_root') . '/' . $manifestScript;
596
597
598 $classname = $row->element . 'InstallerScript';
599
600 JLoader::register($classname, $manifestScriptFile);
601
602 if (class_exists($classname))
603 {
604
605 $this->parent->manifestClass = new $classname($this);
606
607
608 $this->set('manifest_script', $manifestScript);
609 }
610 }
611
612 ob_start();
613 ob_implicit_flush(false);
614
615
616 if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'uninstall'))
617 {
618 $this->parent->manifestClass->uninstall($this);
619 }
620
621 $msg = ob_get_contents();
622 ob_end_clean();
623
624 if ($msg != '')
625 {
626 $this->parent->set('extension_message', $msg);
627 }
628
629 $error = false;
630
631 foreach ($manifest->filelist as $extension)
632 {
633 $tmpInstaller = new JInstaller;
634 $tmpInstaller->setPackageUninstall(true);
635
636 $id = $this->_getExtensionId($extension->type, $extension->id, $extension->client, $extension->group);
637 $client = JApplicationHelper::getClientInfo($extension->client, true);
638
639 if ($id)
640 {
641 if (!$tmpInstaller->uninstall($extension->type, $id, $client->id))
642 {
643 $error = true;
644 JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_NOT_PROPER', basename($extension->filename)), JLog::WARNING, 'jerror');
645 }
646 }
647 else
648 {
649 JLog::add(JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_UNKNOWN_EXTENSION'), JLog::WARNING, 'jerror');
650 }
651 }
652
653
654 $this->parent->removeFiles($xml->languages);
655
656
657 if (!$error)
658 {
659 JFile::delete($manifestFile);
660 $folder = $this->parent->getPath('extension_root');
661
662 if (JFolder::exists($folder))
663 {
664 JFolder::delete($folder);
665 }
666
667 $row->delete();
668 }
669 else
670 {
671 JLog::add(JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_MANIFEST_NOT_REMOVED'), JLog::WARNING, 'jerror');
672 }
673
674
675 return $retval;
676 }
677
678 679 680 681 682 683 684 685 686 687 688 689
690 protected function _getExtensionId($type, $id, $client, $group)
691 {
692 $db = $this->parent->getDbo();
693
694 $query = $db->getQuery(true)
695 ->select('extension_id')
696 ->from('#__extensions')
697 ->where('type = ' . $db->quote($type))
698 ->where('element = ' . $db->quote($id));
699
700 switch ($type)
701 {
702 case 'plugin':
703
704 $query->where('folder = ' . $db->quote($group));
705 break;
706
707 case 'library':
708 case 'package':
709 case 'component':
710
711
712 break;
713
714 case 'language':
715 case 'module':
716 case 'template':
717
718 $client = JApplicationHelper::getClientInfo($client, true);
719 $query->where('client_id = ' . (int) $client->id);
720 break;
721 }
722
723 $db->setQuery($query);
724
725
726
727
728 return $db->loadResult();
729 }
730
731 732 733 734 735 736 737
738 public function refreshManifestCache()
739 {
740
741 $manifestPath = JPATH_MANIFESTS . '/packages/' . $this->parent->extension->element . '.xml';
742 $this->parent->manifest = $this->parent->isManifest($manifestPath);
743 $this->parent->setPath('manifest', $manifestPath);
744
745 $manifest_details = JInstaller::parseXMLInstallFile($this->parent->getPath('manifest'));
746 $this->parent->extension->manifest_cache = json_encode($manifest_details);
747 $this->parent->extension->name = $manifest_details['name'];
748
749 try
750 {
751 return $this->parent->extension->store();
752 }
753 catch (RuntimeException $e)
754 {
755 JLog::add(JText::_('JLIB_INSTALLER_ERROR_PACK_REFRESH_MANIFEST_CACHE'), JLog::WARNING, 'jerror');
756
757 return false;
758 }
759 }
760 }
761
762 763 764 765 766 767 768
769 class JInstallerPackage extends JInstallerAdapterPackage
770 {
771 }
772