1 """Gopher protocol client interface."""
3 __all__
= ["send_selector","send_query"]
5 # Default selector, host and port
7 DEF_HOST
= 'gopher.micro.umn.edu'
10 # Recognized file types
32 A_HTML
= 'h' # HTML file
33 A_WWW
= 'w' # WWW address
40 _type_to_name_map
= {}
41 def type_to_name(gtype
):
42 """Map all file types to strings; unknown types become TYPE='x'."""
43 global _type_to_name_map
44 if _type_to_name_map
=={}:
47 _type_to_name_map
[eval(name
)] = name
[2:]
48 if gtype
in _type_to_name_map
:
49 return _type_to_name_map
[gtype
]
50 return 'TYPE=' + `gtype`
52 # Names for characters and strings
56 def send_selector(selector
, host
, port
= 0):
57 """Send a selector to a given host and port, return a file with the reply."""
62 host
, port
= host
[:i
], int(host
[i
+1:])
65 elif type(port
) == type(''):
67 s
= socket
.socket(socket
.AF_INET
, socket
.SOCK_STREAM
)
68 s
.connect((host
, port
))
69 s
.sendall(selector
+ CRLF
)
71 return s
.makefile('rb')
73 def send_query(selector
, query
, host
, port
= 0):
74 """Send a selector and a query string."""
75 return send_selector(selector
+ '\t' + query
, host
, port
)
77 def path_to_selector(path
):
78 """Takes a path as returned by urlparse and returns the appropriate selector."""
82 return path
[2:] # Cuts initial slash and data type identifier
84 def path_to_datatype_name(path
):
85 """Takes a path as returned by urlparse and maps it to a string.
86 See section 3.4 of RFC 1738 for details."""
88 # No way to tell, although "INDEX" is likely
89 return "TYPE='unknown'"
91 return type_to_name(path
[1])
93 # The following functions interpret the data returned by the gopher
94 # server according to the expected type, e.g. textfile or directory
97 """Get a directory in the form of a list of entries."""
102 print '(Unexpected EOF from server)'
104 if line
[-2:] == CRLF
:
106 elif line
[-1:] in CRLF
:
111 print '(Empty line from server)'
114 parts
= line
[1:].split(TAB
)
116 print '(Bad line from server:', `line`
, ')'
119 if parts
[4:] != ['+']:
120 print '(Extra info from server:',
124 parts
.insert(0, gtype
)
129 """Get a text file as a list of lines, with trailing CRLF stripped."""
131 get_alt_textfile(f
, list.append
)
134 def get_alt_textfile(f
, func
):
135 """Get a text file and pass each line to a function, with trailing CRLF stripped."""
139 print '(Unexpected EOF from server)'
141 if line
[-2:] == CRLF
:
143 elif line
[-1:] in CRLF
:
152 """Get a binary file as one solid data block."""
156 def get_alt_binary(f
, func
, blocksize
):
157 """Get a binary file and pass each block to a function."""
159 data
= f
.read(blocksize
)
165 """Trivial test program."""
168 opts
, args
= getopt
.getopt(sys
.argv
[1:], '')
169 selector
= DEF_SELECTOR
179 type, selector
= type[0], type
190 f
= send_query(selector
, query
, host
)
192 f
= send_selector(selector
, host
)
194 list = get_textfile(f
)
195 for item
in list: print item
196 elif type in (A_MENU
, A_INDEX
):
197 list = get_directory(f
)
198 for item
in list: print item
201 print 'binary data:', len(data
), 'bytes:', `data
[:100]`
[:40]
203 # Run the test when run as script
204 if __name__
== '__main__':