/** * Checks encoding, normalizes whitespace/punctuation, and sets the name string. * * @param String $str a utf8-encoding string. * @return Bool True on success */ public function setStr($str) { if (!drupal_validate_utf8($str)) { throw new Exception("Name is not encoded in UTF-8"); } $this->str = $str; $this->norm(); return true; }
/** * Make sure our query matches the pattern name:value or name:"value" * Make sure that if we are ranges we use name:[ AND ] * allowed inputs : * a. bundle:article * b. date:[1970-12-31T23:59:59Z TO NOW] * Split the text in 4 different parts * 1. name, eg.: bundle or date * 2. The first opening bracket (or nothing), eg.: [ * 3. The value of the field, eg. article or 1970-12-31T23:59:59Z TO NOW * 4. The last closing bracket, eg.: ] * @param string $filter * The filter to validate * @return boolean */ public static function validFilterValue($filter) { $name = NULL; $value = NULL; $matches = array(); $datefields = array(); $datefield_match = array(); if (preg_match('/(?P<name>[^:]+):(?P<value>.+)?$/', $filter, $matches)) { foreach ($matches as $match_id => $match) { switch ($match_id) { case 'name': $name = $match; break; case 'value': $value = $match; break; } } // For the name we allow any character that fits between the A-Z0-9 range and // any alternative for this in other languages. No special characters allowed. // Negative filters may have a leading "-". if (!preg_match('/^-?[a-zA-Z0-9_\\x7f-\\xff]+$/', $name)) { return FALSE; } // For the value we allow anything that is UTF8 if (!drupal_validate_utf8($value)) { return FALSE; } // Check our bracket count. If it does not match it is also not valid $valid_brackets = TRUE; $brackets['opening']['{'] = substr_count($value, '{'); $brackets['closing']['}'] = substr_count($value, '}'); $valid_brackets = $valid_brackets && $brackets['opening']['{'] == $brackets['closing']['}']; $brackets['opening']['['] = substr_count($value, '['); $brackets['closing'][']'] = substr_count($value, ']'); $valid_brackets = $valid_brackets && $brackets['opening']['['] == $brackets['closing'][']']; $brackets['opening']['('] = substr_count($value, '('); $brackets['closing'][')'] = substr_count($value, ')'); $valid_brackets = $valid_brackets && $brackets['opening']['('] == $brackets['closing'][')']; if (!$valid_brackets) { return FALSE; } // Check the date field inputs if (preg_match('/\\[(.+) TO (.+)\\]$/', $value, $datefields)) { // Only Allow a value in the form of // http://lucene.apache.org/solr/api/org/apache/solr/schema/DateField.html // http://lucene.apache.org/solr/api/org/apache/solr/util/DateMathParser.html // http://wiki.apache.org/solr/SolrQuerySyntax // 1976-03-06T23:59:59.999Z (valid) // * (valid) // 1995-12-31T23:59:59.999Z (valid) // 2007-03-06T00:00:00Z (valid) // NOW-1YEAR/DAY (valid) // NOW/DAY+1DAY (valid) // 1976-03-06T23:59:59.999Z (valid) // 1976-03-06T23:59:59.999Z+1YEAR (valid) // 1976-03-06T23:59:59.999Z/YEAR (valid) // 1976-03-06T23:59:59.999Z (valid) // 1976-03-06T23::59::59.999Z (invalid) if (!empty($datefields[1]) && !empty($datefields[2])) { // Do not check to full value, only the splitted ones unset($datefields[0]); // Check if both matches are valid datefields foreach ($datefields as $datefield) { if (!preg_match('/(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:[\\d\\.]{2,6}Z(\\S)*)|(^([A-Z\\*]+)(\\A-Z0-9\\+\\-\\/)*)/', $datefield, $datefield_match)) { return FALSE; } } } } } return TRUE; }
/** * Helper function to reformat fields where required. * * Some values (lat/lon) break down into structures, not strings. * Dates should be parsed nicely. */ function _reformat($data) { // Make the key lowercase as field names must be. $data = array_change_key_case($data, CASE_LOWER); foreach ($data as $key => &$value) { if (is_array($value)) { $value = array_change_key_case($value, CASE_LOWER); switch ($key) { // GPS values case 'gps_latitude': case 'gps_longitude': case 'gpslatitude': case 'gpslongitude': $value = $this->_exif_reformat_DMS2D($value, $data[$key . 'ref']); break; } } else { if (!drupal_validate_utf8($value)) { $value = utf8_encode($value); } switch ($key) { // String values. case 'usercomment': if ($this->startswith($value, 'UNICODE')) { $value = substr($value, 8); } break; // Date values. // Date values. case 'filedatetime': $value = date('c', $value); break; case 'datetimeoriginal': case 'datetime': case 'datetimedigitized': // In case we get a datefield, we need to reformat it to the ISO 8601 standard: // which will look something like 2004-02-12T15:19:21 $date_time = explode(" ", $value); $date_time[0] = str_replace(":", "-", $date_time[0]); if (variable_get('exif_granularity', 0) == 1) { $date_time[1] = "00:00:00"; } $value = implode("T", $date_time); break; // GPS values. // GPS values. case 'gpsaltitude': case 'gpsimgdirection': $value = $this->_exif_reformat_DMS2D($value, $data[$key . 'ref']); break; // Flash values. // Flash values. case 'flash': $flash_descriptions = $this->getFlashDescriptions(); if (isset($flash_descriptions[$value])) { $value = $flash_descriptions[$value]; } break; // Exposure values. // Exposure values. case 'exposuretime': if (strpos($value, '/') !== FALSE) { $value = $this->_normalise_fraction($value) . 's'; } break; // Focal Length values. // Focal Length values. case 'focallength': if (strpos($value, '/') !== FALSE) { $value = $this->_normalise_fraction($value) . 'mm'; } break; } } } return $data; }
/** * {@inheritdoc} */ public function set($cid, $data, $expire = CACHE_PERMANENT) { $scalar = is_scalar($data); $entry = array('_id' => (string) $cid, 'cid' => (string) $cid, 'created' => REQUEST_TIME, 'expire' => $expire, 'serialized' => !$scalar, 'data' => $scalar ? $data : serialize($data)); // Use MongoBinData for non-UTF8 strings. if (is_string($entry['data']) && !drupal_validate_utf8($entry['data'])) { $entry['data'] = $this->createBinData($entry['data']); } try { $this->collection->save($entry, $this->unsafe); } catch (\Exception $e) { // The database may not be available, so we'll ignore cache_set requests. } }