Beispiel #1
0
 public static function getInstance()
 {
     if (empty(self::$instance)) {
         self::$instance = new Xerxes_Framework_Labels();
     }
     return self::$instance;
 }
Beispiel #2
0
 public function ensureSpecifiedUser()
 {
     $strUsername = $this->request->getProperty("username");
     $labels = Xerxes_Framework_Labels::getInstance();
     $error = $labels->getLabel("text_collections_error_private_collection_save");
     $error = sprintf($error, $strUsername);
     Xerxes_Helper::ensureSpecifiedUser($strUsername, $this->request, $this->registry, $error);
 }
 public static function execute()
 {
     // calculate current file, this directory
     $this_directory = dirname(__FILE__);
     // calculate root directory of the app ../../ from here
     $path_to_parent = $this_directory;
     $path_to_parent = str_replace("\\", "/", $path_to_parent);
     $arrPath = explode("/", $path_to_parent);
     array_pop($arrPath);
     array_pop($arrPath);
     $path_to_parent = implode("/", $arrPath);
     // here so other framework files can reference it
     self::$parent_directory = $path_to_parent;
     // register framework any main xerxes class files
     self::registerClasses("{$path_to_parent}/lib/framework", "Xerxes_Framework");
     // initialize the configuration setting (Registry),
     // command-view mapping (ControllerMap), and
     // language translation (Languages) objects
     $objRegistry = Xerxes_Framework_Registry::getInstance();
     $objRegistry->init();
     $objControllerMap = Xerxes_Framework_ControllerMap::getInstance();
     $objControllerMap->init();
     // set the version number, for interface or other places
     $objRegistry->setConfig("XERXES_VERSION", $objControllerMap->getVersion(), true);
     // dynamically set the web path, if config says so,
     // doesn't work on all webserver/php set-ups, so an
     // explicit web path from config is preferred
     if ($objRegistry->getConfig("base_web_path", false) == '{dynamic}') {
         if (isset($_SERVER)) {
             $script_name = $_SERVER['SCRIPT_NAME'];
             $script_name = str_replace("/index.php", "", $script_name);
             $objRegistry->setConfig("base_web_path", $script_name);
         }
     }
     // give our session a name to keep sessions distinct between multiple
     // instances of xerxes on one server.  use base_path (preferably) or
     // application_name config directives.
     $path_base = $objRegistry->getConfig("base_web_path", false);
     $path_key = preg_replace('/\\W/', '_', $path_base);
     $session_name = "xerxessession_" . $path_key;
     if ($path_base == "") {
         $path_base = "/";
     }
     $session_path = $objRegistry->getConfig("session_path", false, $path_base);
     $session_domain = $objRegistry->getConfig("session_domain", false, null);
     session_name($session_name);
     session_set_cookie_params(0, $session_path, $session_domain);
     session_start();
     // processes the incoming request
     $objRequest = Xerxes_Framework_Request::getInstance();
     $objRequest->init();
     // utility classes
     // assists with basic paging/navigation elements for the view
     $objPage = new Xerxes_Framework_Page($objRequest, $objRegistry);
     // functions for special logging or handling of errors
     $objError = new Xerxes_Framework_Error();
     // language names
     $objLanguage = Xerxes_Framework_Languages::getInstance();
     $objLanguage->init();
     // we'll put the remaining code in a try-catch block in order to show friendly error page
     // for any uncaught exceptions
     try {
         ####################
         #  DISPLAY ERRORS  #
         ####################
         if ($objRegistry->getConfig("DISPLAY_ERRORS") == true) {
             error_reporting(E_ALL);
             ini_set('display_errors', '1');
         }
         ####################
         #   DEFAULTS       #
         ####################
         // labels
         $objLabels = Xerxes_Framework_Labels::getInstance();
         $lang = $objRequest->getProperty("lang");
         $objLabels->init($lang);
         // make sure application_name is passthrough, and has a value.
         $objRegistry->setConfig("application_name", $objRegistry->getConfig("APPLICATION_NAME", false, "Xerxes", $lang), true);
         ####################
         #     SET PATHS    #
         ####################
         ### reverse proxy
         // check to see if xerxes is running behind a reverse proxy and swap
         // host and remote ip here with their http_x_forwarded counterparts;
         // but only if configured for this, since client can spoof the header
         // if xerxes is not, in fact, behind a reverse proxy
         if ($objRegistry->getConfig("REVERSE_PROXY", false, false) == true) {
             $forward_host = $objRequest->getServer('HTTP_X_FORWARDED_HOST');
             $forward_address = $objRequest->getServer('HTTP_X_FORWARDED_FOR');
             if ($forward_host != "") {
                 $objRequest->setServer('SERVER_NAME', $forward_host);
             }
             // last ip address is the user's
             if ($forward_address != "") {
                 $arrIP = explode(",", $forward_address);
                 $objRequest->setServer('REMOTE_ADDR', trim(array_pop($arrIP)));
             }
         }
         // the working directory is the instance, so any relative paths will
         // be executed in relation to the root directory of the instance
         $working_dir = getcwd();
         $working_dir = str_replace("\\", "/", $working_dir);
         // full web path
         //
         // NOTE :if you change this code  make sure you make a corresponding
         // change in lib/framework/Error.php, since there is redundant code
         // there in case something goes horribly wrong and we need to set the
         // web path for proper display of a (friendly) error page
         $base_path = $objRegistry->getConfig('BASE_WEB_PATH', false, "");
         $this_server_name = $objRequest->getServer('SERVER_NAME');
         // check for a non-standard port
         $port = $objRequest->getServer('SERVER_PORT');
         if ($port == 80 || $port == 443) {
             $port = "";
         } else {
             $port = ":" . $port;
         }
         $protocol = "http://";
         if ($objRequest->getServer("HTTPS")) {
             $protocol = "https://";
         }
         $web = $protocol . $this_server_name . $port;
         // register these values
         $objRegistry->setConfig("SERVER_URL", $web);
         $objRegistry->setConfig("PATH_PARENT_DIRECTORY", $path_to_parent);
         $objRegistry->setConfig("APP_DIRECTORY", $working_dir);
         $objRegistry->setConfig("BASE_URL", $web . $base_path, true);
         ####################
         #   INSTRUCTIONS   #
         ####################
         // ControllerMap contains instructions for commands and views
         // based on the url parameters 'base' and 'action'
         $strBase = $objRequest->getProperty("base");
         $strAction = $objRequest->getProperty("action");
         $objControllerMap->setAction($strBase, $strAction, $objRequest);
         ####################
         #  ACCESS CONTROL  #
         ####################
         // if this part of the application is restricted to a local ip range, or requires a named login, then the
         // Restrict class will check the user's ip address or if they have logged in; failure stops the flow
         // and redirects user to a login page with the current request passed as 'return' paramater in the url
         $objRestrict = new Xerxes_Framework_Restrict($objRequest);
         // command line scripts will ignore access rules
         if ($objRequest->isCommandLine() != true) {
             if ($objControllerMap->isRestricted() == true) {
                 if ($objControllerMap->requiresLogin() == true) {
                     // resource requires a valid named username
                     $objRestrict->checkLogin();
                 } else {
                     // resource is resricted, but local ip range is okay
                     $objRestrict->checkIP();
                 }
             } else {
                 // go ahead and register local users, but don't prompt for login
                 $objRestrict->checkIP(false);
             }
         }
         // if this action is set to only be run via the command line, in order to prevent
         // web execution of potentially long-running tasks, then restrict it here
         if (!$objRequest->isCommandLine() && $objControllerMap->restrictToCLI()) {
             throw new Exception("cannot run command from web");
         }
         ####################
         #     INCLUDES     #
         ####################
         // files and directories that have been set to be included by the config file
         foreach ($objControllerMap->getIncludes() as $path_to_include) {
             self::registerClasses($path_to_parent . "/{$path_to_include}");
         }
         ####################
         #       DATA       #
         ####################
         // set-up the data by defining the root element
         $strDocumentElement = $objControllerMap->getDocumentElement();
         $objRequest->setDocumentElement($strDocumentElement);
         // pass config values that should be made available to the XSLT
         $objRequest->addDocument($objRegistry->publicXML());
         // the data will be built-up by calling one or more command classes
         // which will fetch their data based on other parameters supplied in
         // the request; returning that data as xml to a master xml dom document
         // inside the Xerxes_Framework_Request class, or in some cases specififying
         // a url to redirect the user out
         $commands = $objControllerMap->getCommands();
         foreach ($commands as $arrCommand) {
             $strDirectory = $arrCommand[0];
             // directory where the command class is located
             $strNamespace = $arrCommand[1];
             // prefix namespace of the command class
             $strClassFile = $arrCommand[2];
             // suffix name of the command class
             // directory where commands live
             $command_path = "{$path_to_parent}/commands/{$strDirectory}";
             // allow for a local override, even
             $local_command_path = "commands/{$strDirectory}";
             // echo "<h3>$strClassFile</h3>";
             // first, include any parent class, assuming that the parent class will
             // follow the naming convention of having the same name as the directory
             $strParentClass = Xerxes_Framework_Parser::strtoupper(substr($strDirectory, 0, 1)) . substr($strDirectory, 1);
             if (file_exists("{$local_command_path}/{$strParentClass}.php")) {
                 require_once "{$local_command_path}/{$strParentClass}.php";
             } elseif (file_exists("{$command_path}/{$strParentClass}.php")) {
                 require_once "{$command_path}/{$strParentClass}.php";
             }
             // if the specified command class exists in the distro or local commands folder, then
             // instantiate an object and execute it
             $strClass = $strNamespace . "_Command_" . $strClassFile;
             $local_command = file_exists("{$local_command_path}/{$strClassFile}.php");
             if (file_exists("{$command_path}/{$strClassFile}.php") || $local_command) {
                 // if the instance has a local version, take it!
                 if ($local_command) {
                     require_once "{$local_command_path}/{$strClassFile}.php";
                 } else {
                     require_once "{$command_path}/{$strClassFile}.php";
                 }
                 // instantiate the command class and execute it, but only
                 // if it extends xerxes_framework_command
                 $objCommand = new $strClass();
                 if ($objCommand instanceof Xerxes_Framework_Command) {
                     $objCommand->execute($objRequest, $objRegistry);
                 } else {
                     throw new Exception("command classes must be instance of Xerxes_Framework_Command");
                 }
             } else {
                 // if no command but a view was specified, then go ahead and show the view
                 // minus any data, since the view is doin' its own thang
                 if (!file_exists($objControllerMap->getView())) {
                     throw new Exception("invalid command {$strClass}");
                 }
             }
         }
         ####################
         #     COOKIES      #
         ####################
         // any cookies specified in the reuqest object? if so, set em now.
         $cookieSetParams = $objRequest->cookieSetParams();
         foreach ($cookieSetParams as $cookieParams) {
             set_cookie($cookieParams[0], $cookieParams[1], $cookieParams[2], $cookieParams[3], $cookieParams[4], $cookieParams[5]);
         }
         ####################
         #     REDIRECT     #
         ####################
         // if the result of the command is a redirect, we will stop the
         // flow and redirect the user out, unless overridden by the noRedirect
         // directive
         if ($objRequest->getRedirect() != null) {
             if ($objRequest->getProperty("noRedirect") == null) {
                 header("Location: " . $objRequest->getRedirect());
                 exit;
             } else {
                 // include in the resposne what the redirect would have been
                 $objRequest->setProperty("redirect", $objRequest->getRedirect());
             }
         }
         ####################
         #       VIEW       #
         ####################
         // SET THE HTTP HEADER
         //
         // we'll set the content-type, and potentially other header elements, based on the paramater 'format';
         // format must correspond to one of the pre-defined format content-types in setHeader() or can be a user-
         // defined format set in action.xml
         $format = $objRequest->getProperty("format");
         if ($objControllerMap->getFormat($format) != null) {
             header($objControllerMap->getFormat($format));
         } else {
             self::setHeader($format);
         }
         // get the xml from the request object, but exclude any server information
         // from being included if format=source
         $bolShowServer = true;
         if ($format == "xerxes") {
             $bolShowServer = false;
         }
         $objXml = new DOMDocument();
         $objXml = $objRequest->toXML($bolShowServer);
         // RAW XML DISPLAY
         //
         // you can append 'format=xerxes' to the querystring to have this controller spit back
         // the response in plain xml, which can be useful in some cases, like maybe AJAX?
         if ($format == "xerxes") {
             echo $objXml->saveXML();
         } else {
             // VIEW CODE
             //
             // ControllerMap contains instructions on what file to include for the view; typically
             // this will be an xslt file, but could be a php file if the xslt does not
             // provide enough flexibility; php page will inherit the xml dom document and
             // can go from there
             if ($objControllerMap->getView() == "") {
                 // No view specified, no view will be executed.
                 return;
             }
             // PHP CODE
             if ($objControllerMap->getViewType() != "xsl" && $objControllerMap->getViewType() != null) {
                 $file = $objControllerMap->getView();
                 $distro_file = $objRegistry->getConfig("PATH_PARENT_DIRECTORY", true) . "/lib/{$file}";
                 if (file_exists($file)) {
                     require_once $file;
                 } elseif (file_exists($distro_file)) {
                     require_once $distro_file;
                 } else {
                     throw new Exception("Could not find non-xsl view specified to include: {$file}");
                 }
             } else {
                 // XSLT CODE
                 $output = $objPage->transform($objXml, $objControllerMap->getView(), null);
                 // EMBEDED JAVASCRIPT DISPLAY
                 //
                 // you can append 'format=embed_html_js' to the querystring to output
                 // the content as a javascript source document with everything wrapped in
                 // document.write() statements
                 if ($format == "embed_html_js") {
                     // first escape any single quotes
                     $output = str_replace("'", "\\'", $output);
                     // now break the html into lines and output with document.write('')
                     $lines = explode("\n", $output);
                     $new_lines = array("// Javascript output. ");
                     foreach ($lines as $line) {
                         array_push($new_lines, "document.write('" . $line . "');");
                     }
                     $output = implode("\n", $new_lines);
                 }
                 echo $output;
             }
             //remove the flash message, intended for one display only.
             $objRequest->setSession("flash_message", null);
         }
     } catch (Exception $e) {
         $objError->handle($e, $objRequest, $objRegistry);
     }
 }
Beispiel #4
0
 public function doExecute()
 {
     $labels = Xerxes_Framework_Labels::getInstance();
     $xml = $labels->getXML();
     $this->request->addDocument($xml);
 }
Beispiel #5
0
 /**
  * Do something with uncaught errors
  */
 public static function handle($e, Xerxes_Framework_Request $objRequest, Xerxes_Framework_Registry $objRegistry)
 {
     if ($objRegistry->getConfig("DISPLAY_ERRORS", false, false)) {
         throw $e;
     }
     // flag certain exception types for special handling in the xslt
     $strErrorType = get_class($e);
     // might be a sub-class, reset so view will catch.
     if ($e instanceof PDOException) {
         $strErrorType = "PDOException";
     }
     // if this is the command line, just rethrow the error so we can see it; might
     // make this a little better formatted in the future
     if ($objRequest->isCommandLine()) {
         throw $e;
     } else {
         // translate heading and message
         $labels = Xerxes_Framework_Labels::getInstance();
         if ($e instanceof Xerxes_Exception) {
             $heading = $e->heading();
         } else {
             $heading = "text_error";
         }
         $heading = $labels->getLabel($heading);
         $message = $labels->getLabel($e->getMessage());
         // first output to apache error log
         error_log("Xerxes error: " . $message . ": " . $e->getTraceAsString());
         //set proper http response code
         $resultStatus = 500;
         if ($e instanceof Xerxes_Exception_AccessDenied) {
             $resultStatus = 403;
         } else {
             if ($e instanceof Xerxes_Exception_NotFound) {
                 $resultStatus = 404;
             }
         }
         header(' ', true, $resultStatus);
         // send back http status as internal server error or other specified status
         // for the web, we'll convert the error message to xml along with the type
         // of exception and hand display off to the error.xsl file
         $objError = new DOMDocument();
         $objError->loadXML("<error />");
         $objMessage = $objError->createElement("message", $message);
         $objMessage->setAttribute("type", $strErrorType);
         $objError->documentElement->appendChild($objMessage);
         $objHeading = $objError->createElement("heading", $heading);
         $objError->documentElement->appendChild($objHeading);
         // make sure we're showing the main error file
         $objRegistry->setConfig("XSL_PARENT_DIRECTORY", null);
         // set the base url for the error.xsl file's benefit; don't want to assume that
         // the earlier code to this effect was executed before an exception, so this is redundant
         $base_path = $objRegistry->getConfig('BASE_WEB_PATH', false, "");
         $this_server_name = $objRequest->getServer('SERVER_NAME');
         // check for a non-standard port
         $port = $objRequest->getServer('SERVER_PORT');
         if ($port == 80 || $port == 443) {
             $port = "";
         } else {
             $port = ":" . $port;
         }
         $protocol = "http://";
         if ($objRequest->getServer("HTTPS")) {
             $protocol = "https://";
         }
         $web = $protocol . $this_server_name . $port . $base_path;
         $objBaseURL = $objError->createElement("base_url", $web);
         $objError->documentElement->appendChild($objBaseURL);
         // if it's a db denied exception, include info on dbs.
         if ($e instanceof Xerxes_Exception_DatabasesDenied) {
             $excluded_xml = $objError->createElement("excluded_dbs");
             $objError->documentElement->appendChild($excluded_xml);
             foreach ($e->deniedDatabases() as $db) {
                 $element = Xerxes_Helper::databaseToNodeset($db, $objRequest, $objRegistry);
                 $element = $objError->importNode($element, true);
                 $excluded_xml->appendChild($element);
             }
         }
         // add in the request object's stuff
         $request_xml = $objRequest->toXML();
         $imported = $objError->importNode($request_xml->documentElement, true);
         foreach ($imported->childNodes as $childNode) {
             $objError->documentElement->appendChild($childNode);
         }
         if ($objRequest->getProperty("format") == "xerxes") {
             header('Content-type: text/xml');
             echo $objError->saveXML();
         } else {
             // display it to the user. Transform will pick up local
             // xsl for error page too, great.
             echo Xerxes_Framework_Parser::transform($objError, "xsl/error.xsl");
         }
     }
     // need to incorporate methods for doing additional actions based on the type
     // of error -- probably a config option
 }
 public function doExecute()
 {
     // metalib search object
     $objSearch = $this->getSearchObject();
     // params from the request
     $strQuery = $this->request->getProperty("query");
     $strQuery2 = $this->request->getProperty("query2");
     $strField = $this->request->getProperty("field");
     $strField2 = $this->request->getProperty("field2");
     $strFindOperator = $this->request->getProperty("find_operator1");
     $arrDatabases = $this->request->getProperty("database", true);
     $strSubject = $this->request->getProperty("subject");
     $strSpell = $this->request->getProperty("spell");
     $strContext = $this->request->getProperty("context");
     $strContextUrl = $this->request->getProperty("context_url");
     // configuration options
     $configNormalize = $this->registry->getConfig("NORMALIZE_QUERY", false, false);
     $configBaseUrl = $this->registry->getConfig("BASE_URL", true);
     $configYahooID = $this->registry->getConfig("YAHOO_ID", false, "calstate");
     $configSearchLimit = $this->registry->getConfig("SEARCH_LIMIT", true);
     $configContextUrl = $this->registry->getConfig("LIMIT_CONTEXT_URL", false);
     //  if so configured, ensure that context_url is limited to certain domain(s)
     if ($configContextUrl != null) {
         $bolPassed = Xerxes_Framework_Parser::withinDomain($strContextUrl, $configContextUrl);
         if ($bolPassed == false) {
             throw new Exception("context_url only allowed for specified domains");
         }
     }
     // database communications object
     $objData = new Xerxes_DataMap();
     // if subject is given but not databases, automatically find
     // databases for subject, from first sub-category.
     if ($strSubject != null && count($arrDatabases) == 0) {
         $search_limit = $this->registry->getConfig("SEARCH_LIMIT", true);
         $arrDatabases = array();
         $objSubject = $objData->getSubject(strtolower($strSubject), null, "metalib", null, $this->request->getProperty("lang"));
         // did we find a subject that has subcategories?
         if ($objSubject != null && $objSubject->subcategories != null && count($objSubject->subcategories) > 0) {
             $subs = $objSubject->subcategories;
             $objSubcategory = $subs[0];
             $index = 0;
             // get databases up to search limit from first subcat,
             // add to $arrdatabases.
             foreach ($objSubcategory->databases as $objDatabaseData) {
                 if ($objDatabaseData->searchable == 1) {
                     array_push($arrDatabases, $objDatabaseData->metalib_id);
                     $index++;
                 }
                 if ($index >= $search_limit) {
                     break;
                 }
             }
         }
     }
     // if we have a subject, but no context/contexturl, look
     // them up for the subject. Allows convenient defaults
     // for direct-linking into search results.
     if ($strContext == "" && $strSubject != "") {
         // look up the subject if we haven't already, to get the name.
         if (!isset($objSubject)) {
             $objSubject = $objData->getSubject($strSubject);
         }
         $strContext = $objSubject->name;
     }
     if ($strContextUrl == "" && $strSubject != "") {
         $strContextUrl = $this->request->url_for(array("base" => "databases", "action" => "subject", "subject" => $strSubject));
     }
     // ensure a query and field
     if ($strQuery == "") {
         throw new Exception("text_metasearch_error_no_search_terms");
     }
     if ($strField == "") {
         $strField = "WRD";
     }
     if ($strField2 == "") {
         $strField2 = "WRD";
     }
     if ($strFindOperator == "") {
         $strFindOperator = "AND";
     }
     // get databases
     $arrDB = $objData->getDatabases($arrDatabases);
     // start out database information xml object.
     $objXml = new DOMDocument();
     $objXml->loadXML("<search />");
     // access control for databases
     $excludedDbs = array();
     $excludedIDs = array();
     foreach ($arrDB as $db) {
         if (!Xerxes_Helper::dbSearchableForUser($db, $this->request, $this->registry)) {
             $excludedDbs[] = $db;
             $excludedIDs[] = (string) $db->metalib_id;
         }
     }
     if (count($excludedDbs) > 0) {
         // remove excluded dbs from our db lists. what a pain in php, sorry.
         foreach ($arrDB as $key => $db) {
             if (in_array((string) $db->metalib_id, $excludedIDs)) {
                 unset($arrDB[$key]);
             }
         }
         foreach ($arrDatabases as $key => $id) {
             if (in_array($id, $excludedIDs)) {
                 unset($arrDatabases[$key]);
             }
         }
         // and make a note of the excluded dbs please.
         $excluded_xml = $objXml->createElement("excluded_dbs");
         $objXml->documentElement->appendChild($excluded_xml);
         foreach ($excludedDbs as $db) {
             $element = Xerxes_Helper::databaseToNodeset($db, $this->request, $this->registry);
             $element = $objXml->importNode($element, true);
             $excluded_xml->appendChild($element);
         }
     }
     // ensure correct number of databases selected
     if (count($arrDatabases) < 1 && count($excludedDbs) > 0) {
         $e = new Xerxes_Exception_DatabasesDenied("text_metasearch_error_not_authorized");
         $e->setDeniedDatabases($excludedDbs);
         throw $e;
     } elseif (count($arrDatabases) < 1) {
         throw new Exception("text_metasearch_error_no_databases");
     }
     if (count($arrDatabases) > $configSearchLimit) {
         $labels = Xerxes_Framework_Labels::getInstance();
         $error = $labels->getLabel("text_metasearch_error_too_many_databases");
         $error = sprintf($error, $configSearchLimit);
         throw new Exception($error);
     }
     $strSpellCorrect = "";
     // spelling correction
     $strSpellUrl = "";
     // return url for spelling change
     $strGroup = "";
     // group id number
     $strNormalizedQuery = "";
     // normalized query
     // query parser provides normalization and spell check
     $objQueryParser = new Xerxes_QueryParser();
     // normalize query option is still experimental (2009-04-16)
     $strFullQuery = $objQueryParser->normalizeMetalibQuery($strField, $strQuery, $strFindOperator, $strField2, $strQuery2, $configNormalize);
     // initiate search with Metalib
     $strGroup = $objSearch->search($strFullQuery, $arrDatabases);
     // something went wrong, yo!
     if ($strGroup == "") {
         throw new Exception("Could not initiate search with Metalib server");
     }
     // check spelling unless this is a return submission from a previous spell correction
     $strSpellSuggestions = null;
     if ($strSpell == null) {
         // check spelling
         $strAltYahoo = $this->registry->getConfig("ALTERNATE_YAHOO_LOCATION", false);
         $strSpellCorrect = $objQueryParser->checkSpelling($strQuery, $configYahooID, $strAltYahoo);
         $strSpellCorrect2 = null;
         if ($strQuery2) {
             $strSpellCorrect2 = $objQueryParser->checkSpelling($strQuery2, $configYahooID);
         }
         if ($strSpellCorrect != "" || $strSpellCorrect2 != "") {
             // construct spell check return url with spelling suggestion
             // If both search fields were used (advanced search), spell corrections
             // may be in first, second, or both.
             $strNewQuery = $strQuery;
             $arrSuggestions = array();
             if ($strSpellCorrect) {
                 $strNewQuery = $strSpellCorrect;
                 array_push($arrSuggestions, $strSpellCorrect);
             }
             $strNewQuery2 = $strQuery2;
             if ($strSpellCorrect2) {
                 $strNewQuery2 = $strSpellCorrect2;
                 array_push($arrSuggestions, $strSpellCorrect2);
             }
             $strSpellSuggestions = join(" ", $arrSuggestions);
             $strSpellUrl = "./?base=metasearch&action=search&spell=1&query=" . urlencode($strNewQuery) . "&field=" . $strField;
             if ($strNewQuery2) {
                 $strSpellUrl .= "&query2=" . urlencode($strNewQuery2) . "&field2=" . $strField2;
             }
             $strSpellUrl .= "&context=" . urlencode($strContext);
             $strSpellUrl .= "&context_url=" . urlencode($strContextUrl);
             foreach ($arrDatabases as $strDatabase) {
                 if ($strDatabase != null) {
                     $strSpellUrl .= "&database=" . $strDatabase;
                 }
             }
         }
     }
     // create search information xml
     $arrSearch = array();
     $arrSearch["date"] = date("Y-m-d");
     $arrSearch["spelling"] = $strSpellSuggestions;
     $arrSearch["spelling_url"] = $strSpellUrl;
     $arrSearch["context"] = $strContext;
     $arrSearch["context_url"] = $strContextUrl;
     foreach ($arrSearch as $key => $value) {
         $objElement = $objXml->createElement($key, Xerxes_Framework_Parser::escapeXml($value));
         $objXml->documentElement->appendChild($objElement);
     }
     $objPair = $objXml->createElement("pair");
     $objPair->setAttribute("position", 1);
     $objXml->documentElement->appendChild($objPair);
     $arrQuery = array();
     $arrQuery["query"] = $strQuery;
     $arrQuery["field"] = $strField;
     $arrQuery["normalized"] = $strFullQuery;
     foreach ($arrQuery as $key => $value) {
         $objElement = $objXml->createElement($key, Xerxes_Framework_Parser::escapeXml($value));
         $objPair->appendChild($objElement);
     }
     // add second pair if present.
     if ($strQuery2) {
         $objOperator = $objXml->createElement("operator", $strFindOperator);
         $objOperator->setAttribute("position", 1);
         $objXml->documentElement->appendChild($objOperator);
         $objPair = $objXml->createElement("pair");
         $objPair->setAttribute("position", 2);
         $objXml->documentElement->appendChild($objPair);
         $arrQuery = array();
         $arrQuery["query"] = $strQuery2;
         $arrQuery["field"] = $strField2;
         foreach ($arrQuery as $key => $value) {
             $objElement = $objXml->createElement($key, Xerxes_Framework_Parser::escapeXml($value));
             $objPair->appendChild($objElement);
         }
     }
     // get links from ird records for those databases that have been included in the search and
     // store it here so we can get at this information easily on any subsequent page without having
     // to go back to the database
     $objDatabaseLinks = $objXml->createElement("database_links");
     $objXml->documentElement->appendChild($objDatabaseLinks);
     foreach ($arrDB as $objDatabase) {
         // create a database node and append to database_links
         $objNodeDatabase = Xerxes_Helper::databaseToLinksNodeset($objDatabase, $this->request, $this->registry);
         $objNodeDatabase = $objXml->importNode($objNodeDatabase, true);
         $objDatabaseLinks->appendChild($objNodeDatabase);
     }
     // add any warnings from metalib
     $objWarnings = $objSearch->getWarnings();
     if ($objWarnings != null) {
         $objImport = $objXml->importNode($objWarnings->documentElement, true);
         $objXml->documentElement->appendChild($objImport);
     }
     $strGroup = $this->getSearchDate() . "-" . $strGroup;
     // save this information in the cache
     $this->setCache($strGroup, "search", $objXml);
     // redirect to hits page
     $arrParams = array("base" => "metasearch", "action" => "hits", "group" => $strGroup);
     $this->saveCache();
     $this->request->setRedirect($this->request->url_for($arrParams));
     return 1;
 }