def disable(plugin_list_): """ Disable a given set of plugins. @param plugin_list An array of plugin names. """ invoke_plugins = [] for plugin_ in plugin_list_: if (plugin_exists(plugin_)): # Check if node_access table needs rebuilding. if (not node_access_needs_rebuild() and plugin_hook(plugin_, \ 'node_grants')): node_access_needs_rebuild(True) plugin_load_install(plugin_) plugin_invoke(plugin_, 'disable') db_query(\ "UPDATE {system} SET status = %d " + \ "WHERE type = '%s' AND name = '%s'", 0, 'plugin', plugin_) invoke_plugins.append(plugin) if (not php.empty(invoke_plugins)): # Refresh the plugin list to exclude the disabled plugins. plugin_list(True, False) # Force to regenerate the stored list of hook implementations. registry_rebuild() # If there remains no more node_access plugin, rebuilding will be # straightforward, we can do it right now. if (node_access_needs_rebuild() and \ php.count(plugin_implements('node_grants')) == 0): node_access_rebuild()
def invoke_all(*args): """ Invoke a hook in all enabled plugins that implement it. @param hook The name of the hook to invoke. @param ... Arguments to pass to the hook. @return An array of return values of the hook implementations. If plugins return arrays from their implementations, those are merged into one array. """ global plugins args = list(args) hook = 'hook_%s' % args[0] del (args[0]) return_ = [] for plugin_ in implements(hook): if (lib_bootstrap.drupal_function_exists(hook, plugins[plugin_])): function = DrupyImport.getFunction(\ plugins[plugin_], hook) result = php.call_user_func_array(function, args) if (result is not None and php.is_array(result)): return_ = p.array_merge_recursive(return_, result) elif (result is not None): return_.append(result) return return_
def update_page(content, show_messages=True): """ Generate a themed update page. Note: this function is not themeable. @param content The page content to show. @param show_messages Whether to output status and error messages. False can be useful to postpone the messages to a subsequent page. """ # Set required headers. drupal_set_header('Content-Type: text/html; charset=utf-8') # Assign content and show message flag. variables['content'] = content variables['show_messages'] = show_messages # The maintenance preprocess function is recycled here. template_preprocess_maintenance_page(variables) # Special handling of warning messages. messages = drupal_set_message() if (php.isset(messages['warning'])): title = ('The following update warnings should be carefully ' + \ 'reviewed before continuing' if \ (php.count(messages['warning']) > 1) else \ 'The following update warning should be carefully ' + \ 'reviewed before continuing') variables['messages'] += '<h4>' + title + ':</h4>' variables['messages'] += theme('status_messages', 'warning') # This was called as a theme hook (not template), so we need to # fix path_to_theme() for the template, to point at the actual # theme rather than system plugin as owner of the hook. lib_appglobals.theme_path = 'themes/garland' return theme_render_template('themes/garland/maintenance-page.tpl.php', \ variables)
def language_list(field="language", reset=False): """ Get a list of languages set up indexed by the specified key @param field The field to index the list with. @param reset Boolean to request a reset of the list. """ php.static(language_list, "languages") # Reset language list if reset: languages_list.languages = {} # Init language list if languages_list.languages == None: if variable_get("language_count", 1) > 1 or plugin_exists("locale"): result = db_query("SELECT# FROM {languages} ORDER BY weight ASC, name ASC") while True: row = db_fetch_object(result) if row == None: break languages_list.languages["language"][row.language] = row else: # No locale plugin, so use the default language only. default_ = language_default() languages_list.languages["language"][default_.language] = default_ # Return the array indexed by the right field if not php.isset(languages_list.languages, field): languages_list.languages[field] = {} for lang in languages_list.languages["language"]: # Some values should be collected into an array if php.in_array(field, ["enabled", "weight"]): languages_list.languages[field][lang.field][lang.language] = lang else: languages_list.languages[field][lang.field] = lang return languages_list.languages[field]
def drupal_set_message(message=None, type="status", repeat=True): """ Set a message which reflects the status of the performed operation. If the def is called with no arguments, this def returns all set messages without clearing them. @param message The message should begin with a capital letter and always ends with a period '.'. @param type The type of the message. One of the following values are possible: - 'status' - 'warning' - 'error' @param repeat If this is FALSE and the message is already set, then the message won't be repeated. """ if message: if not php.isset(php.SESSION, "messages"): php.SESSION["messages"] = {} if not php.isset(php.SESSION["messages"], type): php.SESSION["messages"][type] = [] if repeat or not php.in_array(message, php.SESSION["messages"][type]): php.SESSION["messages"][type].append(message) # messages not set when DB connection fails return php.SESSION["messages"] if php.isset(php.SESSION, "messages") else None
def check_location(source, directory=''): """ Check if a file is really located inside directory + Should be used to make sure a file specified is really located within the directory to prevent exploits. @code // Returns False: file_check_location('/www/example.com/files/../../../etc/passwd', \ '/www/example.com/files') @endcode @param source A string set to the file to check. @param directory A string where the file should be located. @return FALSE for invalid path or the real path of the source. """ check = realpath(source) if (check): source = check else: # This file does not yet exist source = realpath(php.dirname(source)) + '/' + basename(source) directory = realpath(directory) if (directory and php.strpos(source, directory) != 0): return False return source
def create_filename(basename, directory): """ Create a full file path from a directory and filename + If a file with the specified name already exists, an alternative will be used. @param basename string filename @param directory string directory @return """ dest = directory + '/' + basename if (php.file_exists(dest)): # Destination file already exists, generate an alternative. pos = strrpos(basename, '.') if (pos): name = php.substr(basename, 0, pos) ext = php.substr(basename, pos) else: name = basename counter = 0 while True: dest = directory + '/' + name + '_' + counter + ext counter += 1 if (not php.file_exists(dest)): break return dest
def drupal_get_messages(type=None, clear_queue=True): """ Return all messages that have been set. @param type (optional) Only return messages of this type. @param clear_queue (optional) Set to FALSE if you do not want to clear the messages queue @return An associative array, the key is the message type, the value an array of messages. If the type parameter is passed, you get only that type, or an empty array if there are no such messages. If type is not passed, all message types are returned, or an empty array if none exist. """ messages = drupal_set_message() if not php.empty("messages"): if type != None and type != False: if clear_queue: del (php.SESSION["messages"][type]) if php.isset(messages, type): return {type: messages[type]} else: if clear_queue: del (php.SESSION["messages"]) return messages return {}
def arg(index = None, path = None): """ Return a component of the current Drupal path. When viewing a page at the path "admin/build/types", for example, arg(0) would return "admin", arg(1) would return "content", and arg(2) would return "types". Avoid use of this function where possible, as resulting code is hard to read. Instead, attempt to use named arguments in menu callback functions. See the explanation in menu.inc for how to construct callbacks that take arguments. @param index The index of the component, where each component is separated by a '/' (forward-slash), and where the first component has an index of 0 (zero). @return The component specified by index, or NULL if the specified component was not found. """ php.static(arg, 'arguments', {}) if (path is None): path = php.GET['q']; if (not php.isset(arg.arguments, path)): arg.arguments[path] = php.explode('/', path); if (index is None): return arg.arguments[path]; if (php.isset(arg.arguments[path], index)): return arg.arguments[path][index];
def registry_cache_path_files(): """ Save the files required by the registry for this path. """ used_code = registry_mark_code(None, None, True) if (used_code): files = [] type_sql = [] params = [] for type, names in used_code.items(): type_sql.append( "(name IN (" + db_placeholders(names, 'varchar') + \ ") AND type = '%s')" ) params = php.array_merge(params, names) params.append(type) res = db_query("SELECT DISTINCT filename FROM {registry} WHERE " + \ php.implode(' OR ', type_sql), params) while True: row = db_fetch_object(res) if (row == None): break files.append(row.filename) if (files): sort(files) # Only write this to cache if the file list we are going to cache # is different to what we loaded earlier in the request. if (files != registry_load_path_files(True)): menu = menu_get_item() cache_set('registry:' + menu['path'], php.implode(';', files), \ 'cache_registry')
def drupal_validate_utf8(text): """ Checks whether a string is valid UTF-8. All functions designed to filter input should use drupal_validate_utf8 to ensure they operate on valid UTF-8 strings to prevent bypass of the filter. When text containing an invalid UTF-8 lead byte (0xC0 - 0xFF) is presented as UTF-8 to Internet Explorer 6, the program may misinterpret subsequent bytes. When these subsequent bytes are HTML control characters such as quotes or angle brackets, parts of the text that were deemed safe by filters end up in locations that are potentially unsafe; An onerror attribute that is outside of a tag, and thus deemed safe by a filter, can be interpreted by the browser as if it were inside the tag. This def exploits preg_match behaviour (since PHP 4.3.5) when used with the u modifier, as a fast way to find invalid UTF-8. When the matched string contains an invalid byte sequence, it will fail silently. preg_match may not fail on 4 and 5 octet sequences, even though they are not supported by the specification. The specific preg_match behaviour is present since PHP 4.3.5. @param text The text to check. @return TRUE if the text is valid UTF-8, FALSE if not. """ if php.strlen(text) == 0: return True return php.preg_match("/^./us", text) == 1
def destination(destination, replace): """ Determines the destination path for a file depending on how replacement of existing files should be handled. @param destination A string specifying the desired path. @param replace Replace behavior when the destination file already exists. - FILE_EXISTS_REPLACE - Replace the existing file - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is unique - FILE_EXISTS_ERROR - Do nothing and return False. @return The destination file path or False if the file already exists and FILE_EXISTS_ERROR was specified. """ if (php.file_exists(destination)): if replace == FILE_EXISTS_RENAME: basename = basename(destination) directory = php.dirname(destination) destination = file_create_filename(basename, directory) elif replace == FILE_EXISTS_ERROR: drupal_set_message(t('The selected file %file could not be copied, \ because a file by that name already exists in the destination.', \ {'%file' : destination}), 'error') return False return destination
def drupal_load(type_, name): """ Includes a file with the provided type and name. This prevents including a theme, engine, plugin, etc., more than once. @param type The type of item to load (i.e. theme, theme_engine, plugin). @param name The name of the item to load. @return TRUE if the item is loaded or has already been loaded. """ php.static(drupal_load, 'files', {}) if (not php.isset(drupal_load.files, type)): drupal_load.files[type_] = {} if (php.isset(drupal_load.files[type_], name)): return True else: filename = drupal_get_filename(type_, name) if (filename != False): lib_plugin.plugins[name] = DrupyImport.import_file(filename) drupal_load.files[type_][name] = True return True else: return False
def drupal_get_messages(type=None, clear_queue=True): """ Return all messages that have been set. @param type (optional) Only return messages of this type. @param clear_queue (optional) Set to FALSE if you do not want to clear the messages queue @return An associative array, the key is the message type, the value an array of messages. If the type parameter is passed, you get only that type, or an empty array if there are no such messages. If type is not passed, all message types are returned, or an empty array if none exist. """ messages = drupal_set_message() if (not php.empty('messages')): if (type != None and type != False): if (clear_queue): del (php.SESSION['messages'][type]) if (php.isset(messages, type)): return { type: messages[type] } else: if (clear_queue): del (php.SESSION['messages']) return messages return {}
def check_location(source, directory = ''): """ Check if a file is really located inside directory + Should be used to make sure a file specified is really located within the directory to prevent exploits. @code // Returns False: file_check_location('/www/example.com/files/../../../etc/passwd', \ '/www/example.com/files') @endcode @param source A string set to the file to check. @param directory A string where the file should be located. @return FALSE for invalid path or the real path of the source. """ check = realpath(source) if (check): source = check else: # This file does not yet exist source = realpath(php.dirname(source)) + '/' + basename(source) directory = realpath(directory) if (directory and php.strpos(source, directory) != 0): return False return source
def arg(index=None, path=None): """ Return a component of the current Drupal path. When viewing a page at the path "admin/build/types", for example, arg(0) would return "admin", arg(1) would return "content", and arg(2) would return "types". Avoid use of this function where possible, as resulting code is hard to read. Instead, attempt to use named arguments in menu callback functions. See the explanation in menu.inc for how to construct callbacks that take arguments. @param index The index of the component, where each component is separated by a '/' (forward-slash), and where the first component has an index of 0 (zero). @return The component specified by index, or NULL if the specified component was not found. """ php.static(arg, 'arguments', {}) if (path is None): path = php.GET['q'] if (not php.isset(arg.arguments, path)): arg.arguments[path] = php.explode('/', path) if (index is None): return arg.arguments[path] if (php.isset(arg.arguments[path], index)): return arg.arguments[path][index]
def drupal_set_message(message=None, type='status', repeat=True): """ Set a message which reflects the status of the performed operation. If the def is called with no arguments, this def returns all set messages without clearing them. @param message The message should begin with a capital letter and always ends with a period '.'. @param type The type of the message. One of the following values are possible: - 'status' - 'warning' - 'error' @param repeat If this is FALSE and the message is already set, then the message won't be repeated. """ if (message): if (not php.isset(php.SESSION, 'messages')): php.SESSION['messages'] = {} if (not php.isset(php.SESSION['messages'], type)): php.SESSION['messages'][type] = [] if (repeat or not php.in_array(message, php.SESSION['messages'][type])): php.SESSION['messages'][type].append(message) # messages not set when DB connection fails return (php.SESSION['messages'] if php.isset(php.SESSION, 'messages') else \ None)
def invoke_all(*args): """ Invoke a hook in all enabled plugins that implement it. @param hook The name of the hook to invoke. @param ... Arguments to pass to the hook. @return An array of return values of the hook implementations. If plugins return arrays from their implementations, those are merged into one array. """ global plugins args = list(args) hook = 'hook_%s' % args[0] del(args[0]) return_ = [] for plugin_ in implements(hook): if (lib_bootstrap.drupal_function_exists(hook, plugins[plugin_])): function = DrupyImport.getFunction(\ plugins[plugin_], hook) result = php.call_user_func_array(function, args); if (result is not None and php.is_array(result)): return_ = p.array_merge_recursive(return_, result); elif (result is not None): return_.append( result ); return return_
def directory_temp(): """ Determine the default temporary directory. @return A string containing a temp directory. """ temporary_directory = variable_get('file_directory_temp', None) if (is_None(temporary_directory)): directories = [] # Has PHP been set with an upload_tmp_dir? if (ini_get('upload_tmp_dir')): directories.append(ini_get('upload_tmp_dir')) # Operating system specific dirs. if (php.substr(PHP_OS, 0, 3) == 'WIN'): directories.append('c:\\windows\\temp') directories.append('c:\\winnt\\temp') path_delimiter = '\\' else: directories.append('/tmp') path_delimiter = '/' for directory in directories: if (not temporary_directory and php.is_dir(directory)): temporary_directory = directory # if a directory has been found, use it, # otherwise default to 'files/tmp' or 'files\\tmp' temporary_directory = (temporary_directory if \ (temporary_directory != None) else \ (file_directory_path() + path_delimiter + 'tmp')) variable_set('file_directory_temp', temporary_directory) return temporary_directory
def drupal_validate_utf8(text): """ Checks whether a string is valid UTF-8. All functions designed to filter input should use drupal_validate_utf8 to ensure they operate on valid UTF-8 strings to prevent bypass of the filter. When text containing an invalid UTF-8 lead byte (0xC0 - 0xFF) is presented as UTF-8 to Internet Explorer 6, the program may misinterpret subsequent bytes. When these subsequent bytes are HTML control characters such as quotes or angle brackets, parts of the text that were deemed safe by filters end up in locations that are potentially unsafe; An onerror attribute that is outside of a tag, and thus deemed safe by a filter, can be interpreted by the browser as if it were inside the tag. This def exploits preg_match behaviour (since PHP 4.3.5) when used with the u modifier, as a fast way to find invalid UTF-8. When the matched string contains an invalid byte sequence, it will fail silently. preg_match may not fail on 4 and 5 octet sequences, even though they are not supported by the specification. The specific preg_match behaviour is present since PHP 4.3.5. @param text The text to check. @return TRUE if the text is valid UTF-8, FALSE if not. """ if (php.strlen(text) == 0): return True return (php.preg_match('/^./us', text) == 1)
def scan_directory(dir, mask, nomask = ['.', '..', 'CVS'], \ callback = 0, recurse = True, key = 'filename', min_depth = 0, depth = 0): """ Finds all files that match a given mask in a given directory. Directories and files beginning with a period are excluded; this prevents hidden files and directories (such as SVN working directories) from being scanned. @param dir The base directory for the scan, without trailing slash. @param mask The regular expression of the files to find. @param nomask An array of files/directories to ignore. @param callback The callback function to call for each match. @param recurse When True, the directory scan will recurse the entire tree starting at the provided directory. @param key The key to be used for the returned array of files + Possible values are "filename", for the path starting with dir, "basename", for the basename of the file, and "name" for the name of the file without an extension. @param min_depth Minimum depth of directories to return files from. @param depth Current depth of recursion + This parameter is only used internally and should not be passed. @return An associative array (keyed on the provided key) of objects with "path", "basename", and "name" members corresponding to the matching files. """ key = (key if php.in_array(key, \ ('filename', 'basename', 'name')) else 'filename') files = [] if php.is_dir(dir): dir_files = php.scandir(dir) for file in dir_files: if (not php.in_array(file, nomask) and file[0] != '.'): if (php.is_dir("%s/%s" % (dir, file)) and recurse): # Give priority to files in this folder by # merging them in after any subdirectory files. files = php.array_merge(file_scan_directory("%s/%s" % (dir, file), \ mask, nomask, callback, recurse, key, min_depth, depth + 1), files) elif (depth >= min_depth and ereg(mask, file)): # Always use this match over anything already # set in files with the same $key. filename = "%s/%s" % (dir, file) basename_ = php.basename(file) name = php.substr(basename_, 0, php.strrpos(basename_, '.')) files[key] = php.stdClass() files[key].filename = filename files[key].basename = basename_ files[key].name = name if (callback): callback(filename) return files
def directory_temp(): """ Determine the default temporary directory. @return A string containing a temp directory. """ temporary_directory = variable_get('file_directory_temp', None) if (is_None(temporary_directory)): directories = [] # Has PHP been set with an upload_tmp_dir? if (ini_get('upload_tmp_dir')): directories.append( ini_get('upload_tmp_dir') ) # Operating system specific dirs. if (php.substr(PHP_OS, 0, 3) == 'WIN'): directories.append( 'c:\\windows\\temp' ) directories.append( 'c:\\winnt\\temp' ) path_delimiter = '\\' else: directories.append( '/tmp' ) path_delimiter = '/' for directory in directories: if (not temporary_directory and php.is_dir(directory)): temporary_directory = directory # if a directory has been found, use it, # otherwise default to 'files/tmp' or 'files\\tmp' temporary_directory = (temporary_directory if \ (temporary_directory != None) else \ (file_directory_path() + path_delimiter + 'tmp')) variable_set('file_directory_temp', temporary_directory) return temporary_directory
def drupal_load(type_, name): """ Includes a file with the provided type and name. This prevents including a theme, engine, plugin, etc., more than once. @param type The type of item to load (i.e. theme, theme_engine, plugin). @param name The name of the item to load. @return TRUE if the item is loaded or has already been loaded. """ php.static(drupal_load, "files", {}) if not php.isset(drupal_load.files, type): drupal_load.files[type_] = {} if php.isset(drupal_load.files[type_], name): return True else: filename = drupal_get_filename(type_, name) if filename != False: lib_plugin.plugins[name] = DrupyImport.import_file(filename) drupal_load.files[type_][name] = True return True else: return False
def create_table_sql(name, table): """ Generate SQL to create a new table from a Drupal schema definition. @param name The name of the table to create. @param table A Schema API table definition array. @return An array of SQL statements to create the table. """ if (php.empty(table['mysql_suffix'])): table['mysql_suffix'] = "/*not 40100 DEFAULT CHARACTER SET UTF8 */" sql = "CREATE TABLE {" + name + "} (\n" # Add the SQL statement for each field. for field_name, field in table['fields'].items(): sql += _db_create_field_sql(field_name, _db_process_field(field)) + ", \n" # Process keys & indexes. keys = _db_create_keys_sql(table) if (php.count(keys)): sql += php.implode(", \n", keys) + ", \n" # Remove the last comma and space. sql = php.substr(sql, 0, -3) + "\n) " sql += table['mysql_suffix'] return array(sql)
def url_rewrite(path, options): """ Rewrite URL's with language based prefix. Parameters are the same as those of the url() function. """ # Only modify relative (insite) URLs. if (not options['external']): # Language can be passed as an option, or we go for current language. if (not php.isset(options, 'language')): options['language'] = lib_appglobals.language lang_type = variable_get('language_negotiation', \ lib_bootstrap.LANGUAGE_NEGOTIATION_NONE) if lang_type == lib_bootstrap.LANGUAGE_NEGOTIATION_NONE: # No language dependent path allowed in this mode. del (options['language']) return elif lang_type == lib_bootstrap.LANGUAGE_NEGOTIATION_DOMAIN: if (options['language'].domain): # Ask for an absolute URL with our modified base_url. options['absolute'] = True options['base_url'] = options['language'].domain return elif lang_type == lib_bootstrap.LANGUAGE_NEGOTIATION_PATH_DEFAULT: default = language_default() if (options['language'].language == default.language): return if lang_type == lib_bootstrap.LANGUAGE_NEGOTIATION_PATH: if (not php.empty(options['language'].prefix)): options['prefix'] = options['language'].prefix + '/' return
def create_table_sql(name, table): """ Generate SQL to create a new table from a Drupal schema definition. @param name The name of the table to create. @param table A Schema API table definition array. @return An array of SQL statements to create the table. """ if (php.empty(table['mysql_suffix'])): table['mysql_suffix'] = "/*not 40100 DEFAULT CHARACTER SET UTF8 */" sql = "CREATE TABLE {" + name + "} (\n" # Add the SQL statement for each field. for field_name,field in table['fields'].items(): sql += _db_create_field_sql(field_name, _db_process_field(field)) + ", \n" # Process keys & indexes. keys = _db_create_keys_sql(table) if (php.count(keys)): sql += php.implode(", \n", keys) + ", \n" # Remove the last comma and space. sql = php.substr(sql, 0, -3) + "\n) " sql += table['mysql_suffix'] return array(sql)
def update_page(content, show_messages = True): """ Generate a themed update page. Note: this function is not themeable. @param content The page content to show. @param show_messages Whether to output status and error messages. False can be useful to postpone the messages to a subsequent page. """ # Set required headers. drupal_set_header('Content-Type: text/html; charset=utf-8') # Assign content and show message flag. variables['content'] = content variables['show_messages'] = show_messages # The maintenance preprocess function is recycled here. template_preprocess_maintenance_page(variables) # Special handling of warning messages. messages = drupal_set_message() if (php.isset(messages['warning'])): title = ('The following update warnings should be carefully ' + \ 'reviewed before continuing' if \ (php.count(messages['warning']) > 1) else \ 'The following update warning should be carefully ' + \ 'reviewed before continuing') variables['messages'] += '<h4>' + title + ':</h4>' variables['messages'] += theme('status_messages', 'warning') # This was called as a theme hook (not template), so we need to # fix path_to_theme() for the template, to point at the actual # theme rather than system plugin as owner of the hook. lib_appglobals.theme_path = 'themes/garland' return theme_render_template('themes/garland/maintenance-page.tpl.php', \ variables)
def cell(cell, header, ts, i): """ Format a table cell. Adds a class attribute to all cells in the currently active column. @param cell The cell to format. @param header An array of column headers in the format described in theme_table(). @param ts The current table sort context as returned from hook_init(). @param i The index of the cell's table column. @return A properly formatted cell, ready for _theme_table_cell(). """ if (php.isset(header[i]['data']) and header[i]['data'] == ts['name'] and not php.empty(header[i]['field'])): if php.is_array(cell): if php.isset(cell['class']): cell['class'] += ' active' else: cell['class'] = 'active' else: cell = {'data': cell, 'class': 'active'} return cell
def url_rewrite(path, options): """ Rewrite URL's with language based prefix. Parameters are the same as those of the url() function. """ # Only modify relative (insite) URLs. if (not options['external']): # Language can be passed as an option, or we go for current language. if (not php.isset(options, 'language')): options['language'] = lib_appglobals.language lang_type = variable_get('language_negotiation', \ lib_bootstrap.LANGUAGE_NEGOTIATION_NONE) if lang_type == lib_bootstrap.LANGUAGE_NEGOTIATION_NONE: # No language dependent path allowed in this mode. del(options['language']) return elif lang_type == lib_bootstrap.LANGUAGE_NEGOTIATION_DOMAIN: if (options['language'].domain): # Ask for an absolute URL with our modified base_url. options['absolute'] = True options['base_url'] = options['language'].domain return elif lang_type == lib_bootstrap.LANGUAGE_NEGOTIATION_PATH_DEFAULT: default = language_default() if (options['language'].language == default.language): return if lang_type == lib_bootstrap.LANGUAGE_NEGOTIATION_PATH: if (not php.empty(options['language'].prefix)): options['prefix'] = options['language'].prefix + '/' return
def _query_callback(match, init = False): """ Helper function for db_query(). """ php.static(_query_callback, 'args') if (init): _query_callback.args = list(match); return; # We must use type casting to int to convert FALSE/NULL/(TRUE?) if match[1] == '%d': # We don't need db_escape_string as numbers are db-safe return str(int(php.array_shift(_query_callback.args))); elif match[1] == '%s': return db.escape_string(php.array_shift(_query_callback.args)); elif match[1] == '%n': # Numeric values have arbitrary precision, so can't be treated as float. # is_numeric() allows hex values (0xFF), but they are not valid. value = php.trim(php.array_shift(args)); return (value if (php.is_numeric(value) and not \ php.stripos(value, 'x')) else '0') elif match[1] == '%%': return '%'; elif match[1] == '%f': return float(php.array_shift(_query_callback.args)); elif match[1] == '%b': # binary data return db.encode_blob(php.array_shift(_query_callback.args));
def destination(destination, replace): """ Determines the destination path for a file depending on how replacement of existing files should be handled. @param destination A string specifying the desired path. @param replace Replace behavior when the destination file already exists. - FILE_EXISTS_REPLACE - Replace the existing file - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is unique - FILE_EXISTS_ERROR - Do nothing and return False. @return The destination file path or False if the file already exists and FILE_EXISTS_ERROR was specified. """ if (php.file_exists(destination)): if replace == FILE_EXISTS_RENAME: basename = basename(destination) directory = php.dirname(destination) destination = file_create_filename(basename, directory) elif replace == FILE_EXISTS_ERROR: drupal_set_message(t('The selected file %file could not be copied, \ because a file by that name already exists in the destination.' , \ {'%file' : destination}), 'error') return False return destination
def registry_cache_path_files(): """ Save the files required by the registry for this path. """ used_code = registry_mark_code(None, None, True) if used_code: files = [] type_sql = [] params = [] for type, names in used_code.items(): type_sql.append("(name IN (" + db_placeholders(names, "varchar") + ") AND type = '%s')") params = php.array_merge(params, names) params.append(type) res = db_query("SELECT DISTINCT filename FROM {registry} WHERE " + php.implode(" OR ", type_sql), params) while True: row = db_fetch_object(res) if row == None: break files.append(row.filename) if files: sort(files) # Only write this to cache if the file list we are going to cache # is different to what we loaded earlier in the request. if files != registry_load_path_files(True): menu = menu_get_item() cache_set("registry:" + menu["path"], php.implode(";", files), "cache_registry")
def list_(refresh = False, bootstrap = True, sort = False, \ fixed_list = None): """ Collect a list of all loaded plugins. During the bootstrap, return only vital plugins. See bootstrap.inc @param refresh Whether to force the plugin list to be regenerated (such as after the administrator has changed the system settings). @param bootstrap Whether to return the reduced set of plugins loaded in "bootstrap mode" for cached pages. See bootstrap.inc. @param sort By default, plugins are ordered by weight and filename, settings this option to True, plugin list will be ordered by plugin name. @param fixed_list (Optional) Override the plugin list with the given plugins. Stays until the next call with refresh = True. @return An associative array whose keys and values are the names of all loaded plugins. """ php.static(list_, 'list_', {}) php.static(list_, 'sorted_list') if (refresh or fixed_list): list_.sorted_list = None list_.list_ = {} if (fixed_list): for name, plugin in fixed_list.items(): lib_bootstrap.drupal_get_filename('plugin', name, plugin['filename']) list_.list_[name] = name else: if (bootstrap): result = lib_database.query(\ "SELECT name, filename FROM {system} " + \ "WHERE type = 'plugin' AND status = 1 AND " + \ "bootstrap = 1 ORDER BY weight ASC, filename ASC") else: result = lib_database.query(\ "SELECT name, filename FROM {system} " + \ "WHERE type = 'plugin' AND status = 1 " + \ "ORDER BY weight ASC, filename ASC") while True: plugin_ = lib_database.fetch_object(result) if (plugin_ == None or plugin_ == False): break if (DrupyImport.exists(plugin_.filename)): lib_bootstrap.drupal_get_filename('plugin', \ plugin_.name, plugin_.filename) list_.list_[plugin_.name] = plugin_.name if (sort): if (list_.sorted_list == None): list_.sorted_list = plugin_list.list_ p.ksort(list_.sorted_list) return list_.sorted_list return list_.list_
def _create_key_sql(fields): ret = [] for field in fields: if (php.is_array(field)): ret.append( field[0] + '(' + field[1] + ')' ) else: ret.append( field ) return php.implode(', ', ret)
def _create_key_sql(fields): ret = [] for field in fields: if (php.is_array(field)): ret.append(field[0] + '(' + field[1] + ')') else: ret.append(field) return php.implode(', ', ret)
def list_(refresh = False, bootstrap = True, sort = False, \ fixed_list = None): """ Collect a list of all loaded plugins. During the bootstrap, return only vital plugins. See bootstrap.inc @param refresh Whether to force the plugin list to be regenerated (such as after the administrator has changed the system settings). @param bootstrap Whether to return the reduced set of plugins loaded in "bootstrap mode" for cached pages. See bootstrap.inc. @param sort By default, plugins are ordered by weight and filename, settings this option to True, plugin list will be ordered by plugin name. @param fixed_list (Optional) Override the plugin list with the given plugins. Stays until the next call with refresh = True. @return An associative array whose keys and values are the names of all loaded plugins. """ php.static(list_, 'list_', {}) php.static(list_, 'sorted_list') if (refresh or fixed_list): list_.sorted_list = None list_.list_ = {} if (fixed_list): for name,plugin in fixed_list.items(): lib_bootstrap.drupal_get_filename('plugin', name, plugin['filename']) list_.list_[name] = name else: if (bootstrap): result = lib_database.query(\ "SELECT name, filename FROM {system} " + \ "WHERE type = 'plugin' AND status = 1 AND " + \ "bootstrap = 1 ORDER BY weight ASC, filename ASC") else: result = lib_database.query(\ "SELECT name, filename FROM {system} " + \ "WHERE type = 'plugin' AND status = 1 " + \ "ORDER BY weight ASC, filename ASC") while True: plugin_ = lib_database.fetch_object(result) if (plugin_ == None or plugin_ == False): break if (DrupyImport.exists(plugin_.filename)): lib_bootstrap.drupal_get_filename('plugin', \ plugin_.name, plugin_.filename) list_.list_[plugin_.name] = plugin_.name if (sort): if (list_.sorted_list == None): list_.sorted_list = plugin_list.list_ p.ksort(list_.sorted_list) return list_.sorted_list return list_.list_
def get_t(): """ Return the name of the localisation function. Use in code that needs to run both during installation and normal operation. """ php.static(get_t, 't') if (get_t.t == None): get_t.t = ('st' if php.function_exists('install_main') else 't') return get_t.t
def drupal_init_path(): """ Initialize the php.GET['q'] variable to the proper normal path. """ if (php.isset(php.GET, 'q') and not php.empty(php.GET['q'])): php.GET['q'] = drupal_get_normal_path(php.trim(php.GET['q'], '/')) else: php.GET['q'] = drupal_get_normal_path( \ lib_bootstrap.variable_get('site_frontpage', 'node'))
def get_t(): """ Return the name of the localisation function. Use in code that needs to run both during installation and normal operation. """ php.static(get_t, "t") if get_t.t == None: get_t.t = "st" if php.function_exists("install_main") else "t" return get_t.t
def _registry_check_code(type_, name): """ Helper for registry_check_{interface, class}. """ file = db_result(db_query("SELECT filename FROM {registry} WHERE name = '%s' AND type = '%s'", name, type_)) if file: php.require_once(file) registry_mark_code(type_, name) return True
def drupal_initialize_variables(): """ Initialize variables needed for the rest of the execution. """ if (not php.isset(php.SERVER, 'HTTP_REFERER')): php.SERVER['HTTP_REFERER'] = '' if (not php.isset(php.SERVER, 'SERVER_PROTOCOL') or \ (php.SERVER['SERVER_PROTOCOL'] != 'HTTP/1.0' and \ php.SERVER['SERVER_PROTOCOL'] != 'HTTP/1.1')): php.SERVER['SERVER_PROTOCOL'] = 'HTTP/1.0'
def drupal_initialize_variables(): """ Initialize variables needed for the rest of the execution. """ if not php.isset(php.SERVER, "HTTP_REFERER"): php.SERVER["HTTP_REFERER"] = "" if not php.isset(php.SERVER, "SERVER_PROTOCOL") or ( php.SERVER["SERVER_PROTOCOL"] != "HTTP/1.0" and php.SERVER["SERVER_PROTOCOL"] != "HTTP/1.1" ): php.SERVER["SERVER_PROTOCOL"] = "HTTP/1.0"
def get_querystring(): """ Compose a query string to append to table sorting requests. @return A query string that consists of all components of the current page request except for those pertaining to table sorting. """ return lib_common.drupal_query_string_encode( _REQUEST, php.array_merge(['q', 'sort', 'order'], php.array_keys(_COOKIE)))
def _create_field_sql(name, spec): """ Create an SQL string for a field to be used in table creation or alteration. Before passing a field out of a schema definition into this function it has to be processed by _db_process_field(). @param name Name of the field. @param spec The field specification, as per the schema data structure format. """ sql = "`" + name + "` ".spec['mysql_type'] if (php.isset(spec, 'length')): sql += '(' + spec['length'] + ')' elif (php.isset(spec, 'precision') and php.isset(spec, 'scale')): sql += '(' + spec['precision'] + ', ' + spec['scale'] + ')' if (not php.empty(spec['unsigned'])): sql += ' unsigned' if (not php.empty(spec['not None'])): sql += ' NOT None' if (not php.empty(spec['auto_increment'])): sql += ' auto_increment' if (php.isset(spec, 'default')): if (is_string(spec['default'])): spec['default'] = "'" + spec['default'] + "'" sql += ' DEFAULT ' + spec['default'] if (php.empty(spec['not None']) and not php.isset(spec, 'default')): sql += ' DEFAULT None' return sql
def _create_field_sql(name, spec): """ Create an SQL string for a field to be used in table creation or alteration. Before passing a field out of a schema definition into this function it has to be processed by _db_process_field(). @param name Name of the field. @param spec The field specification, as per the schema data structure format. """ sql = "`" + name + "` " . spec['mysql_type'] if (php.isset(spec, 'length')): sql += '(' + spec['length'] + ')' elif (php.isset(spec, 'precision') and php.isset(spec, 'scale')): sql += '(' + spec['precision'] + ', ' + spec['scale'] + ')' if (not php.empty(spec['unsigned'])): sql += ' unsigned' if (not php.empty(spec['not None'])): sql += ' NOT None' if (not php.empty(spec['auto_increment'])): sql += ' auto_increment' if (php.isset(spec, 'default')): if (is_string(spec['default'])): spec['default'] = "'" + spec['default'] + "'" sql += ' DEFAULT ' + spec['default'] if (php.empty(spec['not None']) and not php.isset(spec, 'default')): sql += ' DEFAULT None' return sql
def theme_breadcrumb(breadcrumb): """ Return a themed breadcrumb trail. @param breadcrumb An array containing the breadcrumb links. @return a string containing the breadcrumb output. """ if (not php.empty(breadcrumb)): return '<div class="breadcrumb">' + \ php.implode(' › ', breadcrumb) + '</div>'
def drop_table(ret, table): """ Drop a table. @param ret Array to which query results will be added. @param table The table to be dropped. """ php.Reference.check(ref) php.array_merge(update_sql('DROP TABLE {' + table + '}'), ret, True)
def drop_table(ret, table): """ Drop a table. @param ret Array to which query results will be added. @param table The table to be dropped. """ php.Reference.check(ref) php.array_merge( update_sql('DROP TABLE {' + table + '}'), ret, True )
def _registry_check_code(type_, name): """ Helper for registry_check_{interface, class}. """ file = db_result(db_query(\ "SELECT filename FROM {registry} WHERE name = '%s' AND type = '%s'", \ name, type_)) if (file): php.require_once(file) registry_mark_code(type_, name) return True
def mime_header_decode(header_): """ Complement to mime_header_encode """ # First step: encoded chunks followed by # other encoded chunks (need to collapse whitespace) header_ = php.preg_replace_callback(\ '/=\?([^?]+)\?(Q|B)\?([^?]+|\?(?!=))\?=\s+(?==\?)/', \ '_mime_header_decode', header_); # Second step: remaining chunks (do not collapse whitespace) return php.preg_replace_callback(\ '/=\?([^?]+)\?(Q|B)\?([^?]+|\?(?!=))\?=/', '_mime_header_decode', header_);
def validate_image_resolution(file, maximum_dimensions = 0, \ minimum_dimensions = 0): """ If the file is an image verify that its dimensions are within the specified maximum and minimum dimensions + Non-image files will be ignored. @param file A Drupal file object + This function may resize the file affecting its size. @param maximum_dimensions An optional string in the form WIDTHxHEIGHT e.g + '640x480' or '85x85'. If an image toolkit is installed the image will be resized down to these dimensions + A value of 0 indicates no restriction on size, so resizing will be attempted. @param minimum_dimensions An optional string in the form WIDTHxHEIGHT. This will check that the image meets a minimum size + A value of 0 indicates no restriction. @return An array + If the file is an image and did not meet the requirements, it will contain an error message. """ php.Reference.check(file) errors = [] # Check first that the file is an image. info = image_get_info(file.filepath) if (info): if (maximum_dimensions): # Check that it is smaller than the given dimensions. width, height = php.explode('x', maximum_dimensions) if (info['width'] > width or info['height'] > height): # Try to resize the image to fit the dimensions. if (image_get_toolkit() and image_scale(file.filepath, \ file.filepath, width, height)): drupal_set_message(t('The image was resized to fit within ' + \ 'the maximum allowed dimensions of %dimensions pixels.', \ {'%dimensions' : maximum_dimensions})) # Clear the cached filesize and refresh the image information. clearstatcache() info = image_get_info(file.filepath) file.filesize = info['file_size'] else: errors.append( t('The image is too large; the maximum ' + \ 'dimensions are %dimensions pixels.', \ {'%dimensions' : maximum_dimensions}) ) if (minimum_dimensions): # Check that it is larger than the given dimensions. width, height = php.explode('x', minimum_dimensions) if (info['width'] < width or info['height'] < height): errors.append( t('The image is too small; the ' + \ 'minimum dimensions are %dimensions pixels.', \ {'%dimensions' : minimum_dimensions}) ) return errors
def drupal_strtoupper(text): """ Uppercase a UTF-8 string. """ if (lib_appglobals.multibyte == UNICODE_MULTIBYTE): return php.mb_strtoupper(text); else: # Use C-locale for ASCII-only uppercase text = php.strtoupper(text); # Case flip Latin-1 accented letters text = php.preg_replace_callback('/\xC3[\xA0-\xB6\xB8-\xBE]/', \ _unicode_caseflip, text); return text;