umnlisting.dcgi - geomyidae - A small C-based gopherd.
HTML git clone git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/geomyidae/
DIR Log
DIR Files
DIR Refs
DIR Tags
DIR README
DIR LICENSE
---
umnlisting.dcgi (5552B)
---
1 #!/usr/bin/env python
2 # coding=utf-8
3 #
4 # Dir listing like in UMN gopher.
5 #
6 # Files: .abstract, .names, .cap/$file, .Links
7 # Entries: Name=, Type=, Path=, Host=, Port=, Abstract=, Admin=, URL=,
8 # TTL=
9 #
10
11 import os
12 import sys
13
14 def dcgifilterprint(lines):
15 for line in lines:
16 line = line.strip()
17 if line[0] == 't':
18 print("t%s" % (line))
19 else:
20 print("%s" % (line))
21
22 def parselinksfile(filepath, link={}):
23 fd = open(filepath, "r")
24 links = {}
25 while 1:
26 line = fd.readline()
27 if not line:
28 if "path" in link:
29 links[link["path"]] = link
30 link = {}
31 break
32 line = line.strip()
33 if len(line) == 0 or line.startswith("#"):
34 if "path" in link:
35 links[link["path"]] = link
36 link = {}
37 continue
38 elif line.startswith("Type="):
39 link["type"] = line.split("=", 1)[1]
40 elif line.startswith("Name="):
41 link["name"] = line.split("=", 1)[1]
42 elif line.startswith("Path="):
43 link["path"] = line.split("=", 1)[1]
44 elif line.startswith("Host="):
45 link["host"] = line.split("=", 1)[1]
46 elif line.startswith("Port="):
47 link["port"] = line.split("=", 1)[1]
48 elif line.startswith("Numb="):
49 try:
50 link["number"] = int(line.split("=", 1)[1])
51 except ValueError:
52 pass
53 elif line.startswith("Abstract="):
54 link["abstract"] = line.split("=", 1)[1]
55 while link["abstract"][-1] == "\\":
56 link["abstract"] = link["abstract"][:-1]
57 link["abstract"] += "\n"
58 link["abstract"] += fd.readline().strip()
59
60 # Undefined case in UMN. Handle it nicely.
61 if link["abstract"][-1] == "\\":
62 link["abstract"][-1] = "\n"
63 elif line.startswith("Admin="):
64 link["admin"] = line.split("=", 1)[1]
65 elif line.startswith("URL="):
66 link["url"] = line.split("=", 1)[1]
67 elif line.startswith("TTL="):
68 link["ttl"] = line.split("=", 1)[1]
69 fd.close()
70
71 return links
72
73 def usage(app):
74 print("usage: %s search arguments host port" % (app),
75 file=sys.stderr)
76 sys.exit(1)
77
78 def main(args):
79 scriptname = os.path.basename(args[0])
80 if len(args) < 5:
81 usage(scriptname)
82 search = args[1]
83 arguments = args[2]
84 host = args[3]
85 port = args[4]
86
87 basedir = "."
88 if len(arguments) > 0 and arguments[0] == "/":
89 basedir = arguments[0].split("?")[0]
90
91 # First print every .abstract file content.
92 abstractpath = "%s/.abstract" % (basedir)
93 if os.path.exists(abstractpath):
94 fd = open(abstractpath, "r")
95 dcgifilterprint(fd.readlines())
96 fd.close()
97
98 outputlinks = {}
99 numblinks = {}
100
101 linkspath = "%s/.Links" % (basedir)
102 if os.path.exists(linkspath):
103 linkslinks = parselinksfile(linkspath)
104 for linkkey in linkslinks.keys():
105 outputlinks[linkkey] = linkslinks[linkkey]
106 if "number" in linkslinks[linkkey]:
107 numblinks[linkkey] = linkslinks[linkkey]
108
109 entries = os.listdir(basedir)
110 for entry in entries:
111 entrylink = {}
112 entrylink["type"] = "9"
113 if os.path.isdir(entry):
114 entrylink["type"] = "1"
115
116 entrylink["path"] = "./%s" % (entry)
117 entrylink["name"] = entry
118 capspath = "%s/.cap/%s" % (basedir, entry)
119 if os.path.exists(capspath):
120 caplink = parselinksfile(capspath, entrylink)
121 outputlinks[entrylink["path"]] = entrylink
122 if "number" in entrylink:
123 numblinks[entrylink["path"]] = entrylink
124
125 namespath = "%s/.names" % (basedir)
126 if os.path.exists(namespath):
127 nameslinks = parselinksfile(namespath)
128 for namekey in nameslinks.keys():
129 namelink = nameslinks[namekey]
130 if namekey in outputlinks.keys():
131 for key in namelink:
132 outputlinks[namekey][key] = \
133 namelink[key]
134 else:
135 outputlinks[namekey] = nameslinks[namekey]
136 if "number" in outputlinks[namekey]:
137 numblinks[namekey] = outputlinks[namekey]
138
139 displaylinks = {}
140 for link in outputlinks.keys():
141 if "name" in outputlinks[link]:
142 displaylinks[outputlinks[link]["name"]] = link
143 elif "path" in outputlinks[link]:
144 if outputlinks[link]["path"].startswith("./"):
145 displaylinks[outputlinks[link]["path"][2:]] = \
146 link
147 else:
148 displaylinks[outputlinks[link]["path"]] = \
149 link
150 else:
151 displaylinks[link] = link
152
153 displaykeys = sorted(displaylinks)
154 for dotfile in [".Links", ".names", ".cap", ".abstract"]:
155 try:
156 displaykeys.remove(dotfile)
157 except ValueError:
158 pass
159
160 # This is why the UMN format really sucks.
161 numbers = {}
162 for numb in numblinks.keys():
163 link = outputlinks[numb]
164 numbers[link["number"]] = outputlinks[numb]
165 if "name" in link:
166 displaykeys.remove(link["name"])
167 elif "path" in link:
168 if link["path"].startswith("./"):
169 displaykeys.remove(link["path"][2:])
170 else:
171 displaykeys.remove(link["path"])
172
173 curnumber = 1
174 while 1:
175 if curnumber in numbers.keys():
176 path = numbers[curnumber]["path"]
177 numbers.pop(curnumber)
178 else:
179 key = displaykeys.pop()
180 path = displaylinks[key]
181
182 # Work on the rest of the numbered links, when no display
183 # entries are left.
184 if len(displaykeys) == 0:
185 if len(numbers) == 0:
186 break
187 randnumb = numbers.pop()
188 path = randnumb["path"]
189
190 link = outputlinks[path]
191 if "port" not in link:
192 link["port"] = "port"
193 if "host" not in link:
194 link["host"] = "server"
195 if "name" not in link:
196 if link["path"].startswith("./"):
197 link["name"] = link["path"][2:]
198 else:
199 link["name"] = link["path"]
200 if "type" not in link:
201 link["type"] = "9"
202
203 # dcgi escaping.
204 link["name"].replace("|", "\\|")
205
206 print("[%s|%s|%s|%s|%s]" % (link["type"][0],\
207 link["name"], link["path"], link["host"],\
208 link["port"]))
209
210 if "abstract" in link:
211 dcgifilterprint(link["abstract"].split("\n"))
212
213 curnumber += 1
214
215 return 0
216
217 if __name__ == "__main__":
218 sys.exit(main(sys.argv))
219