Defined functions and added comments. No functional change.
[toast/findwwwritable.git] / findwwwritable.py
1 #!/usr/bin/python
2 # python 2.x is used
3
4 import os
5 import stat
6 from os.path import join
7
8
9 def collect_writable_dirs(rootdir, uid, gids):
10     """Returns a list of directories below rootdir (including rootdir) that are writeable 
11     by the user with the given uid or gids or that are world writeable.
12     Normally, uid is the user id of the apache user (e.g. www-data) and gids is a list
13     of group ids this user is member of.
14     
15     :param rootdir: string. directory where the search should start at
16     :param uid: integer user id
17     :param gids: list of integer group ids"""
18     assert isinstance(rootdir, str)
19     assert isinstance(uid, int)
20     assert isinstance(gids, list)
21     for gid in gids: assert isinstance(gid, int)
22
23     writable_dirs = [] # dirs with write permissions - this list is filled by this function
24
25     for root, dirs, files in os.walk(rootdir):
26         for d in dirs:
27             dp = join(root, d) # dp is the dir with path
28             s = os.lstat(dp)
29             if (s.st_mode & stat.S_IFLNK) == stat.S_IFLNK: continue # skip symlinks
30             if s.st_uid == uid and (s.st_mode & stat.S_IWUSR) > 0:
31                 writable_dirs.append(dp)
32             elif s.st_gid in gids and (s.st_mode & stat.S_IWGRP) > 0:
33                 writable_dirs.append(dp)
34             elif (s.st_mode & stat.S_IWOTH) > 0:
35                 writable_dirs.append(dp)
36
37     return writable_dirs
38
39
40
41 def summarize_dirs(writable_dirs):
42     """Takes a list of directories and omits each subdirectory if its parent directory
43     is also included in the list. This list is modified "in place" (nothing is returned).
44
45     :param writeable_dirs: List of directories (strings)."""
46     writable_dirs = sorted(writable_dirs)
47
48     i = 0
49     while i < len(writable_dirs)-1:
50         if writable_dirs[i+1].startswith(writable_dirs[i] + '/'):
51             del writable_dirs[i+1]
52         else:
53             i += 1
54
55
56
57 if __name__ == '__main__':
58
59     # variables
60     uid = 33                   # user id of the user whos write permissions should be found
61     gids = [33, 42, 121, 127]  # group ids of the user whos write permissions should be found
62     rootdir = '/home'          # directory where the seach is started
63
64     # collect and summarize writeable directories
65     writable_dirs = collect_writable_dirs(rootdir, uid, gids)
66     summarize_dirs(writable_dirs)
67
68     # print writeable directories
69     for d in writable_dirs:
70         print d
71
72