/**
  * Execute this filter.
  *
  * @param      AgaviFilterChain        A FilterChain instance.
  * @param      AgaviExecutionContainer The current execution container.
  *
  * @author     David Zülke <*****@*****.**>
  * @author     Sean Kerr <*****@*****.**>
  * @since      0.9.0
  */
 public function execute(AgaviFilterChain $filterChain, AgaviExecutionContainer $container)
 {
     // get the cool stuff
     $context = $this->getContext();
     $user = $context->getUser();
     // get the current action instance
     $actionInstance = $container->getActionInstance();
     // get the credential required for this action
     $credential = $actionInstance->getCredentials();
     if (!$actionInstance->isSecure()) {
         // the action instance does not require authentication, so we can continue in the chain and then bail out early
         return $filterChain->execute($container);
     }
     // credentials can be anything you wish; a string, array, object, etc.
     // as long as you add the same exact data to the user as a credential,
     // it will use it and authorize the user as having the credential
     //
     // NOTE: the nice thing about the Action class is that getCredential()
     //       is vague enough to describe any level of security and can be
     //       used to retrieve such data and should never have to be altered
     if ($user->isAuthenticated() && ($credential === null || $user->hasCredentials($credential))) {
         // the user has access, continue
         $filterChain->execute($container);
     } else {
         if ($user->isAuthenticated()) {
             // the user doesn't have access
             $container->setNext($container->createSystemActionForwardContainer('secure'));
         } else {
             // the user is not authenticated
             $container->setNext($container->createSystemActionForwardContainer('login'));
         }
     }
 }
 /**
  * Execute this filter.
  *
  * @param      AgaviFilterChain        The filter chain.
  * @param      AgaviExecutionContainer The current execution container.
  *
  * @throws     <b>AgaviFilterException</b> If an error occurs during execution.
  *
  * @author     David Zülke <*****@*****.**>
  * @author     Sean Kerr <*****@*****.**>
  * @since      0.9.0
  */
 public function execute(AgaviFilterChain $filterChain, AgaviExecutionContainer $container)
 {
     $context = $this->getContext();
     $comment = $this->getParameter('comment', false);
     $replace = $this->getParameter('replace', false);
     $start = microtime(true);
     $filterChain->execute($container);
     $response = $container->getResponse();
     $outputTypes = (array) $this->getParameter('output_types');
     if (!$response->isContentMutable() || is_array($outputTypes) && !in_array($response->getOutputType()->getName(), $outputTypes)) {
         return;
     }
     $time = microtime(true) - $start;
     if ($replace) {
         $output = $response->getContent();
         $output = str_replace($replace, $time, $output);
         $response->setContent($output);
     }
     if ($comment) {
         if ($comment === true) {
             $comment = "\n\n<!-- This page took %s seconds to process -->";
         }
         $response->appendContent(sprintf($comment, $time));
     }
 }
 public function executeOnce(AgaviFilterChain $filterChain, AgaviExecutionContainer $container)
 {
     $filterChain->execute($container);
     $interfaces = get_declared_interfaces();
     $classes = get_declared_classes();
     $text = "Interfaces ** \n - " . implode("\n - ", $interfaces) . "\n Classes ** \n - " . implode("\n - ", $classes);
     $container->getContext()->getLoggerManager()->getLogger("debug")->log(new AgaviLoggerMessage("{$text}", AgaviLogger::DEBUG));
 }
 /**
  * If authkey was used, do a logout after executing
  *
  * (non-PHPdoc)
  * @see AgaviIFilter::execute()
  */
 public function execute(AgaviFilterChain $filterChain, AgaviExecutionContainer $container)
 {
     $filterChain->execute($container);
     $flag = (bool) $container->getAttribute('flag', 'org.icinga.api.auth', false);
     $user = $container->getContext()->getUser();
     if ($flag === true && $user->isAuthenticated()) {
         $user->doLogout();
         @session_destroy();
         // Remove session from database
     }
 }
 public function execute(AgaviFilterChain $filterChain, AgaviExecutionContainer $container)
 {
     $isGlobal = ++self::$runCount == 1;
     if ($isGlobal) {
         // We are called from a global filterchain
         //trigger datasource event listeners
         foreach ($this->rq->getAttribute('datasources', self::NS, array()) as $ds) {
             $ds->beforeExecuteOnce($container);
         }
     } else {
         // This is a action filterchain
         //trigger datasource event listeners
         foreach ($this->rq->getAttribute('datasources', self::NS, array()) as $ds) {
             $ds->beforeExecute($container);
         }
     }
     // Proceed with execution
     $filterChain->execute($container);
     if ($isGlobal) {
         // We are called from a global filterchain
         //trigger datasource event listeners
         foreach ($this->rq->getAttribute('datasources', self::NS, array()) as $ds) {
             $ds->afterExecuteOnce($container);
         }
         //log global (i.e. not per action) stuff
         $this->rq->setAttribute('routes', $this->getMatchedRoutes(), self::NS_DATA);
         $this->rq->setAttribute('request_data', array('request_parameters' => $this->getContext()->getRequest()->getRequestData()->getParameters(), 'cookies' => $this->getContext()->getRequest()->getRequestData()->getCookies(), 'headers' => $this->getContext()->getRequest()->getRequestData()->getHeaders()), self::NS_DATA);
         $this->rq->setAttribute('tm', $this->getContext()->getTranslationManager(), self::NS_DATA);
         //		$this->log['environments'] = $this->getAvailableEnvironments();
         $this->render($container);
     } else {
         //trigger datasource event listeners
         foreach ($this->rq->getAttribute('datasources', self::NS, array()) as $ds) {
             $ds->afterExecute($container);
         }
         //now the action has been executed and we'll log what can be logged
         if (true) {
             //FIXME: options: in_array('actions', $this->options['sections'])) {
             $this->log($container);
         }
     }
 }
Пример #6
0
 /**
  * Execute this filter.
  *
  * @param      AgaviFilterChain        The filter chain.
  * @param      AgaviExecutionContainer The current execution container.
  *
  * @throws     <b>AgaviFilterException</b> If an error occurs during execution.
  *
  * @author     David Zülke <*****@*****.**>
  * @since      1.0.0
  */
 public function execute(AgaviFilterChain $filterChain, AgaviExecutionContainer $container)
 {
     // nothing to do so far. let's carry on in the chain
     $filterChain->execute($container);
     // fetch some prerequisites
     $response = $container->getResponse();
     $ot = $response->getOutputType();
     $cfg = $this->getParameters();
     if (!$response->isContentMutable() || !($output = $response->getContent())) {
         // content empty or response not mutable; it's over!
         return;
     }
     if (is_array($cfg['methods']) && !in_array($container->getRequestMethod(), $cfg['methods'])) {
         // we're not allowed to run for this request method
         return;
     }
     if (is_array($cfg['output_types']) && !in_array($ot->getName(), $cfg['output_types'])) {
         // we're not allowed to run for this output type
         return;
     }
     $tidy = new tidy();
     $tidy->parseString($output, $cfg['tidy_options'], $cfg['tidy_encoding']);
     $tidy->cleanRepair();
     if ($tidy->getStatus()) {
         // warning or error occurred
         $emsg = sprintf('Tidy Filter encountered the following problems while parsing and cleaning the document: ' . "\n\n%s", $tidy->errorBuffer);
         if (AgaviConfig::get('core.use_logging') && $cfg['log_errors']) {
             $lmsg = $emsg . "\n\nResponse content:\n\n" . $response->getContent();
             $lm = $this->context->getLoggerManager();
             $mc = $lm->getDefaultMessageClass();
             $m = new $mc($lmsg, $cfg['logging_severity']);
             $lm->log($m, $cfg['logging_logger']);
         }
         // all in all, that didn't go so well. let's see if we should just silently abort instead of throwing an exception
         if (!$cfg['ignore_errors']) {
             throw new AgaviParseException($emsg);
         }
     }
     $response->setContent((string) $tidy);
 }
    /**
     * Execute this filter.
     *
     * @param      AgaviFilterChain        The filter chain.
     * @param      AgaviExecutionContainer The current execution container.
     *
     * @throws     <b>AgaviFilterException</b> If an error occurs during execution.
     *
     * @author     David Zülke <*****@*****.**>
     * @since      0.11.0
     */
    public function executeOnce(AgaviFilterChain $filterChain, AgaviExecutionContainer $container)
    {
        $filterChain->execute($container);
        $response = $container->getResponse();
        if (!$response->isContentMutable() || !($output = $response->getContent())) {
            return;
        }
        $rq = $this->getContext()->getRequest();
        $cfg = $rq->getAttributes('org.agavi.filter.FormPopulationFilter');
        $ot = $response->getOutputType();
        if (is_array($cfg['output_types']) && !in_array($ot->getName(), $cfg['output_types'])) {
            return;
        }
        if (is_array($cfg['populate']) || $cfg['populate'] instanceof AgaviParameterHolder) {
            $populate = $cfg['populate'];
        } elseif ($cfg['populate'] === true || in_array($container->getRequestMethod(), $cfg['methods']) && $cfg['populate'] !== false) {
            $populate = $rq->getRequestData();
        } else {
            return;
        }
        $skip = null;
        if ($cfg['skip'] instanceof AgaviParameterHolder) {
            $cfg['skip'] = $cfg['skip']->getParameters();
        } elseif ($cfg['skip'] !== null && !is_array($cfg['skip'])) {
            $cfg['skip'] = null;
        }
        if ($cfg['skip'] !== null && count($cfg['skip'])) {
            $skip = '/(\\A' . str_replace('\\[\\]', '\\[[^\\]]*\\]', implode('|\\A', array_map('preg_quote', $cfg['skip'], array_fill(0, count($cfg['skip']), '/')))) . ')/';
        }
        if ($cfg['force_request_uri'] !== false) {
            $ruri = $cfg['force_request_uri'];
        } else {
            $ruri = $rq->getRequestUri();
        }
        if ($cfg['force_request_url'] !== false) {
            $rurl = $cfg['force_request_url'];
        } else {
            $rurl = $rq->getUrl();
        }
        if (isset($cfg['validation_report']) && $cfg['validation_report'] instanceof AgaviValidationReport) {
            $vr = $cfg['validation_report'];
        } else {
            $vr = $container->getValidationManager()->getReport();
        }
        $errorMessageRules = array();
        if (isset($cfg['error_messages']) && is_array($cfg['error_messages'])) {
            $errorMessageRules = $cfg['error_messages'];
        }
        $fieldErrorMessageRules = $errorMessageRules;
        if (isset($cfg['field_error_messages']) && is_array($cfg['field_error_messages']) && count($cfg['field_error_messages'])) {
            $fieldErrorMessageRules = $cfg['field_error_messages'];
        }
        $multiFieldErrorMessageRules = $fieldErrorMessageRules;
        if (isset($cfg['multi_field_error_messages']) && is_array($cfg['multi_field_error_messages']) && count($cfg['multi_field_error_messages'])) {
            $multiFieldErrorMessageRules = $cfg['multi_field_error_messages'];
        }
        $luie = libxml_use_internal_errors(true);
        libxml_clear_errors();
        $this->doc = new DOMDocument();
        $this->doc->substituteEntities = $cfg['dom_substitute_entities'];
        $this->doc->resolveExternals = $cfg['dom_resolve_externals'];
        $this->doc->validateOnParse = $cfg['dom_validate_on_parse'];
        $this->doc->preserveWhiteSpace = $cfg['dom_preserve_white_space'];
        $this->doc->formatOutput = $cfg['dom_format_output'];
        $xhtml = preg_match('/<!DOCTYPE[^>]+XHTML[^>]+/', $output) > 0 && strtolower($cfg['force_output_mode']) != 'html' || strtolower($cfg['force_output_mode']) == 'xhtml';
        $hasXmlProlog = false;
        if ($xhtml && preg_match('/^<\\?xml[^\\?]*\\?>/', $output)) {
            $hasXmlProlog = true;
        } elseif ($xhtml && preg_match('/;\\s*charset=(")?(?P<charset>.+?(?(1)(?=(?<!\\\\)")|($|(?=[;\\s]))))(?(1)")/i', $ot->getParameter('http_headers[Content-Type]'), $matches)) {
            // media-type = type "/" subtype *( ";" parameter ), says http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
            // add an XML prolog with the char encoding, works around issues with ISO-8859-1 etc
            $output = "<?xml version='1.0' encoding='" . $matches['charset'] . "' ?>\n" . $output;
        }
        if ($xhtml && $cfg['parse_xhtml_as_xml']) {
            $this->doc->loadXML($output);
            $this->xpath = new DomXPath($this->doc);
            if ($this->doc->documentElement && $this->doc->documentElement->namespaceURI) {
                $this->xpath->registerNamespace('html', $this->doc->documentElement->namespaceURI);
                $this->xmlnsPrefix = 'html:';
            } else {
                $this->xmlnsPrefix = '';
            }
        } else {
            $this->doc->loadHTML($output);
            $this->xpath = new DomXPath($this->doc);
            $this->xmlnsPrefix = '';
        }
        if (libxml_get_last_error() !== false) {
            $errors = array();
            $maxError = LIBXML_ERR_NONE;
            foreach (libxml_get_errors() as $error) {
                $errors[] = sprintf('[%s #%d] Line %d: %s', $error->level == LIBXML_ERR_WARNING ? 'Warning' : ($error->level == LIBXML_ERR_ERROR ? 'Error' : 'Fatal'), $error->code, $error->line, $error->message);
                $maxError = max($maxError, $error->level);
            }
            libxml_clear_errors();
            libxml_use_internal_errors($luie);
            $emsg = sprintf("Form Population Filter encountered the following error%s while parsing the document:\n\n" . "%s\n\n" . "Non-fatal errors are typically recoverable; you may set the 'ignore_parse_errors' configuration parameter to LIBXML_ERR_WARNING or LIBXML_ERR_ERROR (default) to suppress them.\n" . "If you set 'ignore_parse_errors' to LIBXML_ERR_FATAL (recommended for production), Form Population Filter will silently abort execution in the event of fatal errors.\n" . "Regardless of the setting, all errors encountered will be logged.", count($errors) > 1 ? 's' : '', implode("\n", $errors));
            if (AgaviConfig::get('core.use_logging') && $cfg['log_parse_errors']) {
                $severity = AgaviLogger::INFO;
                switch ($maxError) {
                    case LIBXML_ERR_WARNING:
                        $severity = AgaviLogger::WARN;
                        break;
                    case LIBXML_ERR_ERROR:
                        $severity = AgaviLogger::ERROR;
                        break;
                    case LIBXML_ERR_FATAL:
                        $severity = AgaviLogger::FATAL;
                        break;
                }
                $lmsg = $emsg . "\n\nResponse content:\n\n" . $response->getContent();
                $lm = $this->context->getLoggerManager();
                $mc = $lm->getDefaultMessageClass();
                $m = new $mc($lmsg, $severity);
                $lm->log($m, $cfg['logging_logger']);
            }
            // should we throw an exception, or carry on?
            if ($maxError > $cfg['ignore_parse_errors']) {
                throw new AgaviParseException($emsg);
            } elseif ($maxError == LIBXML_ERR_FATAL) {
                // for fatal errors, we cannot continue populating, so we must silently abort
                return;
            }
        }
        libxml_clear_errors();
        libxml_use_internal_errors($luie);
        $properXhtml = false;
        foreach ($this->xpath->query(sprintf('//%1$shead/%1$smeta', $this->xmlnsPrefix)) as $meta) {
            if (strtolower($meta->getAttribute('http-equiv')) == 'content-type') {
                if ($this->doc->encoding === null) {
                    // media-type = type "/" subtype *( ";" parameter ), says http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
                    if (preg_match('/;\\s*charset=(")?(?P<charset>.+?(?(1)(?=(?<!\\\\)")|($|(?=[;\\s]))))(?(1)")/i', $meta->getAttribute('content'), $matches)) {
                        $this->doc->encoding = $matches['charset'];
                    } else {
                        $this->doc->encoding = self::ENCODING_UTF_8;
                    }
                }
                if (strpos($meta->getAttribute('content'), 'application/xhtml+xml') !== false) {
                    $properXhtml = true;
                }
                break;
            }
        }
        if (($encoding = $cfg['force_encoding']) === false) {
            if ($this->doc->actualEncoding) {
                $encoding = $this->doc->actualEncoding;
            } elseif ($this->doc->encoding) {
                $encoding = $this->doc->encoding;
            } else {
                $encoding = $this->doc->encoding = self::ENCODING_UTF_8;
            }
        } else {
            $this->doc->encoding = $encoding;
        }
        $encoding = strtolower($encoding);
        $utf8 = $encoding == self::ENCODING_UTF_8;
        if (!$utf8 && $encoding != self::ENCODING_ISO_8859_1 && !function_exists('iconv')) {
            throw new AgaviException('No iconv module available, input encoding "' . $encoding . '" cannot be handled.');
        }
        $base = $this->xpath->query(sprintf('/%1$shtml/%1$shead/%1$sbase[@href]', $this->xmlnsPrefix));
        if ($base->length) {
            $baseHref = $base->item(0)->getAttribute('href');
        } else {
            $baseHref = $rq->getUrl();
        }
        $baseHref = substr($baseHref, 0, strrpos($baseHref, '/') + 1);
        $forms = array();
        if (is_array($populate)) {
            $query = array();
            foreach (array_keys($populate) as $id) {
                if (is_string($id)) {
                    $query[] = sprintf('@id="%s"', $id);
                }
            }
            if ($query) {
                $forms = $this->xpath->query(sprintf('//%1$sform[%2$s]', $this->xmlnsPrefix, implode(' or ', $query)));
            }
        } else {
            $forms = $this->xpath->query(sprintf('//%1$sform[@action]', $this->xmlnsPrefix));
        }
        // an array of all validation incidents; errors inserted for fields or multiple fields will be removed in here
        $allIncidents = $vr->getIncidents();
        foreach ($forms as $form) {
            if ($populate instanceof AgaviParameterHolder) {
                $action = preg_replace('/#.*$/', '', trim($form->getAttribute('action')));
                if (!($action == $rurl || strpos($action, '/') === 0 && preg_replace(array('#/\\./#', '#/\\.$#', '#[^\\./]+/\\.\\.(/|\\z)#', '#/{2,}#'), array('/', '/', '', '/'), $action) == $ruri || $baseHref . preg_replace(array('#/\\./#', '#/\\.$#', '#[^\\./]+/\\.\\.(/|\\z)#', '#/{2,}#'), array('/', '/', '', '/'), $action) == $rurl)) {
                    continue;
                }
                $p = $populate;
            } else {
                if (isset($populate[$form->getAttribute('id')])) {
                    if ($populate[$form->getAttribute('id')] instanceof AgaviParameterHolder) {
                        $p = $populate[$form->getAttribute('id')];
                    } elseif ($populate[$form->getAttribute('id')] === true) {
                        $p = $rq->getRequestData();
                    } else {
                        continue;
                    }
                } else {
                    continue;
                }
            }
            // our array for remembering foo[] field's indices
            $remember = array();
            // build the XPath query
            // we select descendants of the given form
            // as well as any element in the document associated with the form using a "form" attribute that contains the ID of the current form
            // provided they match the following criteria:
            // * <textarea> with a "name" attribute
            // * <select> with a "name" attribute
            // * <button type="submit"> with a "name" attribute
            // * <input> with a "name" attribute except for the following:
            //  * <input type="checkbox"> elements with a "name" attribute that contains the character sequence "[]" and no "value" attribute
            //  * <input type="hidden"> unless config option "include_hidden_inputs" is true (defaults to true)
            $query = sprintf('
				descendant::%1$stextarea[@name] |
				descendant::%1$sselect[@name] |
				descendant::%1$sbutton[@name and @type="submit"] |
				descendant::%1$sinput[@name and (not(@type="checkbox") or (not(contains(@name, "[]")) or (contains(@name, "[]") and @value)))]', $this->xmlnsPrefix);
            if (($formId = $form->hasAttribute('id')) != "") {
                // find elements associated with this form as well
                $query .= sprintf(' |
					//%1$stextarea[@form="%2$s" and @name] |
					//%1$sselect[@form="%2$s" and @name] |
					//%1$sbutton[@form="%2$s" and @name and @type="submit"] |
					//%1$sinput[@form="%2$s" and @name and (not(@type="checkbox") or (not(contains(@name, "[]")) or (contains(@name, "[]") and @value)))]', $this->xmlnsPrefix, $formId);
            }
            foreach ($this->xpath->query($query, $form) as $element) {
                $pname = $name = $element->getAttribute('name');
                $multiple = $element->nodeName == 'select' && $element->hasAttribute('multiple');
                $checkValue = false;
                if ($element->getAttribute('type') == 'checkbox' || $element->getAttribute('type') == 'radio') {
                    if (($pos = strpos($pname, '[]')) && $pos + 2 != strlen($pname)) {
                        // foo[][3] checkboxes etc not possible, [] must occur only once and at the end
                        continue;
                    } elseif ($pos !== false) {
                        $checkValue = true;
                        $pname = substr($pname, 0, $pos);
                    }
                }
                if (preg_match_all('/([^\\[]+)?(?:\\[([^\\]]*)\\])/', $pname, $matches)) {
                    $pname = $matches[1][0];
                    if ($multiple) {
                        $count = count($matches[2]) - 1;
                    } else {
                        $count = count($matches[2]);
                    }
                    for ($i = 0; $i < $count; $i++) {
                        $val = $matches[2][$i];
                        if ((string) $matches[2][$i] === (string) (int) $matches[2][$i]) {
                            $val = (int) $val;
                        }
                        if (!isset($remember[$pname])) {
                            $add = $val !== "" ? $val : 0;
                            if (is_int($add)) {
                                $remember[$pname] = $add;
                            }
                        } else {
                            if ($val !== "") {
                                $add = $val;
                                if (is_int($val) && $add > $remember[$pname]) {
                                    $remember[$pname] = $add;
                                }
                            } else {
                                $add = ++$remember[$pname];
                            }
                        }
                        $pname .= '[' . $add . ']';
                    }
                }
                if (!$utf8) {
                    $pname = $this->fromUtf8($pname, $encoding);
                }
                if ($skip !== null && preg_match($skip, $pname . ($checkValue ? '[]' : ''))) {
                    // skip field
                    continue;
                }
                $argument = new AgaviValidationArgument($pname, $element->nodeName == 'input' && $element->getAttribute('type') == 'file' ? AgaviWebRequestDataHolder::SOURCE_FILES : AgaviRequestDataHolder::SOURCE_PARAMETERS);
                // there's an error with the element's name in the request? good. let's give the baby a class!
                if ($vr->getAuthoritativeArgumentSeverity($argument) > AgaviValidator::SILENT) {
                    // a collection of all elements that need an error class
                    $errorClassElements = array();
                    // the element itself of course
                    $errorClassElements[] = $element;
                    // all implicit labels
                    foreach ($this->xpath->query(sprintf('ancestor::%1$slabel[not(@for)]', $this->xmlnsPrefix), $element) as $label) {
                        $errorClassElements[] = $label;
                    }
                    // and all explicit labels
                    if (($id = $element->getAttribute('id')) != '') {
                        // we use // and not descendant: because it doesn't have to be a child of the form element
                        foreach ($this->xpath->query(sprintf('//%1$slabel[@for="%2$s"]', $this->xmlnsPrefix, $id), $form) as $label) {
                            $errorClassElements[] = $label;
                        }
                    }
                    // now loop over all those elements and assign the class
                    foreach ($errorClassElements as $errorClassElement) {
                        // go over all the elements in the error class map
                        foreach ($cfg['error_class_map'] as $xpathExpression => $errorClassName) {
                            // evaluate each xpath expression
                            $errorClassResults = $this->xpath->query(AgaviToolkit::expandVariables($xpathExpression, array('htmlnsPrefix' => $this->xmlnsPrefix)), $errorClassElement);
                            if ($errorClassResults && $errorClassResults->length) {
                                // we have results. the xpath expressions are used to locale the actual elements we set the error class on - doesn't necessarily have to be the erroneous element or the label!
                                foreach ($errorClassResults as $errorClassDestinationElement) {
                                    $errorClassDestinationElement->setAttribute('class', preg_replace('/\\s*$/', ' ' . $errorClassName, $errorClassDestinationElement->getAttribute('class')));
                                }
                                // and break the foreach, our expression matched after all - no need to look further
                                break;
                            }
                        }
                    }
                    // up next: the error messages
                    $fieldIncidents = array();
                    $multiFieldIncidents = array();
                    // grab all incidents for this field
                    foreach ($vr->byArgument($argument)->getIncidents() as $incident) {
                        if (($incidentKey = array_search($incident, $allIncidents, true)) !== false) {
                            // does this one have more than one field?
                            // and is it really more than one parameter or file, not a cookie or header?
                            $incidentArgumentCount = 0;
                            $incidentArguments = $incident->getArguments();
                            foreach ($incidentArguments as $incidentArgument) {
                                if (in_array($incidentArgument->getSource(), array(AgaviWebRequestDataHolder::SOURCE_FILES, AgaviRequestDataHolder::SOURCE_PARAMETERS))) {
                                    $incidentArgumentCount++;
                                }
                            }
                            if ($incidentArgumentCount > 1) {
                                $multiFieldIncidents[] = $incident;
                            } else {
                                $fieldIncidents[] = $incident;
                            }
                            // remove it from the list of all incidents
                            unset($allIncidents[$incidentKey]);
                        }
                    }
                    // 1) insert error messages that are specific to this field
                    if (!$this->insertErrorMessages($element, $fieldErrorMessageRules, $fieldIncidents)) {
                        $allIncidents = array_merge($allIncidents, $fieldIncidents);
                    }
                    // 2) insert error messages that belong to multiple fields (including this one), if that message was not inserted before
                    if (!$this->insertErrorMessages($element, $multiFieldErrorMessageRules, $multiFieldIncidents)) {
                        $allIncidents = array_merge($allIncidents, $multiFieldIncidents);
                    }
                }
                // FPF only handles "normal" values, as file inputs cannot be re-populated, so getParameter() with no source-specific stuff is fine here
                $value = $p->getParameter($pname);
                if (is_array($value) && !($element->nodeName == 'select' || $checkValue)) {
                    // name didn't match exactly. skip.
                    continue;
                }
                if (is_bool($value)) {
                    $value = (string) (int) $value;
                } elseif (!$utf8) {
                    $value = $this->toUtf8($value, $encoding);
                } else {
                    if (is_array($value)) {
                        $value = array_map('strval', $value);
                    } else {
                        $value = (string) $value;
                    }
                }
                if ($element->nodeName == 'input') {
                    $inputType = $element->getAttribute('type');
                    if ($inputType == 'checkbox' || $inputType == 'radio') {
                        // checkboxes and radios
                        $element->removeAttribute('checked');
                        if ($checkValue && is_array($value)) {
                            $eValue = $element->getAttribute('value');
                            if (!$utf8) {
                                $eValue = $this->fromUtf8($eValue, $encoding);
                            }
                            if (!in_array($eValue, $value)) {
                                continue;
                            } else {
                                $element->setAttribute('checked', 'checked');
                            }
                        } elseif ($p->hasParameter($pname) && ($element->hasAttribute('value') && $element->getAttribute('value') == $value || !$element->hasAttribute('value') && $p->getParameter($pname))) {
                            $element->setAttribute('checked', 'checked');
                        }
                    } elseif ($inputType != 'button' && $inputType != 'submit') {
                        // everything else
                        // unless "include_hidden_inputs" is false and it's a hidden input...
                        if ($cfg['include_hidden_inputs'] || $inputType != 'hidden') {
                            // remove original value
                            $element->removeAttribute('value');
                            // and set a new one if it's there and unless it's a password field (or we actually want to refill those)
                            if ($p->hasParameter($pname) && ($cfg['include_password_inputs'] || $inputType != 'password')) {
                                $element->setAttribute('value', $value);
                            }
                        }
                    }
                } elseif ($element->nodeName == 'select') {
                    // select elements
                    // yes, we still use XPath because there could be OPTGROUPs
                    foreach ($this->xpath->query(sprintf('descendant::%1$soption', $this->xmlnsPrefix), $element) as $option) {
                        $option->removeAttribute('selected');
                        if ($p->hasParameter($pname) && ($option->getAttribute('value') === $value || $multiple && is_array($value) && in_array($option->getAttribute('value'), $value))) {
                            $option->setAttribute('selected', 'selected');
                        }
                    }
                } elseif ($element->nodeName == 'textarea') {
                    // textareas
                    foreach ($element->childNodes as $cn) {
                        // remove all child nodes (= text nodes)
                        $element->removeChild($cn);
                    }
                    // append a new text node
                    if ($xhtml && $properXhtml) {
                        $element->appendChild($this->doc->createCDATASection($value));
                    } else {
                        $element->appendChild($this->doc->createTextNode($value));
                    }
                }
            }
            // now output the remaining incidents
            // might include errors for cookies, headers and whatnot, but that is okay
            if ($this->insertErrorMessages($form, $errorMessageRules, $allIncidents)) {
                $allIncidents = array();
            }
        }
        $rq->setAttribute('orphaned_errors', $allIncidents, 'org.agavi.filter.FormPopulationFilter');
        if ($xhtml) {
            $firstError = null;
            if (!$cfg['parse_xhtml_as_xml']) {
                // workaround for a bug in dom or something that results in two xmlns attributes being generated for the <html> element
                // attributes must be removed and created again
                // and don't change the DOMNodeList in the foreach!
                $remove = array();
                $reset = array();
                foreach ($this->doc->documentElement->attributes as $attribute) {
                    // remember to remove the node
                    $remove[] = $attribute;
                    // not for the xmlns attribute itself
                    if ($attribute->nodeName != 'xmlns') {
                        // can't do $attribute->prefix. we're in HTML parsing mode, remember? even if there is a prefix, the attribute node will not have a namespace
                        $attributeNameParts = explode(':', $attribute->nodeName);
                        if (isset($attributeNameParts[1])) {
                            // it's a namespaced node
                            $attributeNamespaceUri = $attribute->parentNode->lookupNamespaceURI($attributeNameParts[0]);
                            if ($attributeNamespaceUri) {
                                // it is an attribute, for which the namespace is known internally (even though we're in HTML mode), typically xml: or xmlns:.
                                // so we need to create a new node, in the right namespace
                                $attributeCopy = $this->doc->createAttributeNS($attributeNamespaceUri, $attribute->nodeName);
                            } else {
                                // it's a foo:bar node - just copy it over
                                $attributeCopy = $attribute;
                            }
                        } else {
                            // no namespace on this node, copy it
                            $attributeCopy = $attribute;
                        }
                        // don't forget the attribute value
                        $attributeCopy->nodeValue = $attribute->nodeValue;
                        // and remember to set this attribute later
                        $reset[] = $attributeCopy;
                    }
                }
                foreach ($remove as $attribute) {
                    $this->doc->documentElement->removeAttributeNode($attribute);
                }
                foreach ($reset as $attribute) {
                    $this->doc->documentElement->setAttributeNode($attribute);
                }
            }
            if (strpos(PHP_VERSION, '5.2.6') === 0) {
                // check like this so 5.2.6-0.dotdeb.yourmom is also matched
                // PHP 5.2.6 does not accept null as the first argument to saveXML()
                // as a workaround, the whole document can be passed, but then it is saved as UTF-8, no matter what, so that won't work for other charsets
                if (!$cfg['savexml_options']) {
                    $out = $this->doc->saveXML();
                } elseif ($utf8) {
                    $out = $this->doc->saveXML($this->doc, $cfg['savexml_options']);
                } else {
                    throw new AgaviException("On systems running PHP version 5.2.6, the parameter 'savexml_options' cannot be used in combination with input documents that have a character set other than UTF-8. Please see the following tickets for details:\n\n- http://trac.agavi.org/ticket/1372\n- http://trac.agavi.org/ticket/1279\n- http://bugs.php.net/46191\n- http://trac.agavi.org/ticket/1262");
                }
            } else {
                $out = $this->doc->saveXML(null, $cfg['savexml_options']);
            }
            if ((!$cfg['parse_xhtml_as_xml'] || !$properXhtml) && $cfg['cdata_fix']) {
                // these are ugly fixes so inline style and script blocks still work. better don't use them with XHTML to avoid trouble
                // http://www.456bereastreet.com/archive/200501/the_perils_of_using_xhtml_properly/
                // http://www.hixie.ch/advocacy/xhtml
                $out = preg_replace('/<style([^>]*)>\\s*<!\\[CDATA\\[\\s*?/iU' . ($utf8 ? 'u' : ''), '<style$1><!--/*--><![CDATA[/*><!--*/' . "\n", $out);
                if (!$firstError) {
                    $firstError = preg_last_error();
                }
                // we can't clean up whitespace before the closing element because a preg with a leading \s* expression would be horribly slow
                $out = preg_replace('/\\]\\]>\\s*<\\/style>/iU' . ($utf8 ? 'u' : ''), "\n" . '/*]]>*/--></style>', $out);
                if (!$firstError) {
                    $firstError = preg_last_error();
                }
                $out = preg_replace('/<script([^>]*)>\\s*<!\\[CDATA\\[\\s*?/iU' . ($utf8 ? 'u' : ''), '<script$1><!--//--><![CDATA[//><!--' . "\n", $out);
                if (!$firstError) {
                    $firstError = preg_last_error();
                }
                // we can't clean up whitespace before the closing element because a preg with a leading \s* expression would be horribly slow
                $out = preg_replace('/\\]\\]>\\s*<\\/script>/iU' . ($utf8 ? 'u' : ''), "\n" . '//--><!]]></script>', $out);
                if (!$firstError) {
                    $firstError = preg_last_error();
                }
            }
            if ($cfg['remove_auto_xml_prolog'] && !$hasXmlProlog) {
                // there was no xml prolog in the document before, so we remove the one generated by DOM now
                $out = preg_replace('/<\\?xml.*?\\?>\\s+/iU' . ($utf8 ? 'u' : ''), '', $out);
                if (!$firstError) {
                    $firstError = preg_last_error();
                }
            } elseif (!$cfg['parse_xhtml_as_xml']) {
                // yes, DOM sucks and inserts another XML prolog _after_ the DOCTYPE... and it has two question marks at the end, not one, don't ask me why
                $out = preg_replace('/<\\?xml.*?\\?\\?>\\s+/iU' . ($utf8 ? 'u' : ''), '', $out);
                if (!$firstError) {
                    $firstError = preg_last_error();
                }
            }
            if ($firstError) {
                $error = "Form Population Filter encountered an error while performing final regular expression replaces on the output.\n";
                // the preg_replaces failed and produced an empty string. let's find out why
                $error .= "The error reported by preg_last_error() indicates that ";
                switch ($firstError) {
                    case PREG_BAD_UTF8_ERROR:
                        $error .= "the input contained malformed UTF-8 data.";
                        break;
                    case PREG_RECURSION_LIMIT_ERROR:
                        $error .= "the recursion limit (defined by \"pcre.recursion_limit\") was hit. This shouldn't happen unless you changed that limit yourself in php.ini or using ini_set(). If the problem is not on your end, please file a bug report with a reproduce case on the Agavi issue tracker or drop by on the IRC support channel.";
                        break;
                    case PREG_BACKTRACK_LIMIT_ERROR:
                        $error .= "the backtrack limit (defined by \"pcre.backtrack_limit\") was hit. This shouldn't happen unless you changed that limit yourself in php.ini or using ini_set(). If the problem is not on your end, please file a bug report with a reproduce case on the Agavi issue tracker or drop by on the IRC support channel.";
                        break;
                    case PREG_INTERNAL_ERROR:
                    default:
                        $error .= "an internal PCRE error occurred. As a quick countermeasure, try to upgrade PHP (and the bundled PCRE) as well as libxml (yes!) to the latest versions to see if the problem goes away. If the issue persists, file a bug report with a reproduce case on the Agavi issue tracker or drop by on the IRC support channel.";
                }
                throw new AgaviException($error);
            }
            $response->setContent($out);
        } else {
            $response->setContent($this->doc->saveHTML());
        }
        unset($this->xpath);
        unset($this->doc);
    }
 /**
  * @param string $content
  * @param \AgaviRequestDataHolder|array $parameters
  * @param \AgaviValidationManager $validationManager
  * @param array $config
  * @return string
  */
 protected function executeFormPopulationFilter($content, $parameters, $validationManager = null, array $config = array())
 {
     $container = $this->_context->getController()->createExecutionContainer('FilterTests', 'FormPopulationFilter');
     $container->getResponse()->setContent($content);
     if ($parameters instanceof AgaviRequestDataHolder) {
         $rd = $parameters;
     } else {
         $rd = new AgaviRequestDataHolder(array(AgaviRequestDataHolder::SOURCE_PARAMETERS => $parameters));
     }
     if ($validationManager) {
         $validationManager->execute($rd);
     }
     $fpf = new AgaviFormPopulationFilter();
     $fpf->initialize($this->_context, array_merge(array('populate' => $rd, 'validation_report' => $validationManager ? $validationManager->getReport() : null, 'force_request_uri' => '/'), $config));
     $filterChain = new AgaviFilterChain();
     $filterChain->initialize($this->_context);
     $fpf->execute($filterChain, $container);
     return $container->getResponse()->getContent();
 }
Пример #9
0
 /**
  * The default "execute" method, which just calls continues in the chain.
  *
  * @param      AgaviFilterChain        A FilterChain instance.
  * @param      AgaviExecutionContainer The current execution container.
  *
  * @author     David Zülke <*****@*****.**>
  * @since      0.11.0
  */
 public function execute(AgaviFilterChain $filterChain, AgaviExecutionContainer $container)
 {
     $filterChain->execute($container);
 }
Пример #10
0
 /**
  * Load filters.
  *
  * @param      AgaviFilterChain A FilterChain instance.
  * @param      string           "global" or "action".
  * @param      string           A module name, or "*" for the generic config.
  *
  * @author     David Zülke <*****@*****.**>
  * @since      0.11.0
  */
 public function loadFilters(AgaviFilterChain $filterChain, $which = 'global', $module = null)
 {
     if ($module === null) {
         $module = '*';
     }
     if ($which != 'global' && !isset($this->filters[$which][$module]) || $which == 'global' && $this->filters[$which] == null) {
         if ($which == 'global') {
             $this->filters[$which] = array();
             $filters =& $this->filters[$which];
         } else {
             $this->filters[$which][$module] = array();
             $filters =& $this->filters[$which][$module];
         }
         $config = ($module == '*' ? AgaviConfig::get('core.config_dir') : AgaviConfig::get('core.module_dir') . '/' . $module . '/config') . '/' . $which . '_filters.xml';
         if (is_readable($config)) {
             require AgaviConfigCache::checkConfig($config, $this->context->getName());
         }
     } else {
         if ($which == 'global') {
             $filters =& $this->filters[$which];
         } else {
             $filters =& $this->filters[$which][$module];
         }
     }
     foreach ($filters as $name => $filter) {
         $filterChain->register($filter, $name);
     }
 }