Tizen 2.1 base
[platform/upstream/hplip.git] / fax / ledmfax.py
1 # -*- coding: utf-8 -*-
2 #
3 # (c) Copyright 2003-2007 Hewlett-Packard Development Company, L.P.
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 #
19 # Author: k,shunmugaraj
20 # Date Created: 10/10/2010
21
22 from __future__ import division
23
24 # Std Lib
25 import sys
26 import os
27 import time
28 import cStringIO
29 import urllib # TODO: Replace with urllib2 (urllib is deprecated in Python 3.0)
30 import re
31 import threading
32 import struct
33 import time
34 import xml.parsers.expat as expat
35 from stat import *
36 # Local
37 from base.g import *
38 from base.codes import *
39 from base import device, utils, codes, dime, status
40 from fax import *
41
42
43 # **************************************************************************** #
44
45 http_result_pat = re.compile("""HTTP/\d.\d\s(\d+)""", re.I)
46
47 HTTP_OK = 200
48 HTTP_ACCEPTED = 202
49 HTTP_CREATED = 201
50 HTTP_ERROR = 500
51
52 PIXELS_PER_LINE = 1728
53
54 # **************************************************************************** #
55 setPhoneNumXML = """<?xml version=\"1.0\" encoding=\"UTF-8\"?><!--Sample XML file generated by XMLSPY v5 rel. 4 U (http://www.xmlspy.com)--><faxcfgdyn:FaxConfigDyn xmlns:faxcfgdyn=\"http://www.hp.com/schemas/imaging/con/ledm/faxconfigdyn/2009/03/03\" xmlns:dd=\"http://www.hp.com/schemas/imaging/con/dictionaries/1.0/\" xmlns:fax=\"http://www.hp.com/schemas/imaging/con/fax/2008/06/13\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.hp.com/schemas/imaging/con/ledm/faxconfigdyn/2009/03/03 ../schemas/FaxConfigDyn.xsd\"><faxcfgdyn:SystemSettings><dd:PhoneNumber>%s</dd:PhoneNumber></faxcfgdyn:SystemSettings></faxcfgdyn:FaxConfigDyn>"""
56
57 setStationNameXML = """<?xml version=\"1.0\" encoding=\"UTF-8\"?><!--Sample XML file generated by XMLSPY v5 rel. 4 U (http://www.xmlspy.com)--><faxcfgdyn:FaxConfigDyn xmlns:faxcfgdyn=\"http://www.hp.com/schemas/imaging/con/ledm/faxconfigdyn/2009/03/03\" xmlns:dd=\"http://www.hp.com/schemas/imaging/con/dictionaries/1.0/\" xmlns:fax=\"http://www.hp.com/schemas/imaging/con/fax/2008/06/13\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.hp.com/schemas/imaging/con/ledm/faxconfigdyn/2009/03/03 ../schemas/FaxConfigDyn.xsd\"><faxcfgdyn:SystemSettings><dd:CompanyName>%s</dd:CompanyName></faxcfgdyn:SystemSettings></faxcfgdyn:FaxConfigDyn>"""
58
59 createJobXML = """<?xml version=\"1.0\" encoding=\"UTF-8\"?><!--THIS DATA SUBJECT TO DISCLAIMER(S)INCLUDED WITH THE PRODUCT OF ORIGIN.--><fpsdyn:FaxPCSendDyn xmlns:fpsdyn=\"http://www.hp.com/schemas/imaging/con/ledm/printtofaxdyn/2008/11/24\" xmlns:dd=\"http://www.hp.com/schemas/imaging/con/dictionaries/1.0/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.hp.com/schemas/imaging/con/ledm/printtofaxdyn/2008/11/24 ../schemas/FaxPCSendDyn.xsd\"><dd:Version><dd:Revision>1.0</dd:Revision></dd:Version><fpsdyn:FaxPCSendConfig><fpsdyn:FaxTxPhoneNumber>%s</fpsdyn:FaxTxPhoneNumber><fpsdyn:NumPages>%d</fpsdyn:NumPages><fpsdyn:TTI_Control>TTI_Off</fpsdyn:TTI_Control></fpsdyn:FaxPCSendConfig></fpsdyn:FaxPCSendDyn>"""
60
61 pageConfigXML = """<?xml version=\"1.0\" encoding=\"UTF-8\" ?><!-- THIS DATA SUBJECT TO DISCLAIMER(S)INCLUDED WITH THE PRODUCT OF ORIGIN.--><fpsdyn:FaxPCSendDyn xmlns:fpsdyn=\"http://www.hp.com/schemas/imaging/con/ledm/printtofaxdyn/2008/11/24\" xmlns:dd=\"http://www.hp.com/schemas/imaging/con/dictionaries/1.0/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.hp.com/schemas/imaging/con/ledm/printtofaxdyn/2008/11/24 ../schemas/FaxPCSendDyn.xsd\"><dd:Version><dd:Revision>1.0</dd:Revision></dd:Version><fpsdyn:PageConfig><fpsdyn:PageNum>%d</fpsdyn:PageNum><fpsdyn:Width>1728</fpsdyn:Width><fpsdyn:Height>2200</fpsdyn:Height><fpsdyn:ImageType>BW</fpsdyn:ImageType><fpsdyn:Compression>mh</fpsdyn:Compression><fpsdyn:HorizontalDPI>%d</fpsdyn:HorizontalDPI><fpsdyn:VerticalDPI>%d</fpsdyn:VerticalDPI></fpsdyn:PageConfig></fpsdyn:FaxPCSendDyn>"""
62
63 cancelJobXML = """<?xml version=\"1.0\" encoding=\"UTF-8\"?><!-- THIS DATA SUBJECT TO DISCLAIMER(S) INCLUDED WITH THE PRODUCT OF ORIGIN.--><j:Job xmlns:j=\"http://www.hp.com/schemas/imaging/con/ledm/jobs/2009/04/30\" xmlns:dd=\"http://www.hp.com/schemas/imaging/con/dictionaries/1.0/\" xmlns:fax=\"http://www.hp.com/schemas/imaging/con/fax/2008/06/13\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.hp.com/schemas/imaging/con/ledm/jobs/2009/04/30 ../schemas/Jobs.xsd\"><j:JobUrl>%s</j:JobUrl><j:JobState>Canceled</j:JobState></j:Job>"""
64
65 # **************************************************************************** #
66 class LEDMFaxDevice(FaxDevice):
67
68     def __init__(self, device_uri=None, printer_name=None,
69                  callback=None,
70                  fax_type=FAX_TYPE_NONE,
71                  disable_dbus=False):
72
73         FaxDevice.__init__(self, device_uri,
74                            printer_name,
75                            callback, fax_type,
76                            disable_dbus)
77
78         self.send_fax_thread = None
79         self.upload_log_thread = None
80
81         if self.bus == 'net':
82             self.http_host = self.host
83         else:
84             self.http_host = 'localhost'  
85
86        
87     def put(self, url, post):
88         data = """PUT %s HTTP/1.1\r
89 Connection: Keep-alive\r
90 User-agent: hplip/2.0\r
91 Host: %s\r
92 Content-length: %d\r
93 \r
94 %s""" % (url, self.http_host, len(post), post)
95         log.log_data(data)
96         self.writeLEDM(data)
97         response = cStringIO.StringIO()
98
99         while self.readLEDM(512, response, timeout=5):
100             pass
101
102         response = response.getvalue()
103         log.log_data(response)
104         self.closeLEDM()        
105         
106         match = http_result_pat.match(response)
107         if match is None: return HTTP_OK
108         try:
109             code = int(match.group(1))
110         except (ValueError, TypeError):
111             code = HTTP_ERROR
112
113         return code == HTTP_OK
114
115
116     def setPhoneNum(self, num):
117         xml = setPhoneNumXML %(num)
118         log.debug("SetPhoneNum:xml Value:%s" %xml)
119         return self.put("/DevMgmt/FaxConfigDyn.xml", xml)
120
121
122     def getPhoneNum(self):
123         return self.readAttributeFromXml("/DevMgmt/FaxConfigDyn.xml",'faxcfgdyn:faxconfigdyn-faxcfgdyn:systemsettings-dd:phonenumber')
124
125     phone_num = property(getPhoneNum, setPhoneNum)
126
127
128     def setStationName(self, name):
129         xml = setStationNameXML %(name)
130         return self.put("/DevMgmt/FaxConfigDyn.xml", xml)
131
132
133     def getStationName(self):
134         return self.readAttributeFromXml("/DevMgmt/FaxConfigDyn.xml",'faxcfgdyn:faxconfigdyn-faxcfgdyn:systemsettings-dd:companyname')
135
136     station_name = property(getStationName, setStationName) 
137
138     def sendFaxes(self, phone_num_list, fax_file_list, cover_message='', cover_re='',
139                   cover_func=None, preserve_formatting=False, printer_name='',
140                   update_queue=None, event_queue=None):
141
142         if not self.isSendFaxActive():
143
144             self.send_fax_thread = LEDMFaxSendThread(self, self.service, phone_num_list, fax_file_list,
145                                                      cover_message, cover_re, cover_func,
146                                                      preserve_formatting,
147                                                      printer_name, update_queue,
148                                                      event_queue)
149
150             self.send_fax_thread.start()
151             return True
152         else:
153             return False
154
155
156 # **************************************************************************** #
157 class LEDMFaxSendThread(FaxSendThread):
158     def __init__(self, dev, service, phone_num_list, fax_file_list,
159                  cover_message='', cover_re='', cover_func=None, preserve_formatting=False,
160                  printer_name='', update_queue=None, event_queue=None):
161
162         FaxSendThread.__init__(self, dev, service, phone_num_list, fax_file_list,
163              cover_message, cover_re, cover_func, preserve_formatting,
164              printer_name, update_queue, event_queue)       
165
166         if dev.bus == 'net':
167             self.http_host = "%s:8080" % self.dev.host
168         else:
169             self.http_host = 'localhost:8080'
170         
171
172     def run(self):
173         
174         STATE_DONE = 0
175         STATE_ABORTED = 10
176         STATE_SUCCESS = 20
177         STATE_BUSY = 25
178         STATE_READ_SENDER_INFO = 30
179         STATE_PRERENDER = 40
180         STATE_COUNT_PAGES = 50
181         STATE_NEXT_RECIPIENT = 60
182         STATE_COVER_PAGE = 70
183         STATE_SINGLE_FILE = 80
184         STATE_MERGE_FILES = 90
185         STATE_SINGLE_FILE = 100
186         STATE_SEND_FAX = 110
187         STATE_CLEANUP = 120
188         STATE_ERROR = 130
189
190         next_recipient = self.next_recipient_gen()
191
192         state = STATE_READ_SENDER_INFO
193         error_state = STATUS_ERROR
194         self.rendered_file_list = []
195
196         while state != STATE_DONE: # --------------------------------- Fax state machine
197             if self.check_for_cancel():
198                 state = STATE_ABORTED
199
200             log.debug("STATE=(%d, 0, 0)" % state)
201
202             if state == STATE_ABORTED: # ----------------------------- Aborted (10, 0, 0)
203                 log.error("Aborted by user.")
204                 self.write_queue((STATUS_IDLE, 0, ''))
205                 state = STATE_CLEANUP
206
207
208             elif state == STATE_SUCCESS: # --------------------------- Success (20, 0, 0)
209                 log.debug("Success.")
210                 self.write_queue((STATUS_COMPLETED, 0, ''))
211                 state = STATE_CLEANUP
212
213
214             elif state == STATE_ERROR: # ----------------------------- Error (130, 0, 0)
215                 log.error("Error, aborting.")
216                 self.write_queue((error_state, 0, ''))
217                 state = STATE_CLEANUP           
218
219
220             elif state == STATE_BUSY: # ------------------------------ Busy (25, 0, 0)
221                 log.error("Device busy, aborting.")
222                 self.write_queue((STATUS_BUSY, 0, ''))
223                 state = STATE_CLEANUP
224
225
226             elif state == STATE_READ_SENDER_INFO: # ------------------ Get sender info (30, 0, 0)
227                 log.debug("%s State: Get sender info" % ("*"*20))
228                 state = STATE_PRERENDER
229                 try:
230                     try:
231                         self.dev.open()
232                     except Error, e:
233                         log.error("Unable to open device (%s)." % e.msg)
234                         state = STATE_ERROR
235                     else:
236                         try:
237                             self.sender_name = self.dev.station_name
238                             log.debug("Sender name=%s" % self.sender_name)
239                             self.sender_fax = self.dev.phone_num
240                             log.debug("Sender fax=%s" % self.sender_fax)
241                         except Error:
242                             log.error("LEDM GET failed!")
243                             state = STATE_ERROR
244
245                 finally:
246                     self.dev.close()
247
248
249             elif state == STATE_PRERENDER: # --------------------------------- Pre-render non-G4 files (40, 0, 0)
250                 log.debug("%s State: Pre-render non-G4 files" % ("*"*20))
251                 state = self.pre_render(STATE_COUNT_PAGES)
252
253             elif state == STATE_COUNT_PAGES: # -------------------------------- Get total page count (50, 0, 0)
254                 log.debug("%s State: Get total page count" % ("*"*20))
255                 state = self.count_pages(STATE_NEXT_RECIPIENT)
256
257             elif state == STATE_NEXT_RECIPIENT: # ----------------------------- Loop for multiple recipients (60, 0, 0)
258                 log.debug("%s State: Next recipient" % ("*"*20))
259                 state = STATE_COVER_PAGE
260
261                 try:
262                     recipient = next_recipient.next()
263                     log.debug("Processing for recipient %s" % recipient['name'])
264                     self.write_queue((STATUS_SENDING_TO_RECIPIENT, 0, recipient['name']))
265                 except StopIteration:
266                     state = STATE_SUCCESS
267                     log.debug("Last recipient.")
268                     continue
269
270                 recipient_file_list = self.rendered_file_list[:]
271
272
273             elif state == STATE_COVER_PAGE: # ---------------------------------- Create cover page (70, 0, 0)
274                 log.debug("%s State: Render cover page" % ("*"*20))
275                 state = self.cover_page(recipient)
276
277
278             elif state == STATE_SINGLE_FILE: # --------------------------------- Special case for single file (no merge) (80, 0, 0)
279                 log.debug("%s State: Handle single file" % ("*"*20))
280                 state = self.single_file(STATE_SEND_FAX)
281
282             elif state == STATE_MERGE_FILES: # --------------------------------- Merge multiple G4 files (90, 0, 0)
283                 log.debug("%s State: Merge multiple files" % ("*"*20))
284                 state = self.merge_files(STATE_SEND_FAX)
285
286             elif state == STATE_SEND_FAX: # ------------------------------------ Send fax state machine (110, 0, 0)
287                 log.debug("%s State: Send fax" % ("*"*20))
288                 state = STATE_NEXT_RECIPIENT
289
290                 FAX_SEND_STATE_DONE = 0
291                 FAX_SEND_STATE_ABORT = 10
292                 FAX_SEND_STATE_ERROR = 20
293                 FAX_SEND_STATE_BUSY = 25
294                 FAX_SEND_STATE_SUCCESS = 30
295                 FAX_SEND_STATE_DEVICE_OPEN = 40
296                 FAX_SEND_STATE_BEGINJOB = 50
297                 FAX_SEND_STATE_DOWNLOADPAGES = 60
298                 FAX_SEND_STATE_ENDJOB = 70
299                 FAX_SEND_STATE_CANCELJOB = 80
300                 FAX_SEND_STATE_CLOSE_SESSION = 170
301
302                 monitor_state = False
303                 fax_send_state = FAX_SEND_STATE_DEVICE_OPEN
304
305                 while fax_send_state != FAX_SEND_STATE_DONE:
306
307                     if self.check_for_cancel():
308                         log.error("Fax send aborted.")
309                         fax_send_state = FAX_SEND_STATE_ABORT
310
311                     if monitor_state:
312                         fax_state = self.getFaxDownloadState()
313                         if not fax_state in (pml.UPDN_STATE_XFERACTIVE, pml.UPDN_STATE_XFERDONE):
314                             log.error("D/L error state=%d" % fax_state)
315                             fax_send_state = FAX_SEND_STATE_ERROR
316                             state = STATE_ERROR
317
318                     log.debug("STATE=(%d, %d, 0)" % (STATE_SEND_FAX, fax_send_state))
319
320                     if fax_send_state == FAX_SEND_STATE_ABORT: # ----------------- Abort (110, 10, 0)
321                         monitor_state = False
322                         fax_send_state = FAX_SEND_STATE_CANCELJOB
323                         state = STATE_ABORTED
324
325                     elif fax_send_state == FAX_SEND_STATE_ERROR: # --------------- Error (110, 20, 0)
326                         log.error("Fax send error.")
327                         monitor_state = False
328                         fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
329                         state = STATE_ERROR
330
331                     elif fax_send_state == FAX_SEND_STATE_BUSY: # ---------------- Busy (110, 25, 0)
332                         log.error("Fax device busy.")
333                         monitor_state = False
334                         fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
335                         state = STATE_BUSY
336
337                     elif fax_send_state == FAX_SEND_STATE_SUCCESS: # ------------- Success (110, 30, 0)
338                         log.debug("Fax send success.")
339                         monitor_state = False
340                         fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
341                         state = STATE_NEXT_RECIPIENT
342
343                     elif fax_send_state == FAX_SEND_STATE_DEVICE_OPEN: # --------- Device open (110, 40, 0)
344                         log.debug("%s State: Open device" % ("*"*20))
345                         fax_send_state = FAX_SEND_STATE_BEGINJOB
346                         try:
347                             self.dev.open()
348                         except Error, e:
349                             log.error("Unable to open device (%s)." % e.msg)
350                             fax_send_state = FAX_SEND_STATE_ERROR
351                         else:
352                             if self.dev.device_state == DEVICE_STATE_NOT_FOUND:
353                                 fax_send_state = FAX_SEND_STATE_ERROR
354
355                     elif fax_send_state == FAX_SEND_STATE_BEGINJOB: # -------------- BeginJob (110, 50, 0)
356                         log.debug("%s State: BeginJob" % ("*"*20))
357                         try:
358                             ff = file(self.f, 'r')
359                         except IOError:
360                             log.error("Unable to read fax file.")
361                             fax_send_state = FAX_SEND_STATE_ERROR
362                             continue
363                         
364                         try:
365                             header = ff.read(FILE_HEADER_SIZE)
366                         except IOError:
367                             log.error("Unable to read fax file.")
368                             fax_send_state = FAX_SEND_STATE_ERROR
369                             continue                        
370                         
371                         magic, version, total_pages, hort_dpi, vert_dpi, page_size, \
372                             resolution, encoding, reserved1, reserved2 = self.decode_fax_header(header)
373
374                         if magic != 'hplip_g3':
375                             log.error("Invalid file header. Bad magic.")
376                             fax_send_state = FAX_SEND_STATE_ERROR
377                         else:
378                             log.debug("Magic=%s Ver=%d Pages=%d hDPI=%d vDPI=%d Size=%d Res=%d Enc=%d" %
379                                       (magic, version, total_pages, hort_dpi, vert_dpi, page_size,
380                                        resolution, encoding))
381                         
382                         faxnum = recipient['fax'].encode('ascii')                       
383
384                         createJob = createJobXML  %(faxnum, total_pages)
385                         data = self.format_http_post("/FaxPCSend/Job",len(createJob),createJob)
386                         log.log_data(data)                        
387
388                         self.dev.openLEDM()
389                         self.dev.writeLEDM(data)
390                         response = cStringIO.StringIO()
391                         try:
392                             while self.dev.readLEDM(512, response, timeout=5):
393                                 pass
394                         except Error:
395                             fax_send_state = FAX_SEND_STATE_ERROR
396                             self.dev.closeLEDM() 
397                             break
398                         self.dev.closeLEDM()
399
400                         response = response.getvalue()
401                         log.log_data(response)                         
402                         if self.get_error_code(response) == HTTP_CREATED:
403                             fax_send_state = FAX_SEND_STATE_DOWNLOADPAGES
404                         else:
405                             fax_send_state = FAX_SEND_STATE_ERROR
406                             log.error("Create Job request failed")
407                             break
408                         
409                         responsestr = str(response)                        
410                         pos = responsestr.find("/Jobs/JobList/",0,len(responsestr))
411                         pos1 = responsestr.find("Content-Length",0,len(responsestr))
412                         jobListURI = responsestr[pos:pos1].strip()
413                         log.debug("jobListURI = [%s]" %(jobListURI))
414
415                     elif fax_send_state == FAX_SEND_STATE_DOWNLOADPAGES: # -------------- DownloadPages (110, 60, 0)
416                         log.debug("%s State: DownloadPages" % ("*"*20))
417                         page = StringIO()
418                         log.debug("Total Number of pages are:%d" %total_pages)
419                         for p in range(total_pages):
420
421                             if self.check_for_cancel():
422                                 fax_send_state = FAX_SEND_STATE_ABORT
423
424                             if fax_send_state == FAX_SEND_STATE_ABORT:
425                                 break
426
427                             try:
428                                 header = ff.read(PAGE_HEADER_SIZE)
429                             except IOError:
430                                 log.error("Unable to read fax file.")
431                                 fax_send_state = FAX_SEND_STATE_ERROR
432                                 continue
433
434                             page_num, ppr, rpp, bytes_to_read, thumbnail_bytes, reserved2 = \
435                                 self.decode_page_header(header)
436
437                             log.debug("Page=%d PPR=%d RPP=%d BPP=%d Thumb=%d" %
438                                       (page_num, ppr, rpp, bytes_to_read, thumbnail_bytes))
439
440                             if ppr != PIXELS_PER_LINE:
441                                 log.error("Pixels per line (width) must be %d!" % PIXELS_PER_LINE)
442
443                             page.write(ff.read(bytes_to_read))
444                             thumbnail = ff.read(thumbnail_bytes) # thrown away for now (should be 0 read)
445                             page.seek(0)
446
447                             try:
448                                 data = page.read(bytes_to_read)                                
449                             except IOError:
450                                 log.error("Unable to read fax file.")
451                                 fax_send_state = FAX_SEND_STATE_ERROR
452                                 break
453
454                             if data == '':
455                                 log.error("No data!")
456                                 fax_send_state = FAX_SEND_STATE_ERROR
457                                 break
458                             
459                             pageConfigURI = self.dev.readAttributeFromXml(jobListURI,"j:job-faxpcsendstatus-resourceuri")
460                             log.debug("pageConfigURI:[%s]" %pageConfigURI)  
461
462                             pageConfig = pageConfigXML %(page_num,hort_dpi,vert_dpi)
463                             xmldata = self.format_http_post(pageConfigURI,len(pageConfig),pageConfig)
464                             log.log_data(xmldata) 
465                            
466                             self.dev.openLEDM()
467                             try:
468                                 self.dev.writeLEDM(xmldata)
469                             except Error:
470                                 fax_send_state = FAX_SEND_STATE_ERROR
471                                 self.dev.closeLEDM() 
472                                 break
473
474                             response = cStringIO.StringIO()
475                             try:
476                                 while self.dev.readLEDM(512, response, timeout=5):
477                                     pass
478                             except Error:
479                                 fax_send_state = FAX_SEND_STATE_ERROR
480                                 self.dev.closeLEDM()
481                                 break
482
483                             self.dev.closeLEDM()
484                             response = (response.getvalue())
485                             log.log_data(response)
486                             if self.get_error_code(response) != HTTP_ACCEPTED:
487                                 fax_send_state = FAX_SEND_STATE_ERROR
488                                 log.error("Page config data is not accepted by the device")
489                                 break                                                    
490                                                    
491                             pageImageURI = self.dev.readAttributeFromXml(jobListURI,"j:job-faxpcsendstatus-resourceuri")                                
492                             while(True):
493                                 if self.check_for_cancel():
494                                     fax_send_state = FAX_SEND_STATE_ABORT
495                                     break
496  
497                                 Status, Fax_State = self.checkForError(jobListURI)
498                                 if Status == FAX_SEND_STATE_ERROR and (Fax_State == STATUS_ERROR_IN_TRANSMITTING or
499                                     Fax_State == STATUS_ERROR_IN_CONNECTING or Fax_State == STATUS_ERROR_PROBLEM_IN_FAXLINE or
500                                     Fax_State == STATUS_JOB_CANCEL):
501                                     log.debug("setting state to FAX_SEND_STATE_ERROR")
502                                     fax_send_state = FAX_SEND_STATE_ERROR
503                                     error_state = Fax_State
504                                     break
505                                 elif Status == FAX_SEND_STATE_SUCCESS:
506                                     break  
507                                                             
508                             if fax_send_state == FAX_SEND_STATE_ABORT or fax_send_state  == FAX_SEND_STATE_ERROR:
509                                 break
510                           
511                             
512                             xmldata = self.format_http_post(pageImageURI,len(data),"","application/octet-stream")
513                             log.debug("Sending Page Image XML Data [%s] to the device" %str(xmldata))                           
514                             self.dev.openLEDM()
515                             self.dev.writeLEDM(xmldata)
516                             log.debug("Sending Raw Data to printer............")
517                             try:
518                                 self.dev.writeLEDM(data)
519                             except Error:
520                                 fax_send_state = FAX_SEND_STATE_ERROR
521                                 self.dev.closeLEDM() 
522                                 break  
523                               
524                             response = cStringIO.StringIO()
525                             try:
526                                 while self.dev.readLEDM(512, response, timeout=10):
527                                     pass
528                             except Error:
529                                 fax_send_state = FAX_SEND_STATE_ERROR
530                                 self.dev.closeLEDM()
531                                 break
532                             
533                             self.dev.closeLEDM()
534                             response = response.getvalue()
535                             log.log_data(response)
536     
537                             if self.get_error_code(response) != HTTP_ACCEPTED:
538                                 log.error("Image Data is not accepted by the device")
539                                 fax_send_state = FAX_SEND_STATE_ERROR
540                                 break                   
541                                                
542                             page.truncate(0)
543                             page.seek(0)                           
544
545                         else:
546                             fax_send_state = FAX_SEND_STATE_ENDJOB
547
548
549                     elif fax_send_state == FAX_SEND_STATE_ENDJOB: # -------------- EndJob (110, 70, 0)
550                         fax_send_state = FAX_SEND_STATE_SUCCESS
551                         
552
553                     elif fax_send_state == FAX_SEND_STATE_CANCELJOB: # -------------- CancelJob (110, 80, 0)
554                         log.debug("%s State: CancelJob" % ("*"*20))                        
555                         
556                         xmldata = cancelJobXML %(jobListURI)                        
557                         data = self.format_http_put(jobListURI,len(xmldata),xmldata)
558                         log.log_data(data)
559                         
560                         self.dev.openLEDM()
561                         self.dev.writeLEDM(data)
562                         
563                         response = cStringIO.StringIO()
564                         try:
565                             while self.dev.readLEDM(512, response, timeout=10):
566                                 pass
567                         except Error:
568                             fax_send_state = FAX_SEND_STATE_ERROR
569                             self.dev.closeLEDM()
570                             break
571                         self.dev.closeLEDM()
572                         response = response.getvalue()
573                         log.log_data(response)                  
574
575                         if self.get_error_code(response) == HTTP_OK:
576                             fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
577                         else:
578                             fax_send_state = FAX_SEND_STATE_ERROR
579                             log.error("Job Cancel Request Failed")
580                           
581
582                     elif fax_send_state == FAX_SEND_STATE_CLOSE_SESSION: # -------------- Close session (110, 170, 0)
583                         log.debug("%s State: Close session" % ("*"*20))
584                         log.debug("Closing session...")                       
585
586                         try:
587                             ff.close()
588                         except NameError:
589                             pass
590
591                         #time.sleep(1)
592
593                         self.dev.closeLEDM()
594                         self.dev.close()
595
596                         fax_send_state = FAX_SEND_STATE_DONE # Exit inner state machine
597
598
599             elif state == STATE_CLEANUP: # --------------------------------- Cleanup (120, 0, 0)
600                 log.debug("%s State: Cleanup" % ("*"*20))
601
602                 if self.remove_temp_file:
603                     log.debug("Removing merged file: %s" % self.f)
604                     try:
605                         os.remove(self.f)
606                         log.debug("Removed")
607                     except OSError:
608                         log.debug("Not found")
609
610                 state = STATE_DONE # Exit outer state machine
611
612
613     def get_error_code(self, ret):
614         if not ret: return HTTP_ERROR
615         
616         match = http_result_pat.match(ret)
617         if match is None: return HTTP_OK
618         try:
619             code = int(match.group(1))
620         except (ValueError, TypeError):
621             code = HTTP_ERROR
622         return code        
623         
624     def checkForError(self,uri):
625         stream = cStringIO.StringIO()
626         data = self.dev.FetchLEDMUrl(uri)
627         if not data:
628             log.error("Unable To read the XML data from device")
629             return ""
630
631         xmlDict = utils.XMLToDictParser().parseXML(data)
632         log.debug("Read Attribute:%s and it is value:%s" %(uri,data))
633
634         FAX_SEND_STATE_ERROR = 20
635         FAX_SEND_STATE_SUCCESS = 30
636         state = FAX_SEND_STATE_ERROR
637         Fax_send_state = STATUS_ERROR   
638
639         if cmp(str(xmlDict['j:job-faxpcsendstatus-faxtxmachinestatus']),"Transmitting")==0 \
640             and cmp(str(xmlDict['j:job-faxpcsendstatus-faxtxerrorstatus']),"CommunicationError")== 0:
641             state = FAX_SEND_STATE_ERROR
642             Fax_send_state = STATUS_ERROR_IN_TRANSMITTING
643         elif(cmp(str(xmlDict['j:job-faxpcsendstatus-faxtxmachinestatus']),"Connecting")==0 \
644             and cmp(str(xmlDict['j:job-faxpcsendstatus-faxtxerrorstatus']),"NoAnswer")== 0):
645             state = FAX_SEND_STATE_ERROR
646             Fax_send_state = STATUS_ERROR_IN_CONNECTING
647         elif(cmp(str(xmlDict['j:job-faxpcsendstatus-faxtxerrorstatus']),"PcDisconnect")==0 \
648             and cmp(str(xmlDict['j:job-faxpcsendstatus-pagestatus-state']),"Error")== 0):
649             state = FAX_SEND_STATE_ERROR
650             Fax_send_state = STATUS_ERROR_PROBLEM_IN_FAXLINE
651         elif(cmp(str(xmlDict['j:job-faxpcsendstatus-faxtxerrorstatus']),"Stop")==0 \
652             and cmp(str(xmlDict['j:job-faxpcsendstatus-pagestatus-state']),"Error")== 0):
653             state = FAX_SEND_STATE_ERROR
654             Fax_send_state = STATUS_JOB_CANCEL 
655         elif(cmp(str(xmlDict['j:job-faxpcsendstatus-faxtxmachinestatus']),"Transmitting")== 0):
656             state = FAX_SEND_STATE_SUCCESS
657             Fax_send_state = FAX_SEND_STATE_SUCCESS
658         return state,Fax_send_state   
659
660     def format_http_post(self, requst, ledmlen, xmldata, content_type="text/xml; charset=utf-8"):
661         host = self.http_host      
662         
663         return utils.cat(
664 """POST $requst HTTP/1.1\r
665 Host: $host\r
666 User-Agent: hplip/2.0\r
667 Content-Type: $content_type\r
668 Content-Length: $ledmlen\r
669 Connection: Keep-alive\r
670 SOAPAction: ""\r
671 \r
672 $xmldata""")
673     
674     def format_http_put(self, requst, ledmlen, xmldata, content_type="text/xml; charset=utf-8"):
675         host = self.http_host
676         return  utils.cat(
677 """PUT $requst HTTP/1.1\r
678 Host: $host\r
679 User-Agent: hplip/2.0\r
680 Content-Type: $content_type\r
681 Content-Length: $ledmlen\r
682 \r
683 $xmldata""")
684
685         
686
687
688
689
690
691