PageRenderTime 54ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/libraries/joomla/factory.php

https://bitbucket.org/organicdevelopment/joomla-2.5
PHP | 922 lines | 417 code | 126 blank | 379 comment | 47 complexity | 5b47e23667e36812b06e3254221522f0 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-2.0, MIT, BSD-3-Clause, LGPL-2.1
  1. <?php
  2. /**
  3. * @package Joomla.Platform
  4. *
  5. * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
  6. * @license GNU General Public License version 2 or later; see LICENSE
  7. */
  8. defined('JPATH_PLATFORM') or die;
  9. /**
  10. * Joomla Platform Factory class
  11. *
  12. * @package Joomla.Platform
  13. * @since 11.1
  14. */
  15. abstract class JFactory
  16. {
  17. /**
  18. * @var JApplication
  19. * @since 11.1
  20. */
  21. public static $application = null;
  22. /**
  23. * @var JCache
  24. * @since 11.1
  25. */
  26. public static $cache = null;
  27. /**
  28. * @var JConfig
  29. * @since 11.1
  30. */
  31. public static $config = null;
  32. /**
  33. * @var array
  34. * @since 11.3
  35. */
  36. public static $dates = array();
  37. /**
  38. * @var JSession
  39. * @since 11.1
  40. */
  41. public static $session = null;
  42. /**
  43. * @var JLanguage
  44. * @since 11.1
  45. */
  46. public static $language = null;
  47. /**
  48. * @var JDocument
  49. * @since 11.1
  50. */
  51. public static $document = null;
  52. /**
  53. * @var JAccess
  54. * @since 11.1
  55. */
  56. public static $acl = null;
  57. /**
  58. * @var JDatabase
  59. * @since 11.1
  60. */
  61. public static $database = null;
  62. /**
  63. * @var JMail
  64. * @since 11.1
  65. */
  66. public static $mailer = null;
  67. /**
  68. * Get a application object.
  69. *
  70. * Returns the global {@link JApplication} object, only creating it if it doesn't already exist.
  71. *
  72. * @param mixed $id A client identifier or name.
  73. * @param array $config An optional associative array of configuration settings.
  74. * @param string $prefix Application prefix
  75. *
  76. * @return JApplication object
  77. *
  78. * @see JApplication
  79. * @since 11.1
  80. */
  81. public static function getApplication($id = null, $config = array(), $prefix = 'J')
  82. {
  83. if (!self::$application)
  84. {
  85. if (!$id)
  86. {
  87. JError::raiseError(500, 'Application Instantiation Error');
  88. }
  89. self::$application = JApplication::getInstance($id, $config, $prefix);
  90. }
  91. return self::$application;
  92. }
  93. /**
  94. * Get a configuration object
  95. *
  96. * Returns the global {@link JRegistry} object, only creating it if it doesn't already exist.
  97. *
  98. * @param string $file The path to the configuration file
  99. * @param string $type The type of the configuration file
  100. *
  101. * @return JRegistry
  102. *
  103. * @see JRegistry
  104. * @since 11.1
  105. */
  106. public static function getConfig($file = null, $type = 'PHP')
  107. {
  108. if (!self::$config)
  109. {
  110. if ($file === null)
  111. {
  112. $file = JPATH_PLATFORM . '/config.php';
  113. }
  114. self::$config = self::createConfig($file, $type);
  115. }
  116. return self::$config;
  117. }
  118. /**
  119. * Get a session object.
  120. *
  121. * Returns the global {@link JSession} object, only creating it if it doesn't already exist.
  122. *
  123. * @param array $options An array containing session options
  124. *
  125. * @return JSession object
  126. *
  127. * @see JSession
  128. * @since 11.1
  129. */
  130. public static function getSession($options = array())
  131. {
  132. if (!self::$session)
  133. {
  134. self::$session = self::createSession($options);
  135. }
  136. return self::$session;
  137. }
  138. /**
  139. * Get a language object.
  140. *
  141. * Returns the global {@link JLanguage} object, only creating it if it doesn't already exist.
  142. *
  143. * @return JLanguage object
  144. *
  145. * @see JLanguage
  146. * @since 11.1
  147. */
  148. public static function getLanguage()
  149. {
  150. if (!self::$language)
  151. {
  152. self::$language = self::createLanguage();
  153. }
  154. return self::$language;
  155. }
  156. /**
  157. * Get a document object.
  158. *
  159. * Returns the global {@link JDocument} object, only creating it if it doesn't already exist.
  160. *
  161. * @return JDocument object
  162. *
  163. * @see JDocument
  164. * @since 11.1
  165. */
  166. public static function getDocument()
  167. {
  168. if (!self::$document)
  169. {
  170. self::$document = self::createDocument();
  171. }
  172. return self::$document;
  173. }
  174. /**
  175. * Get an user object.
  176. *
  177. * Returns the global {@link JUser} object, only creating it if it doesn't already exist.
  178. *
  179. * @param integer $id The user to load - Can be an integer or string - If string, it is converted to ID automatically.
  180. *
  181. * @return JUser object
  182. *
  183. * @see JUser
  184. * @since 11.1
  185. */
  186. public static function getUser($id = null)
  187. {
  188. if (is_null($id))
  189. {
  190. $instance = self::getSession()->get('user');
  191. if (!($instance instanceof JUser))
  192. {
  193. $instance = JUser::getInstance();
  194. }
  195. }
  196. else
  197. {
  198. $current = self::getSession()->get('user');
  199. if ($current->id != $id)
  200. {
  201. $instance = JUser::getInstance($id);
  202. }
  203. else
  204. {
  205. $instance = self::getSession()->get('user');
  206. }
  207. }
  208. return $instance;
  209. }
  210. /**
  211. * Get a cache object
  212. *
  213. * Returns the global {@link JCache} object
  214. *
  215. * @param string $group The cache group name
  216. * @param string $handler The handler to use
  217. * @param string $storage The storage method
  218. *
  219. * @return JCache object
  220. *
  221. * @see JCache
  222. */
  223. public static function getCache($group = '', $handler = 'callback', $storage = null)
  224. {
  225. $hash = md5($group . $handler . $storage);
  226. if (isset(self::$cache[$hash]))
  227. {
  228. return self::$cache[$hash];
  229. }
  230. $handler = ($handler == 'function') ? 'callback' : $handler;
  231. $options = array('defaultgroup' => $group);
  232. if (isset($storage))
  233. {
  234. $options['storage'] = $storage;
  235. }
  236. $cache = JCache::getInstance($handler, $options);
  237. self::$cache[$hash] = $cache;
  238. return self::$cache[$hash];
  239. }
  240. /**
  241. * Get an authorization object
  242. *
  243. * Returns the global {@link JACL} object, only creating it
  244. * if it doesn't already exist.
  245. *
  246. * @return JACL object
  247. */
  248. public static function getACL()
  249. {
  250. if (!self::$acl)
  251. {
  252. self::$acl = new JAccess;
  253. }
  254. return self::$acl;
  255. }
  256. /**
  257. * Get a database object.
  258. *
  259. * Returns the global {@link JDatabase} object, only creating it if it doesn't already exist.
  260. *
  261. * @return JDatabase object
  262. *
  263. * @see JDatabase
  264. * @since 11.1
  265. */
  266. public static function getDbo()
  267. {
  268. if (!self::$database)
  269. {
  270. //get the debug configuration setting
  271. $conf = self::getConfig();
  272. $debug = $conf->get('debug');
  273. self::$database = self::createDbo();
  274. self::$database->setDebug($debug);
  275. }
  276. return self::$database;
  277. }
  278. /**
  279. * Get a mailer object.
  280. *
  281. * Returns the global {@link JMail} object, only creating it if it doesn't already exist.
  282. *
  283. * @return JMail object
  284. *
  285. * @see JMail
  286. * @since 11.1
  287. */
  288. public static function getMailer()
  289. {
  290. if (!self::$mailer)
  291. {
  292. self::$mailer = self::createMailer();
  293. }
  294. $copy = clone self::$mailer;
  295. return $copy;
  296. }
  297. /**
  298. * Get a parsed XML Feed Source
  299. *
  300. * @param string $url Url for feed source.
  301. * @param integer $cache_time Time to cache feed for (using internal cache mechanism).
  302. *
  303. * @return mixed SimplePie parsed object on success, false on failure.
  304. *
  305. * @since 11.1
  306. */
  307. public static function getFeedParser($url, $cache_time = 0)
  308. {
  309. jimport('simplepie.simplepie');
  310. $cache = self::getCache('feed_parser', 'callback');
  311. if ($cache_time > 0)
  312. {
  313. $cache->setLifeTime($cache_time);
  314. }
  315. $simplepie = new SimplePie(null, null, 0);
  316. $simplepie->enable_cache(false);
  317. $simplepie->set_feed_url($url);
  318. $simplepie->force_feed(true);
  319. $contents = $cache->get(array($simplepie, 'init'), null, false, false);
  320. if ($contents)
  321. {
  322. return $simplepie;
  323. }
  324. else
  325. {
  326. JError::raiseWarning('SOME_ERROR_CODE', JText::_('JLIB_UTIL_ERROR_LOADING_FEED_DATA'));
  327. }
  328. return false;
  329. }
  330. /**
  331. * Get an XML document
  332. *
  333. * @param string $type The type of XML parser needed 'DOM', 'RSS' or 'Simple'
  334. * @param array $options ['rssUrl'] the rss url to parse when using "RSS", ['cache_time'] with '
  335. * RSS' - feed cache time. If not defined defaults to 3600 sec
  336. *
  337. * @return object Parsed XML document object
  338. *
  339. * @deprecated 12.1 Use JXMLElement instead.
  340. * @see JXMLElement
  341. */
  342. public static function getXMLParser($type = '', $options = array())
  343. {
  344. // Deprecation warning.
  345. JLog::add('JFactory::getXMLParser() is deprecated.', JLog::WARNING, 'deprecated');
  346. $doc = null;
  347. switch (strtolower($type))
  348. {
  349. case 'rss':
  350. case 'atom':
  351. $cache_time = isset($options['cache_time']) ? $options['cache_time'] : 0;
  352. $doc = self::getFeedParser($options['rssUrl'], $cache_time);
  353. break;
  354. case 'simple':
  355. // JError::raiseWarning('SOME_ERROR_CODE', 'JSimpleXML is deprecated. Use self::getXML instead');
  356. jimport('joomla.utilities.simplexml');
  357. $doc = new JSimpleXML;
  358. break;
  359. case 'dom':
  360. JError::raiseWarning('SOME_ERROR_CODE', JText::_('JLIB_UTIL_ERROR_DOMIT'));
  361. $doc = null;
  362. break;
  363. default:
  364. $doc = null;
  365. }
  366. return $doc;
  367. }
  368. /**
  369. * Reads a XML file.
  370. *
  371. * @param string $data Full path and file name.
  372. * @param boolean $isFile true to load a file or false to load a string.
  373. *
  374. * @return mixed JXMLElement on success or false on error.
  375. *
  376. * @see JXMLElement
  377. * @since 11.1
  378. * @todo This may go in a separate class - error reporting may be improved.
  379. */
  380. public static function getXML($data, $isFile = true)
  381. {
  382. jimport('joomla.utilities.xmlelement');
  383. // Disable libxml errors and allow to fetch error information as needed
  384. libxml_use_internal_errors(true);
  385. if ($isFile)
  386. {
  387. // Try to load the XML file
  388. $xml = simplexml_load_file($data, 'JXMLElement');
  389. }
  390. else
  391. {
  392. // Try to load the XML string
  393. $xml = simplexml_load_string($data, 'JXMLElement');
  394. }
  395. if (empty($xml))
  396. {
  397. // There was an error
  398. JError::raiseWarning(100, JText::_('JLIB_UTIL_ERROR_XML_LOAD'));
  399. if ($isFile)
  400. {
  401. JError::raiseWarning(100, $data);
  402. }
  403. foreach (libxml_get_errors() as $error)
  404. {
  405. JError::raiseWarning(100, 'XML: ' . $error->message);
  406. }
  407. }
  408. return $xml;
  409. }
  410. /**
  411. * Get an editor object.
  412. *
  413. * @param string $editor The editor to load, depends on the editor plugins that are installed
  414. *
  415. * @return JEditor object
  416. *
  417. * @since 11.1
  418. */
  419. public static function getEditor($editor = null)
  420. {
  421. jimport('joomla.html.editor');
  422. //get the editor configuration setting
  423. if (is_null($editor))
  424. {
  425. $conf = self::getConfig();
  426. $editor = $conf->get('editor');
  427. }
  428. return JEditor::getInstance($editor);
  429. }
  430. /**
  431. * Return a reference to the {@link JURI} object
  432. *
  433. * @param string $uri Uri name.
  434. *
  435. * @return JURI object
  436. *
  437. * @see JURI
  438. * @since 11.1
  439. */
  440. public static function getURI($uri = 'SERVER')
  441. {
  442. jimport('joomla.environment.uri');
  443. return JURI::getInstance($uri);
  444. }
  445. /**
  446. * Return the {@link JDate} object
  447. *
  448. * @param mixed $time The initial time for the JDate object
  449. * @param mixed $tzOffset The timezone offset.
  450. *
  451. * @return JDate object
  452. *
  453. * @see JDate
  454. * @since 11.1
  455. */
  456. public static function getDate($time = 'now', $tzOffset = null)
  457. {
  458. jimport('joomla.utilities.date');
  459. static $classname;
  460. static $mainLocale;
  461. $language = self::getLanguage();
  462. $locale = $language->getTag();
  463. if (!isset($classname) || $locale != $mainLocale)
  464. {
  465. //Store the locale for future reference
  466. $mainLocale = $locale;
  467. if ($mainLocale !== false)
  468. {
  469. $classname = str_replace('-', '_', $mainLocale) . 'Date';
  470. if (!class_exists($classname))
  471. {
  472. //The class does not exist, default to JDate
  473. $classname = 'JDate';
  474. }
  475. }
  476. else
  477. {
  478. //No tag, so default to JDate
  479. $classname = 'JDate';
  480. }
  481. }
  482. $key = $time . '-' . ($tzOffset instanceof DateTimeZone ? $tzOffset->getName() : (string) $tzOffset);
  483. if (!isset(self::$dates[$classname][$key]))
  484. {
  485. self::$dates[$classname][$key] = new $classname($time, $tzOffset);
  486. }
  487. $date = clone self::$dates[$classname][$key];
  488. return $date;
  489. }
  490. /**
  491. * Create a configuration object
  492. *
  493. * @param string $file The path to the configuration file.
  494. * @param string $type The type of the configuration file.
  495. * @param string $namespace The namespace of the configuration file.
  496. *
  497. * @return JRegistry
  498. *
  499. * @see JRegistry
  500. * @since 11.1
  501. * @deprecated 12.3
  502. */
  503. protected static function _createConfig($file, $type = 'PHP', $namespace = '')
  504. {
  505. JLog::add(__METHOD__ . '() is deprecated.', JLog::WARNING, 'deprecated');
  506. return self::createConfig($file, $type, $namespace);
  507. }
  508. /**
  509. * Create a configuration object
  510. *
  511. * @param string $file The path to the configuration file.
  512. * @param string $type The type of the configuration file.
  513. * @param string $namespace The namespace of the configuration file.
  514. *
  515. * @return JRegistry
  516. *
  517. * @see JRegistry
  518. * @since 11.1
  519. */
  520. protected static function createConfig($file, $type = 'PHP', $namespace = '')
  521. {
  522. if (is_file($file))
  523. {
  524. include_once $file;
  525. }
  526. // Create the registry with a default namespace of config
  527. $registry = new JRegistry;
  528. // Sanitize the namespace.
  529. $namespace = ucfirst((string) preg_replace('/[^A-Z_]/i', '', $namespace));
  530. // Build the config name.
  531. $name = 'JConfig' . $namespace;
  532. // Handle the PHP configuration type.
  533. if ($type == 'PHP' && class_exists($name))
  534. {
  535. // Create the JConfig object
  536. $config = new $name;
  537. // Load the configuration values into the registry
  538. $registry->loadObject($config);
  539. }
  540. return $registry;
  541. }
  542. /**
  543. * Create a session object
  544. *
  545. * @param array $options An array containing session options
  546. *
  547. * @return JSession object
  548. *
  549. * @since 11.1
  550. * @deprecated 12.3
  551. */
  552. protected static function _createSession($options = array())
  553. {
  554. JLog::add(__METHOD__ . '() is deprecated.', JLog::WARNING, 'deprecated');
  555. return self::createSession($options);
  556. }
  557. /**
  558. * Create a session object
  559. *
  560. * @param array $options An array containing session options
  561. *
  562. * @return JSession object
  563. *
  564. * @since 11.1
  565. */
  566. protected static function createSession($options = array())
  567. {
  568. // Get the editor configuration setting
  569. $conf = self::getConfig();
  570. $handler = $conf->get('session_handler', 'none');
  571. // Config time is in minutes
  572. $options['expire'] = ($conf->get('lifetime')) ? $conf->get('lifetime') * 60 : 900;
  573. $session = JSession::getInstance($handler, $options);
  574. if ($session->getState() == 'expired')
  575. {
  576. $session->restart();
  577. }
  578. return $session;
  579. }
  580. /**
  581. * Create an database object
  582. *
  583. * @return JDatabase object
  584. *
  585. * @see JDatabase
  586. * @since 11.1
  587. * @deprecated 12.3
  588. */
  589. protected static function _createDbo()
  590. {
  591. JLog::add(__METHOD__ . '() is deprecated.', JLog::WARNING, 'deprecated');
  592. return self::createDbo();
  593. }
  594. /**
  595. * Create an database object
  596. *
  597. * @return JDatabase object
  598. *
  599. * @see JDatabase
  600. * @since 11.1
  601. */
  602. protected static function createDbo()
  603. {
  604. jimport('joomla.database.table');
  605. $conf = self::getConfig();
  606. $host = $conf->get('host');
  607. $user = $conf->get('user');
  608. $password = $conf->get('password');
  609. $database = $conf->get('db');
  610. $prefix = $conf->get('dbprefix');
  611. $driver = $conf->get('dbtype');
  612. $debug = $conf->get('debug');
  613. $options = array('driver' => $driver, 'host' => $host, 'user' => $user, 'password' => $password, 'database' => $database, 'prefix' => $prefix);
  614. $db = JDatabase::getInstance($options);
  615. if ($db instanceof Exception)
  616. {
  617. if (!headers_sent())
  618. {
  619. header('HTTP/1.1 500 Internal Server Error');
  620. }
  621. jexit('Database Error: ' . (string) $db);
  622. }
  623. if ($db->getErrorNum() > 0)
  624. {
  625. die(sprintf('Database connection error (%d): %s', $db->getErrorNum(), $db->getErrorMsg()));
  626. }
  627. $db->setDebug($debug);
  628. return $db;
  629. }
  630. /**
  631. * Create a mailer object
  632. *
  633. * @return JMail object
  634. *
  635. * @see JMail
  636. * @since 11.1
  637. * @deprecated 12.3
  638. */
  639. protected static function _createMailer()
  640. {
  641. JLog::add(__METHOD__ . '() is deprecated.', JLog::WARNING, 'deprecated');
  642. return self::createMailer();
  643. }
  644. /**
  645. * Create a mailer object
  646. *
  647. * @return JMail object
  648. *
  649. * @see JMail
  650. * @since 11.1
  651. */
  652. protected static function createMailer()
  653. {
  654. $conf = self::getConfig();
  655. $smtpauth = ($conf->get('smtpauth') == 0) ? null : 1;
  656. $smtpuser = $conf->get('smtpuser');
  657. $smtppass = $conf->get('smtppass');
  658. $smtphost = $conf->get('smtphost');
  659. $smtpsecure = $conf->get('smtpsecure');
  660. $smtpport = $conf->get('smtpport');
  661. $mailfrom = $conf->get('mailfrom');
  662. $fromname = $conf->get('fromname');
  663. $mailer = $conf->get('mailer');
  664. // Create a JMail object
  665. $mail = JMail::getInstance();
  666. // Set default sender without Reply-to
  667. $mail->SetFrom(JMailHelper::cleanLine($mailfrom), JMailHelper::cleanLine($fromname), 0);
  668. // Default mailer is to use PHP's mail function
  669. switch ($mailer)
  670. {
  671. case 'smtp':
  672. $mail->useSMTP($smtpauth, $smtphost, $smtpuser, $smtppass, $smtpsecure, $smtpport);
  673. break;
  674. case 'sendmail':
  675. $mail->IsSendmail();
  676. break;
  677. default:
  678. $mail->IsMail();
  679. break;
  680. }
  681. return $mail;
  682. }
  683. /**
  684. * Create a language object
  685. *
  686. * @return JLanguage object
  687. *
  688. * @see JLanguage
  689. * @since 11.1
  690. * @deprecated 12.3
  691. */
  692. protected static function _createLanguage()
  693. {
  694. JLog::add(__METHOD__ . ' is deprecated.', JLog::WARNING, 'deprecated');
  695. return self::createLanguage();
  696. }
  697. /**
  698. * Create a language object
  699. *
  700. * @return JLanguage object
  701. *
  702. * @see JLanguage
  703. * @since 11.1
  704. */
  705. protected static function createLanguage()
  706. {
  707. $conf = self::getConfig();
  708. $locale = $conf->get('language');
  709. $debug = $conf->get('debug_lang');
  710. $lang = JLanguage::getInstance($locale, $debug);
  711. return $lang;
  712. }
  713. /**
  714. * Create a document object
  715. *
  716. * @return JDocument object
  717. *
  718. * @see JDocument
  719. * @since 11.1
  720. * @deprecated 12.3
  721. */
  722. protected static function _createDocument()
  723. {
  724. JLog::add(__METHOD__ . ' is deprecated.', JLog::WARNING, 'deprecated');
  725. return self::createDocument();
  726. }
  727. /**
  728. * Create a document object
  729. *
  730. * @return JDocument object
  731. *
  732. * @see JDocument
  733. * @since 11.1
  734. */
  735. protected static function createDocument()
  736. {
  737. $lang = self::getLanguage();
  738. // Keep backwards compatibility with Joomla! 1.0
  739. // @deprecated 12.1 This will be removed in the next version
  740. $raw = JRequest::getBool('no_html');
  741. $type = JRequest::getWord('format', $raw ? 'raw' : 'html');
  742. $attributes = array('charset' => 'utf-8', 'lineend' => 'unix', 'tab' => ' ', 'language' => $lang->getTag(),
  743. 'direction' => $lang->isRTL() ? 'rtl' : 'ltr');
  744. return JDocument::getInstance($type, $attributes);
  745. }
  746. /**
  747. * Creates a new stream object with appropriate prefix
  748. *
  749. * @param boolean $use_prefix Prefix the connections for writing
  750. * @param boolean $use_network Use network if available for writing; use false to disable (e.g. FTP, SCP)
  751. * @param string $ua UA User agent to use
  752. * @param boolean $uamask User agent masking (prefix Mozilla)
  753. *
  754. * @return JStream
  755. *
  756. * @see JStream
  757. * @since 11.1
  758. */
  759. public static function getStream($use_prefix = true, $use_network = true, $ua = null, $uamask = false)
  760. {
  761. jimport('joomla.filesystem.stream');
  762. // Setup the context; Joomla! UA and overwrite
  763. $context = array();
  764. $version = new JVersion;
  765. // set the UA for HTTP and overwrite for FTP
  766. $context['http']['user_agent'] = $version->getUserAgent($ua, $uamask);
  767. $context['ftp']['overwrite'] = true;
  768. if ($use_prefix)
  769. {
  770. $FTPOptions = JClientHelper::getCredentials('ftp');
  771. $SCPOptions = JClientHelper::getCredentials('scp');
  772. if ($FTPOptions['enabled'] == 1 && $use_network)
  773. {
  774. $prefix = 'ftp://' . $FTPOptions['user'] . ':' . $FTPOptions['pass'] . '@' . $FTPOptions['host'];
  775. $prefix .= $FTPOptions['port'] ? ':' . $FTPOptions['port'] : '';
  776. $prefix .= $FTPOptions['root'];
  777. }
  778. elseif ($SCPOptions['enabled'] == 1 && $use_network)
  779. {
  780. $prefix = 'ssh2.sftp://' . $SCPOptions['user'] . ':' . $SCPOptions['pass'] . '@' . $SCPOptions['host'];
  781. $prefix .= $SCPOptions['port'] ? ':' . $SCPOptions['port'] : '';
  782. $prefix .= $SCPOptions['root'];
  783. }
  784. else
  785. {
  786. $prefix = JPATH_ROOT . '/';
  787. }
  788. $retval = new JStream($prefix, JPATH_ROOT, $context);
  789. }
  790. else
  791. {
  792. $retval = new JStream('', '', $context);
  793. }
  794. return $retval;
  795. }
  796. }