]> git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Python/Python-2.7.2/Demo/sockets/gopher.py
AppPkg/Applications/Python: Add Python 2.7.2 sources since the release of Python...
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Demo / sockets / gopher.py
1 #! /usr/bin/env python
2
3 # A simple gopher client.
4 #
5 # Usage: gopher [ [selector] host [port] ]
6
7 import string
8 import sys
9 import os
10 import socket
11
12 # Default selector, host and port
13 DEF_SELECTOR = ''
14 DEF_HOST = 'gopher.micro.umn.edu'
15 DEF_PORT = 70
16
17 # Recognized file types
18 T_TEXTFILE = '0'
19 T_MENU = '1'
20 T_CSO = '2'
21 T_ERROR = '3'
22 T_BINHEX = '4'
23 T_DOS = '5'
24 T_UUENCODE = '6'
25 T_SEARCH = '7'
26 T_TELNET = '8'
27 T_BINARY = '9'
28 T_REDUNDANT = '+'
29 T_SOUND = 's'
30
31 # Dictionary mapping types to strings
32 typename = {'0': '<TEXT>', '1': '<DIR>', '2': '<CSO>', '3': '<ERROR>', \
33 '4': '<BINHEX>', '5': '<DOS>', '6': '<UUENCODE>', '7': '<SEARCH>', \
34 '8': '<TELNET>', '9': '<BINARY>', '+': '<REDUNDANT>', 's': '<SOUND>'}
35
36 # Oft-used characters and strings
37 CRLF = '\r\n'
38 TAB = '\t'
39
40 # Open a TCP connection to a given host and port
41 def open_socket(host, port):
42 if not port:
43 port = DEF_PORT
44 elif type(port) == type(''):
45 port = string.atoi(port)
46 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
47 s.connect((host, port))
48 return s
49
50 # Send a selector to a given host and port, return a file with the reply
51 def send_request(selector, host, port):
52 s = open_socket(host, port)
53 s.send(selector + CRLF)
54 s.shutdown(1)
55 return s.makefile('r')
56
57 # Get a menu in the form of a list of entries
58 def get_menu(selector, host, port):
59 f = send_request(selector, host, port)
60 list = []
61 while 1:
62 line = f.readline()
63 if not line:
64 print '(Unexpected EOF from server)'
65 break
66 if line[-2:] == CRLF:
67 line = line[:-2]
68 elif line[-1:] in CRLF:
69 line = line[:-1]
70 if line == '.':
71 break
72 if not line:
73 print '(Empty line from server)'
74 continue
75 typechar = line[0]
76 parts = string.splitfields(line[1:], TAB)
77 if len(parts) < 4:
78 print '(Bad line from server: %r)' % (line,)
79 continue
80 if len(parts) > 4:
81 print '(Extra info from server: %r)' % (parts[4:],)
82 parts.insert(0, typechar)
83 list.append(parts)
84 f.close()
85 return list
86
87 # Get a text file as a list of lines, with trailing CRLF stripped
88 def get_textfile(selector, host, port):
89 list = []
90 get_alt_textfile(selector, host, port, list.append)
91 return list
92
93 # Get a text file and pass each line to a function, with trailing CRLF stripped
94 def get_alt_textfile(selector, host, port, func):
95 f = send_request(selector, host, port)
96 while 1:
97 line = f.readline()
98 if not line:
99 print '(Unexpected EOF from server)'
100 break
101 if line[-2:] == CRLF:
102 line = line[:-2]
103 elif line[-1:] in CRLF:
104 line = line[:-1]
105 if line == '.':
106 break
107 if line[:2] == '..':
108 line = line[1:]
109 func(line)
110 f.close()
111
112 # Get a binary file as one solid data block
113 def get_binary(selector, host, port):
114 f = send_request(selector, host, port)
115 data = f.read()
116 f.close()
117 return data
118
119 # Get a binary file and pass each block to a function
120 def get_alt_binary(selector, host, port, func, blocksize):
121 f = send_request(selector, host, port)
122 while 1:
123 data = f.read(blocksize)
124 if not data:
125 break
126 func(data)
127
128 # A *very* simple interactive browser
129
130 # Browser main command, has default arguments
131 def browser(*args):
132 selector = DEF_SELECTOR
133 host = DEF_HOST
134 port = DEF_PORT
135 n = len(args)
136 if n > 0 and args[0]:
137 selector = args[0]
138 if n > 1 and args[1]:
139 host = args[1]
140 if n > 2 and args[2]:
141 port = args[2]
142 if n > 3:
143 raise RuntimeError, 'too many args'
144 try:
145 browse_menu(selector, host, port)
146 except socket.error, msg:
147 print 'Socket error:', msg
148 sys.exit(1)
149 except KeyboardInterrupt:
150 print '\n[Goodbye]'
151
152 # Browse a menu
153 def browse_menu(selector, host, port):
154 list = get_menu(selector, host, port)
155 while 1:
156 print '----- MENU -----'
157 print 'Selector:', repr(selector)
158 print 'Host:', host, ' Port:', port
159 print
160 for i in range(len(list)):
161 item = list[i]
162 typechar, description = item[0], item[1]
163 print string.rjust(repr(i+1), 3) + ':', description,
164 if typename.has_key(typechar):
165 print typename[typechar]
166 else:
167 print '<TYPE=' + repr(typechar) + '>'
168 print
169 while 1:
170 try:
171 str = raw_input('Choice [CR == up a level]: ')
172 except EOFError:
173 print
174 return
175 if not str:
176 return
177 try:
178 choice = string.atoi(str)
179 except string.atoi_error:
180 print 'Choice must be a number; try again:'
181 continue
182 if not 0 < choice <= len(list):
183 print 'Choice out of range; try again:'
184 continue
185 break
186 item = list[choice-1]
187 typechar = item[0]
188 [i_selector, i_host, i_port] = item[2:5]
189 if typebrowser.has_key(typechar):
190 browserfunc = typebrowser[typechar]
191 try:
192 browserfunc(i_selector, i_host, i_port)
193 except (IOError, socket.error):
194 print '***', sys.exc_type, ':', sys.exc_value
195 else:
196 print 'Unsupported object type'
197
198 # Browse a text file
199 def browse_textfile(selector, host, port):
200 x = None
201 try:
202 p = os.popen('${PAGER-more}', 'w')
203 x = SaveLines(p)
204 get_alt_textfile(selector, host, port, x.writeln)
205 except IOError, msg:
206 print 'IOError:', msg
207 if x:
208 x.close()
209 f = open_savefile()
210 if not f:
211 return
212 x = SaveLines(f)
213 try:
214 get_alt_textfile(selector, host, port, x.writeln)
215 print 'Done.'
216 except IOError, msg:
217 print 'IOError:', msg
218 x.close()
219
220 # Browse a search index
221 def browse_search(selector, host, port):
222 while 1:
223 print '----- SEARCH -----'
224 print 'Selector:', repr(selector)
225 print 'Host:', host, ' Port:', port
226 print
227 try:
228 query = raw_input('Query [CR == up a level]: ')
229 except EOFError:
230 print
231 break
232 query = string.strip(query)
233 if not query:
234 break
235 if '\t' in query:
236 print 'Sorry, queries cannot contain tabs'
237 continue
238 browse_menu(selector + TAB + query, host, port)
239
240 # "Browse" telnet-based information, i.e. open a telnet session
241 def browse_telnet(selector, host, port):
242 if selector:
243 print 'Log in as', repr(selector)
244 if type(port) <> type(''):
245 port = repr(port)
246 sts = os.system('set -x; exec telnet ' + host + ' ' + port)
247 if sts:
248 print 'Exit status:', sts
249
250 # "Browse" a binary file, i.e. save it to a file
251 def browse_binary(selector, host, port):
252 f = open_savefile()
253 if not f:
254 return
255 x = SaveWithProgress(f)
256 get_alt_binary(selector, host, port, x.write, 8*1024)
257 x.close()
258
259 # "Browse" a sound file, i.e. play it or save it
260 def browse_sound(selector, host, port):
261 browse_binary(selector, host, port)
262
263 # Dictionary mapping types to browser functions
264 typebrowser = {'0': browse_textfile, '1': browse_menu, \
265 '4': browse_binary, '5': browse_binary, '6': browse_textfile, \
266 '7': browse_search, \
267 '8': browse_telnet, '9': browse_binary, 's': browse_sound}
268
269 # Class used to save lines, appending a newline to each line
270 class SaveLines:
271 def __init__(self, f):
272 self.f = f
273 def writeln(self, line):
274 self.f.write(line + '\n')
275 def close(self):
276 sts = self.f.close()
277 if sts:
278 print 'Exit status:', sts
279
280 # Class used to save data while showing progress
281 class SaveWithProgress:
282 def __init__(self, f):
283 self.f = f
284 def write(self, data):
285 sys.stdout.write('#')
286 sys.stdout.flush()
287 self.f.write(data)
288 def close(self):
289 print
290 sts = self.f.close()
291 if sts:
292 print 'Exit status:', sts
293
294 # Ask for and open a save file, or return None if not to save
295 def open_savefile():
296 try:
297 savefile = raw_input( \
298 'Save as file [CR == don\'t save; |pipeline or ~user/... OK]: ')
299 except EOFError:
300 print
301 return None
302 savefile = string.strip(savefile)
303 if not savefile:
304 return None
305 if savefile[0] == '|':
306 cmd = string.strip(savefile[1:])
307 try:
308 p = os.popen(cmd, 'w')
309 except IOError, msg:
310 print repr(cmd), ':', msg
311 return None
312 print 'Piping through', repr(cmd), '...'
313 return p
314 if savefile[0] == '~':
315 savefile = os.path.expanduser(savefile)
316 try:
317 f = open(savefile, 'w')
318 except IOError, msg:
319 print repr(savefile), ':', msg
320 return None
321 print 'Saving to', repr(savefile), '...'
322 return f
323
324 # Test program
325 def test():
326 if sys.argv[4:]:
327 print 'usage: gopher [ [selector] host [port] ]'
328 sys.exit(2)
329 elif sys.argv[3:]:
330 browser(sys.argv[1], sys.argv[2], sys.argv[3])
331 elif sys.argv[2:]:
332 try:
333 port = string.atoi(sys.argv[2])
334 selector = ''
335 host = sys.argv[1]
336 except string.atoi_error:
337 selector = sys.argv[1]
338 host = sys.argv[2]
339 port = ''
340 browser(selector, host, port)
341 elif sys.argv[1:]:
342 browser('', sys.argv[1])
343 else:
344 browser()
345
346 # Call the test program as a main program
347 test()