Beispiel #1
0
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
Beispiel #2
0
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]
Beispiel #3
0
def ip_address(reset=False):
    """
   If Drupal is behind a reverse proxy, we use the X-Forwarded-For header
   instead of $_SERVER['REMOTE_ADDR'], which would be the IP address of 
   the proxy server, and not the client's.  If Drupal is run in a cluster
   we use the X-Cluster-Client-Ip header instead.

   @param $reset
     Reset the current IP address saved in static.
   @return
     IP address of client machine, adjusted for reverse proxy and/or cluster
     environments.
  """
    php.static(ip_address, "ip_address")
    if ip_address.ip_address is None or reset:
        ip_address.ip_address = php.SERVER["REMOTE_ADDR"]
        if variable_get("reverse_proxy", 0):
            if php.array_key_exists("HTTP_X_FORWARDED_FOR", php.SERVER):
                # If an array of known reverse proxy IPs is provided, then trust
                # the XFF header if request really comes from one of them.
                reverse_proxy_addresses = variable_get("reverse_proxy_addresses", tuple())
                if not php.empty(reverse_proxy_addresses) and php.in_array(
                    ip_address.ip_address, reverse_proxy_addresses, True
                ):
                    # If there are several arguments, we need to check the most
                    # recently added one, i.e. the last one.
                    ip_address.ip_address = php.array_pop(php.explode(",", php.SERVER["HTTP_X_FORWARDED_FOR"]))
            # When Drupal is run in a cluster environment,
            # REMOTE_ADDR contains the IP
            # address of a server in the cluster, while the IP address
            # of the client is
            # stored in HTTP_X_CLUSTER_CLIENT_IP.
            if php.array_key_exists("HTTP_X_CLUSTER_CLIENT_IP", php.SERVER):
                ip_address.ip_address = php.SERVER["HTTP_X_CLUSTER_CLIENT_IP"]
    return ip_address.ip_address
Beispiel #4
0
def sql(header, before = ''):
  """
   Create an SQL sort clause.

   This def produces the ORDER BY clause to insert in your SQL queries,
   assuring that the returned database table rows match the sort order chosen
   by the user.

   @param header
     An array of column headers in the format described in theme_table().
   @param before
     An SQL string to insert after ORDER BY and before the table sorting code.
     Useful for sorting by important attributes like "sticky" first.
   @return
     An SQL string to append to the end of a query.

   @ingroup database
  """
  ts = hook_init(header)
  if ts['sql']:
    # Based on code from db_escape_table(), but this can also contain a dot.
    field = php.php.preg_replace('/[^A-Za-z0-9_.]+/', '', ts['sql'])
    # Sort order can only be ASC or DESC.
    sort = lib_unicode.drupal_strtoupper(ts['sort'])
    sort = (sort if php.in_array(sort, ['ASC', 'DESC']) else '')
    return " ORDER BY before field sort"
Beispiel #5
0
def munge_filename(filename, extensions, alerts = True):
  """
   Munge the filename as needed for security purposes + For instance the file
   name "exploit.php.pps" would become "exploit.php_.pps".
  
   @param filename The name of a file to modify.
   @param extensions A space separated list of extensions that should not
     be altered.
   @param alerts Whether alerts (watchdog, drupal_set_message()) should be
     displayed.
   @return filename The potentially modified filename.
  """
  original = filename
  # Allow potentially insecure uploads for very savvy users and admin
  if (not variable_get('allow_insecure_uploads', 0)):
    whitelist = array_unique(php.explode(' ', php.trim(extensions)))
    # Split the filename up by periods + The first part becomes the basename
    # the last part the final extension.
    filename_parts = php.explode('.', filename)
    new_filename = php.array_shift(filename_parts); # Remove file basename.
    final_extension = php.array_pop(filename_parts); # Remove final extension.
    # Loop through the middle parts of the name and add an underscore to the
    # end of each section that could be a file extension but isn't in the list
    # of allowed extensions.
    for filename_part in filename_parts:
      new_filename += '.' + filename_part
      if (not php.in_array(filename_part, whitelist) and \
          php.preg_match("/^[a-zA-Z]{2,5}\d?$/", filename_part)):
        new_filename += '_'
    filename = new_filename + '.' + final_extension
    if (alerts and original != filename):
      drupal_set_message(t('For security reasons, your upload has ' + \
        'been renamed to %filename.', {'%filename' : filename}))
  return filename
Beispiel #6
0
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)
Beispiel #7
0
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
Beispiel #8
0
def registry_mark_code(type_, name, return_=False):
    """
   Collect the resources used for this request.
  
   @param type
     The type of resource.
   @param name
     The name of the resource.
   @param return
     Boolean flag to indicate whether to return the resources.
  """
    php.static(registry_mark_code, "resources", [])
    if type_ and name:
        if not php.isset(registry_mark_code.resources, type_):
            registry_mark_code.resources[type_] = []
        if not php.in_array(name, registry_mark_code.resources[type_]):
            registry_mark_code.resources[type].append(name)
    if return_:
        return registry_mark_code.resources
Beispiel #9
0
def download():
    """
   Call plugins that implement hook_file_download() to find out if a file is
   accessible and what headers it should be transferred with + If a plugin
   returns -1 drupal_access_denied() will be returned + If one or more plugins
   returned headers the download will start with the returned headers + If no
   plugins respond drupal_not_found() will be returned.
  """
    # Merge remainder of arguments from php.GET['q'], into relative file path.
    args = func_get_args()
    filepath = php.implode('/', args)
    # Maintain compatibility with old ?file=paths saved in node bodies.
    if (php.isset(php.GET, 'file')):
        filepath = php.GET['file']
    if (php.file_exists(file_create_path(filepath))):
        headers = plugin_invoke_all('file_download', filepath)
        if (php.in_array(-1, headers)):
            return drupal_access_denied()
        if (php.count(headers)):
            file_transfer(filepath, headers)
    return drupal_not_found()
Beispiel #10
0
def download():
  """
   Call plugins that implement hook_file_download() to find out if a file is
   accessible and what headers it should be transferred with + If a plugin
   returns -1 drupal_access_denied() will be returned + If one or more plugins
   returned headers the download will start with the returned headers + If no
   plugins respond drupal_not_found() will be returned.
  """
  # Merge remainder of arguments from php.GET['q'], into relative file path.
  args = func_get_args()
  filepath = php.implode('/', args)
  # Maintain compatibility with old ?file=paths saved in node bodies.
  if (php.isset(php.GET, 'file')):
    filepath =  php.GET['file']
  if (php.file_exists(file_create_path(filepath))):
    headers = plugin_invoke_all('file_download', filepath)
    if (php.in_array(-1, headers)):
      return drupal_access_denied()
    if (php.count(headers)):
      file_transfer(filepath, headers)
  return drupal_not_found()
Beispiel #11
0
def registry_mark_code(type_, name, return_=False):
    """
   Collect the resources used for this request.
  
   @param type
     The type of resource.
   @param name
     The name of the resource.
   @param return
     Boolean flag to indicate whether to return the resources.
  """
    php.static(registry_mark_code, 'resources', [])
    if (type_ and name):
        if (not php.isset(
                registry_mark_code.resources,
                type_,
        )):
            registry_mark_code.resources[type_] = []
        if (not php.in_array(name, registry_mark_code.resources[type_])):
            registry_mark_code.resources[type].append(name)
    if (return_):
        return registry_mark_code.resources
Beispiel #12
0
def drupal_is_denied(ip):
    """
   Check to see if an IP address has been blocked.
  
   Blocked IP addresses are stored in the database by default. However for
   performance reasons we allow an override in settings.php. This allows us
   to avoid querying the database at this critical stage of the bootstrap if
   an administrative interface for IP address blocking is not required.
  
   @param $ip string
     IP address to check.
   @return bool
     TRUE if access is denied, FALSE if access is allowed.
  """
    # Because this function is called on every page request, we first check
    # for an array of IP addresses in settings.php before querying the
    # database.
    blocked_ips = variable_get('blocked_ips', None)
    if (blocked_ips != None and php.is_array(blocked_ips)):
        return php.in_array(ip, blocked_ips)
    else:
        sql = "SELECT 1 FROM {blocked_ips} WHERE ip = '%s'"
        return (lib_database.result(lib_database.query(sql, ip)) != False)
Beispiel #13
0
def drupal_is_denied(ip):
    """
   Check to see if an IP address has been blocked.
  
   Blocked IP addresses are stored in the database by default. However for
   performance reasons we allow an override in settings.php. This allows us
   to avoid querying the database at this critical stage of the bootstrap if
   an administrative interface for IP address blocking is not required.
  
   @param $ip string
     IP address to check.
   @return bool
     TRUE if access is denied, FALSE if access is allowed.
  """
    # Because this function is called on every page request, we first check
    # for an array of IP addresses in settings.php before querying the
    # database.
    blocked_ips = variable_get("blocked_ips", None)
    if blocked_ips != None and php.is_array(blocked_ips):
        return php.in_array(ip, blocked_ips)
    else:
        sql = "SELECT 1 FROM {blocked_ips} WHERE ip = '%s'"
        return lib_database.result(lib_database.query(sql, ip)) != False
Beispiel #14
0
def ip_address(reset=False):
    """
   If Drupal is behind a reverse proxy, we use the X-Forwarded-For header
   instead of $_SERVER['REMOTE_ADDR'], which would be the IP address of 
   the proxy server, and not the client's.  If Drupal is run in a cluster
   we use the X-Cluster-Client-Ip header instead.

   @param $reset
     Reset the current IP address saved in static.
   @return
     IP address of client machine, adjusted for reverse proxy and/or cluster
     environments.
  """
    php.static(ip_address, 'ip_address')
    if (ip_address.ip_address is None or reset):
        ip_address.ip_address = php.SERVER['REMOTE_ADDR']
        if (variable_get('reverse_proxy', 0)):
            if (php.array_key_exists('HTTP_X_FORWARDED_FOR', php.SERVER)):
                # If an array of known reverse proxy IPs is provided, then trust
                # the XFF header if request really comes from one of them.
                reverse_proxy_addresses = variable_get('reverse_proxy_addresses', \
                  tuple())
                if (not php.empty(reverse_proxy_addresses) and \
                    php.in_array(ip_address.ip_address, reverse_proxy_addresses, \
                    True)):
                    # If there are several arguments, we need to check the most
                    # recently added one, i.e. the last one.
                    ip_address.ip_address = php.array_pop(\
                      php.explode(',', php.SERVER['HTTP_X_FORWARDED_FOR']))
            # When Drupal is run in a cluster environment,
            # REMOTE_ADDR contains the IP
            # address of a server in the cluster, while the IP address
            # of the client is
            # stored in HTTP_X_CLUSTER_CLIENT_IP.
            if (php.array_key_exists('HTTP_X_CLUSTER_CLIENT_IP', php.SERVER)):
                ip_address.ip_address = php.SERVER['HTTP_X_CLUSTER_CLIENT_IP']
    return ip_address.ip_address
Beispiel #15
0
def munge_filename(filename, extensions, alerts=True):
    """
   Munge the filename as needed for security purposes + For instance the file
   name "exploit.php.pps" would become "exploit.php_.pps".
  
   @param filename The name of a file to modify.
   @param extensions A space separated list of extensions that should not
     be altered.
   @param alerts Whether alerts (watchdog, drupal_set_message()) should be
     displayed.
   @return filename The potentially modified filename.
  """
    original = filename
    # Allow potentially insecure uploads for very savvy users and admin
    if (not variable_get('allow_insecure_uploads', 0)):
        whitelist = array_unique(php.explode(' ', php.trim(extensions)))
        # Split the filename up by periods + The first part becomes the basename
        # the last part the final extension.
        filename_parts = php.explode('.', filename)
        new_filename = php.array_shift(filename_parts)
        # Remove file basename.
        final_extension = php.array_pop(filename_parts)
        # Remove final extension.
        # Loop through the middle parts of the name and add an underscore to the
        # end of each section that could be a file extension but isn't in the list
        # of allowed extensions.
        for filename_part in filename_parts:
            new_filename += '.' + filename_part
            if (not php.in_array(filename_part, whitelist) and \
                php.preg_match("/^[a-zA-Z]{2,5}\d?$/", filename_part)):
                new_filename += '_'
        filename = new_filename + '.' + final_extension
        if (alerts and original != filename):
            drupal_set_message(t('For security reasons, your upload has ' + \
              'been renamed to %filename.', {'%filename' : filename}))
    return filename
Beispiel #16
0
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]
Beispiel #17
0
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