|
1 # |
|
2 # fileclient.py |
|
3 # |
|
4 # A client library for the simple file transfer server for Series 60 Python environment. |
|
5 # |
|
6 # Copyright (c) 2005 Nokia Corporation |
|
7 # |
|
8 # Licensed under the Apache License, Version 2.0 (the "License"); |
|
9 # you may not use this file except in compliance with the License. |
|
10 # You may obtain a copy of the License at |
|
11 # |
|
12 # http://www.apache.org/licenses/LICENSE-2.0 |
|
13 # |
|
14 # Unless required by applicable law or agreed to in writing, software |
|
15 # distributed under the License is distributed on an "AS IS" BASIS, |
|
16 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
17 # See the License for the specific language governing permissions and |
|
18 # limitations under the License. |
|
19 |
|
20 |
|
21 import os |
|
22 import sys |
|
23 import binascii |
|
24 import ntpath |
|
25 |
|
26 symbianbasename=ntpath.basename |
|
27 |
|
28 class fileclient: |
|
29 def __init__(self,sock,verbose=0): |
|
30 self.sock=sock |
|
31 self.verbose=verbose |
|
32 if verbose: |
|
33 self.log=sys.stdout.write |
|
34 else: |
|
35 self.log=lambda x:0 |
|
36 def recvdata(self): |
|
37 #self.log("Waiting for content length..." |
|
38 header_lines=[self.readline() for x in range(2)] |
|
39 header=dict([x.rstrip().split(': ') for x in header_lines]) |
|
40 content_length=int(header['Content-Length']) |
|
41 crc32=int(header['CRC32']) |
|
42 self.log("Content-Length: %d"%content_length+"\n") |
|
43 recvbytes=0 |
|
44 content=[] |
|
45 #self.log("Receiving data...") |
|
46 while recvbytes<content_length: |
|
47 recvstring=self.sock.recv(min(content_length-recvbytes,2048)) |
|
48 recvbytes+=len(recvstring) |
|
49 self.log("Received: %d bytes (%3.1f%%)\r"%(recvbytes,(100.*recvbytes/content_length))) |
|
50 sys.stdout.flush() |
|
51 content.append(recvstring) |
|
52 self.log("Received: %d bytes. "%(recvbytes)+"\n") |
|
53 content=''.join(content) |
|
54 if crc32 != binascii.crc32(content): |
|
55 raise IOError("CRC error while receiving data") |
|
56 return content |
|
57 def senddata(self,data): |
|
58 #print "Sending data..." |
|
59 self.log("Content-Length: %d"%len(data)+"\n") |
|
60 self.write('Content-Length: '+str(len(data))+'\n'+ |
|
61 'CRC32: '+str(binascii.crc32(data))+'\n') |
|
62 sentbytes=0 |
|
63 # Send the data in little bits because the Bluetooth serial |
|
64 # connection may lose data on large sends. |
|
65 MAX_SEND=2048 |
|
66 while sentbytes<len(data): |
|
67 n=min(len(data)-sentbytes,MAX_SEND) |
|
68 self.write(data[sentbytes:sentbytes+n]) |
|
69 sentbytes+=n |
|
70 self.log("Sent: %d bytes (%3.1f%%)\r"%(sentbytes,(100.*sentbytes/len(data)))) |
|
71 sys.stdout.flush() |
|
72 self.log("Sent: %d bytes. "%(sentbytes)+"\n") |
|
73 def get(self,filename): |
|
74 self.log("get "+filename+"\n") |
|
75 self.write("get "+repr(filename)+"\n") |
|
76 return self.recvdata() |
|
77 def put(self,filename,content): |
|
78 self.log("put "+filename+"\n") |
|
79 # self.write("put "+repr(filename)+" "+str(len(content))+'\n') |
|
80 self.write("put "+repr(filename)+"\n") |
|
81 self.senddata(content) |
|
82 def download(self,remotefile,localfile=None): |
|
83 if localfile is None: |
|
84 localfile=symbianbasename(remotefile) |
|
85 content=self.get(remotefile) |
|
86 f=open(localfile,'wb') |
|
87 f.write(content) |
|
88 f.close() |
|
89 def upload(self,remotefile,localfile=None): |
|
90 if localfile is None: |
|
91 localfile=symbianbasename(remotefile) |
|
92 f=open(localfile,'rb') |
|
93 content=f.read() |
|
94 f.close() |
|
95 self.put(remotefile,content) |
|
96 def eval(self,expr): |
|
97 self.log("eval "+expr+"\n") |
|
98 self.write("eval\n")# "+repr(expr)+"\n") |
|
99 self.senddata(repr(expr)) |
|
100 result=eval(self.recvdata()) |
|
101 if result[0]!=0: |
|
102 raise "Exception on server side: "+''.join(result[1]) |
|
103 else: |
|
104 return result[1] |
|
105 def exec_(self,expr): |
|
106 self.log("exec "+expr+"\n") |
|
107 self.write("exec\n") |
|
108 self.senddata(repr(expr)) |
|
109 #self.write("exec "+repr(expr)+"\n") |
|
110 result=eval(self.recvdata()) |
|
111 if result[0]!=0: |
|
112 raise "Exception on server side: "+''.join(result[1]) |
|
113 def killserver(self): |
|
114 self.log("Sending quit command to server..."+"\n") |
|
115 self.write('quit\n') |
|
116 def readline(self): |
|
117 s=[] |
|
118 while 1: |
|
119 c=self.sock.recv(1) |
|
120 if c=='': |
|
121 continue |
|
122 #self.sock.send(c) |
|
123 s.append(c) |
|
124 # We support just sane line-endings here. |
|
125 if c=='\n': |
|
126 break |
|
127 return ''.join(s) |
|
128 def write(self,msg): |
|
129 self.sock.send(msg) |
|
130 |
|
131 class filesocket: |
|
132 def __init__(self,file): |
|
133 self.file=file |
|
134 def recv(self,n=1): |
|
135 return self.file.read(n) |
|
136 def send(self,msg): |
|
137 n=self.file.write(msg) |
|
138 self.file.flush() |
|
139 return n |
|
140 |
|
141 def connect(port='/dev/ttyS4',use_tcp=0,verbose=0): |
|
142 if use_tcp: |
|
143 import socket |
|
144 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) |
|
145 addr=('127.0.0.1',1025) |
|
146 print "Connecting via TCP to "+`addr`+"...", |
|
147 sys.stdout.flush() |
|
148 s.connect(addr) |
|
149 client=fileclient(s,verbose) |
|
150 print "ok." |
|
151 else: |
|
152 print "Connecting to serial port "+port+"...", |
|
153 sys.stdout.flush() |
|
154 f=open(port,'r+b',0) |
|
155 fs=filesocket(f) |
|
156 client=fileclient(fs,verbose) |
|
157 print "ok." |
|
158 return client |