示例#1
0
 function setUp()
 {
     $this->tearDown();
     $s = DIRECTORY_SEPARATOR;
     $tables = self::$TABLES;
     foreach ($tables as $t) {
         Dataface_Table::setBasePath($t, dirname(__FILE__));
         self::q(file_get_contents(Dataface_Table::getBasePath($t) . $s . 'tables' . $s . basename($t) . $s . 'create.sql'));
         self::q(file_get_contents(Dataface_Table::getBasePath($t) . $s . 'tables' . $s . basename($t) . $s . 'init.sql'));
     }
 }
示例#2
0
 /**
  * Loads configuration information from an INI file.
  * @param $type The type of configuration information to load: e.g., actions, relationships, valuelists, fields, etc..
  * @param $tablename The name of the table for which to load the configuration information.
  * @return Associative array of configuration options in the same form as they would be returned by parse_ini_file().
  */
 function &loadConfigFromINI($type = null, $tablename = '__global__')
 {
     if (!isset($tablename)) {
         $tablename = '__global__';
     }
     $app =& Dataface_Application::getInstance();
     if ($type == 'lang') {
         if (isset($this->config[$type][$app->_conf['lang']][$tablename])) {
             return $this->config[$type][$app->_conf['lang']][$tablename];
         }
     } else {
         if (isset($this->config[$type][$tablename])) {
             return $this->config[$type][$tablename];
         }
     }
     $app =& Dataface_Application::getInstance();
     $paths = array();
     $lpaths = array();
     if ($type === 'lang') {
         if ($tablename !== '__global__') {
             if (!class_exists('Dataface_Table')) {
                 import('Dataface/Table.php');
             }
             $lpaths[] = Dataface_Table::getBasePath($tablename) . '/tables/' . basename($tablename) . '/lang/' . basename($app->_conf['lang']) . '.ini';
         } else {
             $paths[] = DATAFACE_PATH . '/lang/' . basename($app->_conf['lang']) . '.ini';
             $lpaths[] = DATAFACE_SITE_PATH . '/lang/' . basename($app->_conf['lang']) . '.ini';
         }
     } else {
         if ($tablename !== '__global__') {
             //$paths = array(DATAFACE_SITE_PATH.'/tables/'.$tablename.'/'.$type.'.ini');
             // Valuelists handle their own cascading because it involves loading
             // the valuelist each time... and there may be opportunities to
             // share between tables
             if ($type != 'valuelists') {
                 $paths[] = DATAFACE_PATH . '/' . basename($type) . '.ini';
             }
             if ($type != 'valuelists') {
                 $lpaths[] = DATAFACE_SITE_PATH . '/' . basename($type) . '.ini';
             }
             $lpaths[] = Dataface_Table::getBasePath($tablename) . '/tables/' . basename($tablename) . '/' . basename($type) . '.ini';
         } else {
             $paths[] = DATAFACE_PATH . '/' . basename($type) . '.ini';
             $lpaths[] = DATAFACE_SITE_PATH . '/' . basename($type) . '.ini';
         }
     }
     // Add the ability to override settings in a module.
     // Added Feb. 28, 2007 by Steve Hannah for version 0.6.14
     if (isset($app->_conf['_modules']) and count($app->_conf['_modules']) > 0) {
         foreach ($app->_conf['_modules'] as $classname => $path) {
             $modpath = explode('_', $classname);
             array_shift($modpath);
             $modname = implode('_', $modpath);
             if ($type == 'lang') {
                 $paths[] = DATAFACE_SITE_PATH . '/modules/' . basename($modname) . '/lang/' . basename($app->_conf['lang']) . '.ini';
                 $paths[] = DATAFACE_PATH . '/modules/' . basename($modname) . '/lang/' . basename($app->_conf['lang']) . '.ini';
             } else {
                 $paths[] = DATAFACE_SITE_PATH . '/modules/' . basename($modname) . '/' . basename($type) . '.ini';
                 $paths[] = DATAFACE_PATH . '/modules/' . basename($modname) . '/' . basename($type) . '.ini';
             }
         }
     }
     // Add the ability to override settings in the database.
     // Added Feb. 27, 2007 by Steve Hannah for version 0.6.14
     if (@$app->_conf['enable_db_config'] and $type != 'permissions') {
         if ($type == 'lang') {
             if (isset($tablename)) {
                 $lpaths[] = 'db:tables/' . basename($tablename) . '/lang/' . basename($app->_conf['lang']);
             } else {
                 $paths[] = 'db:lang/' . basename($app->_conf['lang']) . '.ini';
             }
         } else {
             if (isset($tablename)) {
                 $paths[] = 'db:' . basename($type) . '.ini';
                 $lpaths[] = 'db:tables/' . basename($tablename) . '/' . basename($type) . '.ini';
             } else {
                 $paths[] = 'db:' . basename($type) . '.ini';
             }
         }
     }
     if (!$tablename) {
         $tablename = '__global__';
     }
     $paths = array_merge($paths, $lpaths);
     //print_r($paths);
     //print_r($lpaths);
     if (!isset($this->config[$type][$tablename])) {
         $this->config[$type][$tablename] = array();
     }
     //import('Config.php');
     foreach ($paths as $path) {
         if (!isset($this->iniLoaded[$path])) {
             $this->iniLoaded[$path] = true;
             if (is_readable($path) || strstr($path, 'db:') == $path) {
                 $config = $this->parse_ini_file($path, true);
                 if (isset($config['charset']) and function_exists('iconv')) {
                     I18Nv2::recursiveIconv($config, $config['charset'], 'UTF-8');
                 }
                 if (isset($config['__extends__'])) {
                     $config = array_merge_recursive_unique($this->loadConfigFromINI($type, $config['__extends__']), $config);
                 }
                 $this->rawConfig[$path] =& $config;
             } else {
                 $config = array();
                 $this->rawConfig[$path] =& $config;
             }
         } else {
             //echo "getting $path from raw config.";
             //echo "$path already loaded:".implode(',', array_keys($this->iniLoaded));
             $config =& $this->rawConfig[$path];
         }
         //echo "Conf for x".$path."x: ";
         if (!$config) {
             $config = array();
         }
         foreach (array_keys($config) as $entry) {
             if ($type == 'lang') {
                 $this->config[$type][$app->_conf['lang']][$tablename][$entry] =& $config[$entry];
             } else {
                 $sep = null;
                 if (strpos($entry, '>') !== false) {
                     $sep = '>';
                 }
                 if (strpos($entry, ' extends ') !== false) {
                     $sep = ' extends ';
                 }
                 if ($sep and is_array($config[$entry])) {
                     list($newentry, $entryParents) = explode($sep, $entry);
                     $entryParents = array_map('trim', explode(',', $entryParents));
                     $newentry = trim($newentry);
                     $cout = array();
                     foreach ($entryParents as $entryParent) {
                         if (!isset($this->config[$type][$tablename][$entryParent])) {
                             throw new Exception("Illegal extends.  Parent not found: " . $entryParent . " from rule: " . $entry . " in " . $path);
                         }
                         $pconf =& $this->config[$type][$tablename][$entryParent];
                         if (!is_array($pconf)) {
                             throw new Exception("Illegal extends.  Parent is not a section. It is a scalar: " . $entryParent . " from rule: " . $entry . " in " . $path);
                         }
                         foreach ($pconf as $pkey => $pval) {
                             $cout[$pkey] = $pval;
                         }
                         unset($pconf);
                     }
                     $centry =& $config[$entry];
                     foreach ($centry as $ckey => $cval) {
                         $cout[$ckey] = $cval;
                     }
                     unset($centry);
                     unset($this->config[$type][$tablename][$entry]);
                     unset($this->config[$type][$tablename][$newentry]);
                     $this->config[$type][$tablename][$newentry] =& $cout;
                     unset($cout);
                     //$this->config[$type][$tablename][trim($newentry)] = array_merge($this->config[$type][$tablename][trim($entryParent)],$config[$entry]);
                 } else {
                     $this->config[$type][$tablename][$entry] =& $config[$entry];
                 }
             }
         }
         unset($config);
     }
     // New in 2.1.  We load user config if it is available to override the
     // built-in config
     $user_config = $this->userConfig;
     $upaths = array();
     if ($type == 'lang') {
         $upaths[] = 'lang/' . $app->_conf['lang'] . '.ini';
         $upaths[] = 'tables/' . $tablename . '/lang/' . $app->_conf['lang'] . '.ini';
     } else {
         $upaths[] = $type . '.ini';
         $upaths[] = 'tables/' . $tablename . '/' . $type . '.ini';
     }
     foreach ($upaths as $p) {
         if (isset($user_config->{$p})) {
             if ($type == 'lang') {
                 $this->config[$type][$app->_conf['lang']][$tablename] = array_merge_recursive_unique($this->config[$type][$app->_conf['lang']][$tablename], $this->objectToArray($user_config->{$p}));
             } else {
                 $this->config[$type][$tablename] = array_merge_recursive_unique($this->config[$type][$tablename], $this->objectToArray($user_config->{$p}));
             }
         }
     }
     if ($type == 'lang') {
         return $this->config[$type][$app->_conf['lang']][$tablename];
     } else {
         return $this->config[$type][$tablename];
     }
 }
示例#3
0
 /**
  * @brief Handle a request.  This method is the starting point for all Dataface application requests.
  * It will delegate the request to the appropriate handler.
  * The order of delegation is as follows:
  *  -# Uses the ActionTool to check permissions for the action.  If permissions are not granted,
  *		dispatch the error handler.  If permissions are granted then we continue down the delegation
  *		chain.
  *  -# If the current table's delegate class defines a handleRequest() method, then call that.
  *	-# If the current table's delegate class does not have a handleRequest() method or that method
  *		returns a PEAR_Error object with code E_DATAFACE_REQUEST_NOT_HANDLED, then check for a handler
  *		bearing the name of the action in one of the actions directories.  Check the directories 
  *		in the following order:
  *		a. <site url>/tables/<table name>/actions
  *		b. <site url>/actions
  *		b. <dataface url>/actions
  *
  * @param boolean $disableCache Whether to disable the cache or not for this request.
  *
  * @see ApplicationDelegateClass::beforeHandleRequest()
  */
 function handleRequest($disableCache = false)
 {
     if (!$disableCache and @$_GET['-action'] != 'getBlob' and isset($this->_conf['_output_cache']) and @$this->_conf['_output_cache']['enabled'] and count($_POST) == 0) {
         import('Dataface/OutputCache.php');
         $oc = new Dataface_OutputCache($this->_conf['_output_cache']);
         $oc->ob_start();
     }
     import('Dataface/ActionTool.php');
     import('Dataface/PermissionsTool.php');
     import('Dataface/Table.php');
     if (isset($this->_conf['_modules']) and count($this->_conf['_modules']) > 0) {
         $mt = Dataface_ModuleTool::getInstance();
         foreach ($this->_conf['_modules'] as $modname => $modpath) {
             $mt->loadModule($modname);
         }
     }
     $this->fireEvent('beforeHandleRequest');
     $applicationDelegate = $this->getDelegate();
     if (isset($applicationDelegate) and method_exists($applicationDelegate, 'beforeHandleRequest')) {
         // Do whatever we need to do before the request is handled.
         $applicationDelegate->beforeHandleRequest();
     }
     // Set up security filters
     $query =& $this->getQuery();
     $table = Dataface_Table::loadTable($query['-table']);
     //$table->setSecurityFilter();
     /*
      * Set up some preferences for the display of the application.
      * These can be overridden by the getPreferences() method in the
      * application delegate class.
      */
     if (isset($this->_conf['_prefs']) and is_array($this->_conf['_prefs'])) {
         $this->prefs = array_merge($this->prefs, $this->_conf['_prefs']);
     }
     if (@$this->_conf['hide_nav_menu']) {
         $this->prefs['show_tables_menu'] = 0;
     }
     if (@$this->_conf['hide_view_tabs']) {
         $this->prefs['show_table_tabs'] = 0;
     }
     if (@$this->_conf['hide_result_controller']) {
         $this->prefs['show_result_controller'] = 0;
     }
     if (@$this->_conf['hide_table_result_stats']) {
         $this->prefs['show_result_stats'] = 0;
     }
     if (@$this->_conf['hide_search']) {
         $this->prefs['show_search'] = 0;
     }
     if (!isset($this->prefs['disable_ajax_record_details'])) {
         $this->prefs['disable_ajax_record_details'] = 1;
     }
     if ($query['-action'] == 'login_prompt') {
         $this->prefs['no_history'] = 1;
     }
     if (isset($applicationDelegate) and method_exists($applicationDelegate, 'getPreferences')) {
         $this->prefs = array_merge($this->prefs, $applicationDelegate->getPreferences());
     }
     $this->prefs = array_map('intval', $this->prefs);
     // Check to make sure that this table hasn't been disallowed
     $disallowed = false;
     if (isset($this->_conf['_disallowed_tables'])) {
         foreach ($this->_conf['_disallowed_tables'] as $name => $pattern) {
             if ($pattern[0] == '/' and preg_match($pattern, $query['-table'])) {
                 $disallowed = true;
                 break;
             } else {
                 if ($pattern == $query['-table']) {
                     $disallowed = true;
                     break;
                 }
             }
         }
     }
     if ($disallowed and isset($this->_conf['_allowed_tables'])) {
         foreach ($this->_conf['_allowed_tables'] as $name => $pattern) {
             if ($pattern[0] == '/' and preg_match($pattern, $query['-table'])) {
                 $disallowed = false;
                 break;
             } else {
                 if ($pattern == $query['-table']) {
                     $disallowed = false;
                     break;
                 }
             }
         }
     }
     if ($disallowed) {
         return Dataface_Error::permissionDenied(Dataface_LanguageTool::translate("Permission Denied. This table has been disallowed in the conf.ini file", "Permission denied because this table has been disallowed in the conf.ini file '"));
     }
     $actionTool = Dataface_ActionTool::getInstance();
     //if ( $this->_conf['multilingual_content'] ){
     //import('I18Nv2/I18Nv2.php');
     //I18Nv2::autoConv();
     //}
     $params = array('table' => $query['-table'], 'name' => $query['-action']);
     if (strpos($query['-action'], 'custom_') === 0) {
         $action = array('name' => $query['-action'], 'page' => substr($query['-action'], 7), 'permission' => 'view', 'mode' => 'browse', 'custom' => true);
     } else {
         $action = $actionTool->getAction($params);
         if (is_array($action) and @$action['related'] and @$query['-relationship'] and preg_match('/relationships\\.ini/', @$action['allow_override'])) {
             // This action is to be performed on the currently selected relationship.
             $raction = $table->getRelationshipsAsActions(array(), $query['-relationship']);
             if (is_array($raction)) {
                 $action = array_merge($action, $raction);
             }
         }
         if (is_array($action) and isset($action['delegate'])) {
             $params['name'] = $query['-action'] = $action['delegate'];
             $tmp = $actionTool->getActions($params);
             unset($action);
             $action =& $tmp;
             unset($tmp);
         }
         if (is_array($action) and isset($action['auth_type'])) {
             $authTool = $this->getAuthenticationTool();
             $authTool->setAuthType($action['auth_type']);
         }
     }
     if ((PEAR::isError($action) or !@$action['permission']) and $this->_conf['security_level'] >= DATAFACE_STRICT_PERMISSIONS) {
         // The only reason getAction() will return an error is if the specified action could not be found.
         // If the application is set to use strict permissions and no action was defined in the ini file
         // then this action cannot be performed.  Strict permissions mode requires that permissions be
         // strictly set or permission will be denied.
         return Dataface_Error::permissionDenied(Dataface_LanguageTool::translate("Permission Denied. No action found in strict permissions mode", "Permission denied for action '" . $query['-action'] . "'.  No entry for this action was found in the actions.ini file.  \n\t\t\t\t\tYou are currently using strict permissions mode which requires that you define all actions that you want to use in the actions.ini file with appropriate permissions information.", array('action' => $query['-action'])));
     } else {
         if (PEAR::isError($action)) {
             $action = array('name' => $query['-action'], 'label' => $query['-action']);
         }
     }
     // Step 1:  See if the delegate class has a handler.
     $delegate = $table->getDelegate();
     $handled = false;
     if (method_exists($delegate, 'handleRequest')) {
         $result = $delegate->handleRequest();
         if (PEAR::isError($result) and $result->getCode() === DATAFACE_E_REQUEST_NOT_HANDLED) {
             $handled = false;
         } else {
             if (PEAR::isError($result)) {
                 return $result;
             } else {
                 $handled = true;
             }
         }
     }
     if (isset($action['mode']) and $action['mode']) {
         $query['-mode'] = $action['mode'];
     }
     // Step 2: Look to see if there is a handler defined
     if (isset($action['custom'])) {
         $locations = array(DATAFACE_PATH . '/actions/custom.php' => 'dataface_actions_custom');
     } else {
         $locations = array();
         $locations[Dataface_Table::getBasePath($query['-table']) . '/tables/' . basename($query['-table']) . '/actions/' . basename($query['-action']) . '.php'] = 'tables_' . $query['-table'] . '_actions_' . $query['-action'];
         $locations[DATAFACE_SITE_PATH . '/actions/' . basename($query['-action']) . '.php'] = 'actions_' . $query['-action'];
         if (isset($this->_conf['_modules']) and count($this->_conf['_modules']) > 0) {
             $mt = Dataface_ModuleTool::getInstance();
             foreach ($this->_conf['_modules'] as $modname => $modpath) {
                 $mt->loadModule($modname);
                 if ($modpath[0] == '/') {
                     $locations[dirname($modpath) . '/actions/' . basename($query['-action']) . '.php'] = 'actions_' . $query['-action'];
                 } else {
                     $locations[DATAFACE_SITE_PATH . '/' . dirname($modpath) . '/actions/' . basename($query['-action']) . '.php'] = 'actions_' . $query['-action'];
                     $locations[DATAFACE_PATH . '/' . dirname($modpath) . '/actions/' . basename($query['-action']) . '.php'] = 'actions_' . $query['-action'];
                 }
             }
         }
         $locations[DATAFACE_PATH . '/actions/' . basename($query['-action']) . '.php'] = 'dataface_actions_' . $query['-action'];
         $locations[DATAFACE_PATH . '/actions/default.php'] = 'dataface_actions_default';
     }
     $doParams = array('action' => &$action);
     //parameters to be passed to the do method of the handler
     foreach ($locations as $handlerPath => $handlerClassName) {
         if (is_readable($handlerPath)) {
             import($handlerPath);
             $handler = new $handlerClassName();
             $params = array();
             if (is_array($action) and @$action['related'] and @$query['-relationship']) {
                 $params['relationship'] = $query['-relationship'];
             }
             if (!PEAR::isError($action) and method_exists($handler, 'getPermissions')) {
                 // check the permissions on this action to make sure that we are 'allowed' to perform it
                 // this method will return an array of Strings that are names of permissions granted to
                 // the current user.
                 //echo "Checking permissions:";
                 //print_r($params);
                 $permissions = $handler->getPermissions($params);
                 //} else if ( $applicationDelegate !== null and method_exists($applicationDelegate, 'getPermissions') ){
                 //	$permissions =& $applicationDelegate->getPermissions($params);
             } else {
                 //print_r($params);
                 //print_r($action);
                 $permissions = $this->getPermissions($params);
             }
             if (isset($action['permission']) && !(isset($permissions[$action['permission']]) and $permissions[$action['permission']])) {
                 if (!$permissions) {
                     return Dataface_Error::permissionDenied(df_translate("Permission Denied for action no permissions", "Permission to perform action '" . $action['name'] . "' denied. " . "Requires permission " . $action['permission'] . " but you currently " . " have no permissions granted.", array('action' => $action)));
                 } else {
                     return Dataface_Error::permissionDenied(Dataface_LanguageTool::translate("Permission Denied for action.", "Permission to perform action '" . $action['name'] . "' denied.  \n                                                            Requires permission '" . $action['permission'] . "' but only granted '" . Dataface_PermissionsTool::namesAsString($permissions) . "'.", array('action' => $action, 'permissions_granted' => Dataface_PermissionsTool::namesAsString($permissions))));
                 }
             }
             if (method_exists($handler, 'handle')) {
                 $result = $handler->handle($doParams);
                 if (PEAR::isError($result) and $result->getCode() === DATAFACE_E_REQUEST_NOT_HANDLED) {
                     continue;
                 }
                 return $result;
             }
         }
     }
     throw new Exception(df_translate('scripts.Dataface.Application.handleRequest.NO_HANDLER_FOUND', "No handler found for request.  This should never happen because, at the very least, the default handler at dataface/actions/default.php should be called.  Check the permissions on dataface/actions/default.php to make sure that it is readable by the web server."), E_USER_ERROR);
 }
 function handle($params)
 {
     session_write_close();
     header('Connection: close');
     $app = Dataface_Application::getInstance();
     $query = $app->getQuery();
     $table = Dataface_Table::loadTable($query['-table']);
     $customPath = Dataface_Table::getBasePath($table->tablename);
     $findPath = $customPath . DIRECTORY_SEPARATOR . basename($table->tablename) . DIRECTORY_SEPARATOR . 'find.html';
     if (file_exists($findPath)) {
         $html = file_get_contents($findPath);
     } else {
         $fields = array_keys($table->fields(false, true));
         $temp = $fields;
         foreach ($temp as $k => $v) {
             $fperms = $table->getPermissions(array('field' => $v));
             if (!@$fperms['find']) {
                 unset($fields[$k]);
             }
         }
         foreach ($table->relationships() as $relationship) {
             if (@$relationship->_schema['visibility'] and @$relationship->_schema['visibility']['find'] == 'hidden') {
                 continue;
             }
             $rperms = $table->getPermissions(array('relationship' => $relationship->getName()));
             if (!@$rperms['find']) {
                 continue;
             }
             $rfields = $relationship->fields(true);
             $fkeys = $relationship->getForeignKeyValues();
             $removedKeys = array();
             foreach ($fkeys as $fkeyTable => $fkey) {
                 foreach (array_keys($fkey) as $fkeyKey) {
                     $removedKeys[] = $fkeyTable . '.' . $fkeyKey;
                 }
             }
             $rfields = array_diff($rfields, $removedKeys);
             foreach ($rfields as $rfield) {
                 list($rtable, $rfield) = explode('.', $rfield);
                 //$rfperms = $table->getPermissions(array('relationship' => $relationship->getName(), 'field'=>$rfield));
                 $rfperms = $relationship->getPermissions(array('field' => $rfield));
                 if (@$rfperms['find']) {
                     $fields[] = $relationship->getName() . '.' . $rfield;
                 }
             }
             unset($rfields);
             unset($relationship);
         }
         $finalFields = array();
         foreach ($fields as $fieldname) {
             $finalFields[$fieldname] =& $table->getField($fieldname);
             if (@$finalFields[$fieldname]['visibility']['find'] == 'hidden') {
                 unset($finalFields[$fieldname]);
                 continue;
             }
             $tbl = Dataface_Table::loadTable($finalFields[$fieldname]['tablename']);
             if ($tbl->isDate($finalFields[$fieldname]['name'])) {
                 $finalFields[$fieldname]['find']['type'] = 'date';
             }
         }
         $context['fields'] = array();
         $context['relatedFields'] = array();
         foreach ($finalFields as $k => $fld) {
             if (strpos($k, '.') !== false) {
                 list($rel, $fldname) = explode('.', $k);
                 $relationship = $table->getRelationship($rel);
                 $context['relatedFields'][$relationship->getLabel()][$k] = $fld;
             } else {
                 $context['fields'][$k] = $fld;
             }
         }
         ob_start();
         df_display($context, 'xataface/modules/g2/advanced_find_form.html');
         $html = ob_get_contents();
         ob_end_clean();
     }
     $mod = Dataface_ModuleTool::getInstance()->loadModule('modules_g2');
     require_once 'modules/g2/inc/simple_html_dom.php';
     $dom = str_get_html($html);
     $els = $dom->find('select');
     foreach ($els as $el) {
         $vocab = $el->{'data-xf-vocabulary'};
         if (!$vocab) {
             continue;
         }
         $options = array('' => '', '=' => df_translate('g2_advanced_find_form.empty_list_label', "<Empty>"));
         $fieldTableName = $el->{'data-xf-table'};
         if ($fieldTableName) {
             $fieldTable = Dataface_Table::loadTable($fieldTableName);
         } else {
             $fieldTable = null;
         }
         if (!$fieldTable) {
             $fieldTable = $table;
         }
         $o2 = $fieldTable->getValuelist($vocab);
         if ($o2) {
             foreach ($o2 as $k => $v) {
                 $options[$k] = $v;
             }
         }
         $opts = array();
         foreach ($options as $k => $v) {
             $opts[] = '<option value="' . htmlspecialchars($k) . '">' . htmlspecialchars($v) . '</option>';
         }
         $el->innertext = implode("\n", $opts);
     }
     header('Content-type: text/html; charset="' . $app->_conf['oe'] . '"');
     $out = $dom->save();
     header('Content-length: ' . strlen($out));
     echo $out;
     flush();
 }