|
1 # fileserver.py |
|
2 # |
|
3 # A simple file transfer server for Series 60 Python environment. |
|
4 # |
|
5 # Copyright (c) 2005 Nokia Corporation |
|
6 # |
|
7 # Licensed under the Apache License, Version 2.0 (the "License"); |
|
8 # you may not use this file except in compliance with the License. |
|
9 # You may obtain a copy of the License at |
|
10 # |
|
11 # http://www.apache.org/licenses/LICENSE-2.0 |
|
12 # |
|
13 # Unless required by applicable law or agreed to in writing, software |
|
14 # distributed under the License is distributed on an "AS IS" BASIS, |
|
15 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
16 # See the License for the specific language governing permissions and |
|
17 # limitations under the License. |
|
18 |
|
19 |
|
20 import binascii |
|
21 |
|
22 #DEBUGLOG=lambda x: sys.stdout.write(x+"\n") |
|
23 DEBUGLOG=lambda x: 0 |
|
24 |
|
25 def file_checksums(filelist): |
|
26 retval={} |
|
27 for fname in filelist: |
|
28 try: |
|
29 f=open(fname,'rb') |
|
30 checksum=binascii.crc32(f.read()) |
|
31 f.close() |
|
32 except: |
|
33 checksum=None |
|
34 retval[fname]=checksum |
|
35 return retval |
|
36 |
|
37 class fileserver: |
|
38 def __init__(self,sock): |
|
39 self.sock=sock |
|
40 self.commands={'quit': self.cmd_quit, |
|
41 'get': self.cmd_get, |
|
42 'put': self.cmd_put, |
|
43 'exec': self.cmd_exec, |
|
44 'eval': self.cmd_eval} |
|
45 def cmd_quit(self,line): |
|
46 self.finished=True |
|
47 def cmd_invalid(self,line): |
|
48 print >>sys.stderr,'Invalid command '+line, |
|
49 self.finished=True |
|
50 def cmd_get(self,cmdline): |
|
51 filename=eval(cmdline[4:]) |
|
52 DEBUGLOG("get "+filename) |
|
53 f=open(filename,'rb') |
|
54 content=f.read() |
|
55 f.close() |
|
56 self.senddata(content) |
|
57 def cmd_put(self,cmdline): |
|
58 words=cmdline.split() |
|
59 filename=eval(words[1]) |
|
60 DEBUGLOG("put "+filename) |
|
61 content=self.recvdata() |
|
62 f=open(filename,'wb') |
|
63 f.write(content) |
|
64 f.close() |
|
65 print "Wrote %d bytes to %s."%(len(content),filename) |
|
66 def senddata(self,data): |
|
67 DEBUGLOG("Content-Length: %d"%len(data)) |
|
68 self.write('Content-Length: '+str(len(data))+'\n'+ |
|
69 'CRC32: '+str(binascii.crc32(data))+'\n') |
|
70 sentbytes=0 |
|
71 # Send the data in little bits because the Bluetooth serial |
|
72 # connection may lose data on large sends. |
|
73 MAX_SEND=2048 |
|
74 while sentbytes<len(data): |
|
75 n=min(len(data),MAX_SEND) |
|
76 self.write(data[sentbytes:sentbytes+n]) |
|
77 sentbytes+=n |
|
78 print "Sent %d bytes."%sentbytes |
|
79 def recvdata(self): |
|
80 DEBUGLOG("Waiting for data...") |
|
81 header_lines=[self.readline() for x in range(2)] |
|
82 header=dict([x.rstrip().split(': ') for x in header_lines]) |
|
83 content_length=int(header['Content-Length']) |
|
84 crc32=int(header['CRC32']) |
|
85 DEBUGLOG("Content-Length: %d"%content_length) |
|
86 recvbytes=0 |
|
87 content=[] |
|
88 DEBUGLOG("Receiving data...") |
|
89 while recvbytes<content_length: |
|
90 recvstring=self.sock.recv(min(content_length-recvbytes,2048)) |
|
91 recvbytes+=len(recvstring) |
|
92 #print "Received: %d bytes (%3.1f%%)\r"%(recvbytes,(100.*recvbytes/content_length)), |
|
93 content.append(recvstring) |
|
94 print "Received %d bytes."%recvbytes |
|
95 content=''.join(content) |
|
96 if crc32 != binascii.crc32(content): |
|
97 print "*** CRC error!" |
|
98 return content |
|
99 def cmd_exec(self,cmdline): |
|
100 # command=eval(cmdline[5:]) |
|
101 command=eval(self.recvdata()) |
|
102 DEBUGLOG("exec "+command) |
|
103 try: |
|
104 exec command in globals() |
|
105 result=(0,'') |
|
106 except: |
|
107 import traceback |
|
108 result=(1,apply(traceback.format_exception,sys.exc_info())) |
|
109 self.senddata(repr(result)) |
|
110 |
|
111 def cmd_eval(self,cmdline): |
|
112 expr=eval(self.recvdata()) |
|
113 #expr=eval(cmdline[5:]) |
|
114 DEBUGLOG("eval "+expr) |
|
115 # two eval's because we need to first get rid of one level of |
|
116 # quoting. |
|
117 result='' |
|
118 try: |
|
119 value=eval(expr,globals()) |
|
120 result=(0,value) |
|
121 except: |
|
122 import traceback |
|
123 result=(1,apply(traceback.format_exception,sys.exc_info())) |
|
124 self.senddata(repr(result)) |
|
125 |
|
126 def readline(self): |
|
127 s=[] |
|
128 while 1: |
|
129 c=self.sock.recv(1) |
|
130 #self.sock.send(c) |
|
131 s.append(c) |
|
132 # We support just sane line-endings here. |
|
133 if c=='\n': |
|
134 break |
|
135 return ''.join(s) |
|
136 def write(self,msg): |
|
137 self.sock.send(msg) |
|
138 def run(self): |
|
139 self.finished=False |
|
140 while not self.finished: |
|
141 cmdline=self.readline().rstrip() |
|
142 print "Received: "+cmdline |
|
143 words=cmdline.split() |
|
144 if len(words)>0: |
|
145 cmd=words[0] |
|
146 DEBUGLOG("Running command: "+cmdline) |
|
147 self.commands.get(cmd,self.cmd_invalid)(cmdline) |
|
148 |
|
149 if __name__ == '__main__': |
|
150 import sys |
|
151 from e32socket import * |
|
152 import e32 |
|
153 if not e32.is_ui_thread(): |
|
154 f=open('c:/pythonout.txt','at') |
|
155 sys.stdout=f |
|
156 sys.stderr=f |
|
157 |
|
158 print "Starting server" |
|
159 use_tcp=0 |
|
160 |
|
161 if use_tcp: |
|
162 s=socket(AF_INET,SOCK_STREAM) |
|
163 addr=('127.0.0.1',1025) |
|
164 s.bind(addr) |
|
165 s.listen(1) |
|
166 |
|
167 while 1: |
|
168 print "Waiting" |
|
169 (sock,remoteaddr)=s.accept() |
|
170 print "Connected" |
|
171 server=fileserver(sock) |
|
172 try: |
|
173 server.run() |
|
174 except: |
|
175 import traceback |
|
176 traceback.print_exc() |
|
177 sock.close() |
|
178 else: |
|
179 s=socket(AF_BT,SOCK_STREAM) |
|
180 try: |
|
181 f=open('c:/system/apps/python/fileserver_conf.txt') |
|
182 conf=eval(f.read()) |
|
183 f.close() |
|
184 addr=conf['target'] |
|
185 except: |
|
186 addr=('00:20:e0:76:c3:52',10) |
|
187 conf={} |
|
188 #addr=('00:20:e0:76:c3:52',9) |
|
189 print "Connecting to "+`addr` |
|
190 s.connect(addr) |
|
191 server=fileserver(s) |
|
192 try: |
|
193 server.run() |
|
194 except: |
|
195 import traceback |
|
196 traceback.print_exc() |
|
197 s.close() |
|
198 print "Server finished." |
|
199 |