Beispiel #1
0
def handle_hpdio_event(event, bytes_written):
    log.debug("Reading %d bytes from hpdio pipe..." % bytes_written)
    total_read, data = 0, to_bytes_utf8('')

    while True:
        r, w, e = select.select([r3], [], [r3], 0.0)
        if not r: break

        x = os.read(r3, PIPE_BUF)
        if not x: break

        data = to_bytes_utf8('').join([data, x])
        total_read += len(x)

        if total_read == bytes_written: break

    log.debug("Read %d bytes" % total_read)

    if total_read == bytes_written:
        dq = loads(data)

        if check_device(event.device_uri) == ERROR_SUCCESS:
            devices[event.device_uri].dq = dq.copy()

            handle_event(
                device.Event(event.device_uri, '',
                             dq.get('status-code', STATUS_PRINTER_IDLE),
                             prop.username, 0, ''))

            send_toolbox_event(event, EVENT_DEVICE_UPDATE_REPLY)
Beispiel #2
0
def handle_hpdio_event(event, bytes_written):
    log.debug("Reading %d bytes from hpdio pipe..." % bytes_written)
    total_read, data = 0, to_bytes_utf8('')

    while True:
        r, w, e = select.select([r3], [], [r3], 0.0)
        if not r: break

        x = os.read(r3, PIPE_BUF)
        if not x: break

        data = to_bytes_utf8('').join([data, x])
        total_read += len(x)

        if total_read == bytes_written: break

    log.debug("Read %d bytes" % total_read)

    if total_read == bytes_written:
        dq = loads(data)

        if check_device(event.device_uri) == ERROR_SUCCESS:
            devices[event.device_uri].dq = dq.copy()

            handle_event(device.Event(event.device_uri, '',
                dq.get('status-code', STATUS_PRINTER_IDLE), prop.username, 0, ''))

            send_toolbox_event(event, EVENT_DEVICE_UPDATE_REPLY)
Beispiel #3
0
def buildPCLCmd(punc, letter1, letter2, data=None, value=None):
    if data is None:
        return to_bytes_utf8('').join([
            ESC,
            to_bytes_utf8(punc),
            to_bytes_utf8(letter1),
            to_bytes_utf8(str(value)),
            to_bytes_utf8(letter2)
        ])
    return to_bytes_utf8('').join([
        ESC,
        to_bytes_utf8(punc),
        to_bytes_utf8(letter1),
        to_bytes_utf8(str(len(data))),
        to_bytes_utf8(letter2), data
    ])
Beispiel #4
0
def buildRP(a, f, c, d, e):
    return to_bytes_utf8('').join([
        b'\x00' * 600, RESET, UEL, PJL_ENTER_LANG,
        buildPCLCmd(
            '&', 'b', 'W',
            pml.buildEmbeddedPMLSetPacket('1.1.1.36', a + f + c + d + e,
                                          pml.TYPE_STRING)), RESET, UEL
    ])
Beispiel #5
0
def check_file_contains(f, s):
    log.debug("Checking file '%s' for contents '%s'..." % (f, s))
    try:
        if os.path.exists(f):
            s = to_bytes_utf8(s)
            for a in open(f, 'rb'):
                update_spinner()

                if s in a:
                    log.debug("'%s' found in file '%s'." % (s.replace(b'\n', b''), f))
                    return True

        log.debug("Contents not found.")
        return False

    finally:
        cleanup_spinner()
Beispiel #6
0
def check_file_contains(f, s):
    log.debug("Checking file '%s' for contents '%s'..." % (f, s))
    try:
        if os.path.exists(f):
            s = to_bytes_utf8(s)
            for a in open(f, 'rb'):
                update_spinner()

                if s in a:
                    log.debug("'%s' found in file '%s'." % (s.replace(b'\n', b''), f))
                    return True

        log.debug("Contents not found.")
        return False

    finally:
        cleanup_spinner()
Beispiel #7
0
def buildEmbeddedPML(pml):
    return to_bytes_utf8('').join(
        [UEL, PJL_ENTER_LANG, RESET, pml, RESET, UEL])
Beispiel #8
0
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
#
# Author: Don Welch
#

# Std Lib
import struct

# Local
from base import pml
from base.sixext import to_bytes_utf8

ESC = to_bytes_utf8('\x1b')
RESET = to_bytes_utf8('\x1bE')
UEL = to_bytes_utf8('\x1b%-12345X')
PJL_ENTER_LANG = to_bytes_utf8("@PJL ENTER LANGUAGE=PCL3GUI\n")
PJL_BEGIN_JOB = to_bytes_utf8('@PJL JOB NAME="unnamed"\n')
PJL_END_JOB = to_bytes_utf8('@PJL EOJ\n')


def buildPCLCmd(punc, letter1, letter2, data=None, value=None):
    if data is None:
        return to_bytes_utf8('').join([
            ESC,
            to_bytes_utf8(punc),
            to_bytes_utf8(letter1),
            to_bytes_utf8(str(value)),
            to_bytes_utf8(letter2)
Beispiel #9
0
def buildRP(a, f, c, d, e):
    return to_bytes_utf8('').join([b'\x00'*600, RESET, UEL, PJL_ENTER_LANG, buildPCLCmd('&', 'b', 'W', pml.buildEmbeddedPMLSetPacket('1.1.1.36', a + f + c + d + e, pml.TYPE_STRING)), RESET, UEL])
Beispiel #10
0
    def run(self):
        
        STATE_DONE = 0
        STATE_ABORTED = 10
        STATE_SUCCESS = 20
        STATE_BUSY = 25
        STATE_READ_SENDER_INFO = 30
        STATE_PRERENDER = 40
        STATE_COUNT_PAGES = 50
        STATE_NEXT_RECIPIENT = 60
        STATE_COVER_PAGE = 70
        STATE_SINGLE_FILE = 80
        STATE_MERGE_FILES = 90
        STATE_SINGLE_FILE = 100
        STATE_SEND_FAX = 110
        STATE_CLEANUP = 120
        STATE_ERROR = 130

        next_recipient = self.next_recipient_gen()

        state = STATE_READ_SENDER_INFO
        error_state = STATUS_ERROR
        self.rendered_file_list = []
        num_tries = 0

        while state != STATE_DONE: # --------------------------------- Fax state machine
            if self.check_for_cancel():
                state = STATE_ABORTED

            log.debug("STATE=(%d, 0, 0)" % state)

            if state == STATE_ABORTED: # ----------------------------- Aborted (10, 0, 0)
                log.error("Aborted by user.")
                self.write_queue((STATUS_IDLE, 0, ''))
                state = STATE_CLEANUP


            elif state == STATE_SUCCESS: # --------------------------- Success (20, 0, 0)
                log.debug("Success.")
                self.write_queue((STATUS_COMPLETED, 0, ''))
                state = STATE_CLEANUP


            elif state == STATE_ERROR: # ----------------------------- Error (130, 0, 0)
                log.error("Error, aborting.")
                self.write_queue((error_state, 0, ''))
                state = STATE_CLEANUP           


            elif state == STATE_BUSY: # ------------------------------ Busy (25, 0, 0)
                log.error("Device busy, aborting.")
                self.write_queue((STATUS_BUSY, 0, ''))
                state = STATE_CLEANUP


            elif state == STATE_READ_SENDER_INFO: # ------------------ Get sender info (30, 0, 0)
                log.debug("%s State: Get sender info" % ("*"*20))
                state = STATE_PRERENDER
                try:
                    try:
                        self.dev.open()
                    except Error as  e:
                        log.error("Unable to open device (%s)." % e.msg)
                        state = STATE_ERROR
                    else:
                        try:
                            self.sender_name = self.dev.station_name
                            log.debug("Sender name=%s" % self.sender_name)
                            self.sender_fax = self.dev.phone_num
                            log.debug("Sender fax=%s" % self.sender_fax)
                        except Error:
                            log.error("LEDM GET failed!")
                            state = STATE_ERROR

                finally:
                    self.dev.close()


            elif state == STATE_PRERENDER: # --------------------------------- Pre-render non-G4 files (40, 0, 0)
                log.debug("%s State: Pre-render non-G4 files" % ("*"*20))
                state = self.pre_render(STATE_COUNT_PAGES)

            elif state == STATE_COUNT_PAGES: # -------------------------------- Get total page count (50, 0, 0)
                log.debug("%s State: Get total page count" % ("*"*20))
                state = self.count_pages(STATE_NEXT_RECIPIENT)

            elif state == STATE_NEXT_RECIPIENT: # ----------------------------- Loop for multiple recipients (60, 0, 0)
                log.debug("%s State: Next recipient" % ("*"*20))
                state = STATE_COVER_PAGE

                try:
                    recipient = next(next_recipient)
                    log.debug("Processing for recipient %s" % recipient['name'])
                    self.write_queue((STATUS_SENDING_TO_RECIPIENT, 0, recipient['name']))
                except StopIteration:
                    state = STATE_SUCCESS
                    log.debug("Last recipient.")
                    continue

                recipient_file_list = self.rendered_file_list[:]


            elif state == STATE_COVER_PAGE: # ---------------------------------- Create cover page (70, 0, 0)
                log.debug("%s State: Render cover page" % ("*"*20))
                state = self.cover_page(recipient)


            elif state == STATE_SINGLE_FILE: # --------------------------------- Special case for single file (no merge) (80, 0, 0)
                log.debug("%s State: Handle single file" % ("*"*20))
                state = self.single_file(STATE_SEND_FAX)

            elif state == STATE_MERGE_FILES: # --------------------------------- Merge multiple G4 files (90, 0, 0)
                log.debug("%s State: Merge multiple files" % ("*"*20))
                state = self.merge_files(STATE_SEND_FAX)

            elif state == STATE_SEND_FAX: # ------------------------------------ Send fax state machine (110, 0, 0)
                log.debug("%s State: Send fax" % ("*"*20))
                state = STATE_NEXT_RECIPIENT

                FAX_SEND_STATE_DONE = 0
                FAX_SEND_STATE_ABORT = 10
                FAX_SEND_STATE_ERROR = 20
                FAX_SEND_STATE_BUSY = 25
                FAX_SEND_STATE_SUCCESS = 30
                FAX_SEND_STATE_DEVICE_OPEN = 40
                FAX_SEND_STATE_BEGINJOB = 50
                FAX_SEND_STATE_DOWNLOADPAGES = 60
                FAX_SEND_STATE_ENDJOB = 70
                FAX_SEND_STATE_CANCELJOB = 80
                FAX_SEND_STATE_CLOSE_SESSION = 170

                monitor_state = False
                fax_send_state = FAX_SEND_STATE_DEVICE_OPEN

                while fax_send_state != FAX_SEND_STATE_DONE:

                    if self.check_for_cancel():
                        log.error("Fax send aborted.")
                        fax_send_state = FAX_SEND_STATE_ABORT

                    if monitor_state:
                        fax_state = self.getFaxDownloadState()
                        if not fax_state in (pml.UPDN_STATE_XFERACTIVE, pml.UPDN_STATE_XFERDONE):
                            log.error("D/L error state=%d" % fax_state)
                            fax_send_state = FAX_SEND_STATE_ERROR
                            state = STATE_ERROR

                    log.debug("STATE=(%d, %d, 0)" % (STATE_SEND_FAX, fax_send_state))

                    if fax_send_state == FAX_SEND_STATE_ABORT: # ----------------- Abort (110, 10, 0)
                        monitor_state = False
                        fax_send_state = FAX_SEND_STATE_CANCELJOB
                        state = STATE_ABORTED

                    elif fax_send_state == FAX_SEND_STATE_ERROR: # --------------- Error (110, 20, 0)
                        log.error("Fax send error.")
                        monitor_state = False
                        fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
                        state = STATE_ERROR

                    elif fax_send_state == FAX_SEND_STATE_BUSY: # ---------------- Busy (110, 25, 0)
                        log.error("Fax device busy.")
                        monitor_state = False
                        fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
                        state = STATE_BUSY

                    elif fax_send_state == FAX_SEND_STATE_SUCCESS: # ------------- Success (110, 30, 0)
                        log.debug("Fax send success.")
                        monitor_state = False
                        fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
                        state = STATE_NEXT_RECIPIENT

                    elif fax_send_state == FAX_SEND_STATE_DEVICE_OPEN: # --------- Device open (110, 40, 0)
                        log.debug("%s State: Open device" % ("*"*20))
                        fax_send_state = FAX_SEND_STATE_BEGINJOB
                        try:
                            self.dev.open()
                        except Error as e:
                            log.error("Unable to open device (%s)." % e.msg)
                            fax_send_state = FAX_SEND_STATE_ERROR
                        else:
                            if self.dev.device_state == DEVICE_STATE_NOT_FOUND:
                                fax_send_state = FAX_SEND_STATE_ERROR

                    elif fax_send_state == FAX_SEND_STATE_BEGINJOB: # -------------- BeginJob (110, 50, 0)
                        log.debug("%s State: BeginJob" % ("*"*20))
                        try:
                            ff = open(self.f, 'rb')
                        except IOError:
                            log.error("Unable to read fax file.")
                            fax_send_state = FAX_SEND_STATE_ERROR
                            continue
                        
                        try:
                            header = ff.read(FILE_HEADER_SIZE)
                        except IOError:
                            log.error("Unable to read fax file.")
                            fax_send_state = FAX_SEND_STATE_ERROR
                            continue                        
                        
                        magic, version, total_pages, hort_dpi, vert_dpi, page_size, \
                            resolution, encoding, reserved1, reserved2 = self.decode_fax_header(header)

                        if magic != to_bytes_utf8('hplip_g3'):
                            log.error("Invalid file header. Bad magic.")
                            fax_send_state = FAX_SEND_STATE_ERROR
                        else:
                            log.debug("Magic=%s Ver=%d Pages=%d hDPI=%d vDPI=%d Size=%d Res=%d Enc=%d" %
                                      (magic, version, total_pages, hort_dpi, vert_dpi, page_size,
                                       resolution, encoding))
                        
                        faxnum = recipient['fax'] 

                        createJob = createJobXML  %(faxnum, total_pages)
                        data = self.format_http_post("/FaxPCSend/Job",len(createJob),createJob)
                        log.log_data(data)

                        self.dev.openLEDM()
                        self.dev.writeLEDM(to_bytes_utf8(data))
                        response = BytesIO()
                        try:
                            while self.dev.readLEDM(512, response, timeout=5):
                                pass
                        except Error:
                            fax_send_state = FAX_SEND_STATE_ERROR
                            self.dev.closeLEDM() 
                            break
                        self.dev.closeLEDM()

                        response = response.getvalue()
                        log.log_data(response)
                        if self.get_error_code(response) == HTTP_CREATED:
                            fax_send_state = FAX_SEND_STATE_DOWNLOADPAGES
                        elif self.get_error_code(response) == HTTP_SERVICE_UNAVALIABLE and num_tries <= MAX_TRIES:
                            fax_send_state = FAX_SEND_STATE_BEGINJOB
                            num_tries += 1
                        else:
                            if num_tries > MAX_TRIES:
                                log.error("HTTP ERROR CODE: 531, Server Temporary Unavailable")
                            fax_send_state = FAX_SEND_STATE_ERROR
                            log.error("Create Job request failed")
                            break
                        pos = response.find(b"/Jobs/JobList/",0,len(response))
                        pos1 = response.find(b"Content-Length",0,len(response))
                        jobListURI = response[pos:pos1].strip()
                        jobListURI = jobListURI.replace(b'\r',b'').replace(b'\n',b'')
                        log.debug("jobListURI = [%s] type=%s" %(jobListURI, type(jobListURI)))
                        if type(jobListURI) != str:
                             jobListURI = jobListURI.decode('utf-8')

                    elif fax_send_state == FAX_SEND_STATE_DOWNLOADPAGES: # -------------- DownloadPages (110, 60, 0)
                        log.debug("%s State: DownloadPages" % ("*"*20))
                        page = BytesIO()
                        log.debug("Total Number of pages are:%d" %total_pages)
                        for p in range(total_pages):

                            if self.check_for_cancel():
                                fax_send_state = FAX_SEND_STATE_ABORT

                            if fax_send_state == FAX_SEND_STATE_ABORT:
                                break

                            try:
                                header = ff.read(PAGE_HEADER_SIZE)
                            except IOError:
                                log.error("Unable to read fax file.")
                                fax_send_state = FAX_SEND_STATE_ERROR
                                continue

                            page_num, ppr, rpp, bytes_to_read, thumbnail_bytes, reserved2 = \
                                self.decode_page_header(header)

                            log.debug("Page=%d PPR=%d RPP=%d BPP=%d Thumb=%d" %
                                      (page_num, ppr, rpp, bytes_to_read, thumbnail_bytes))

                            if ppr != PIXELS_PER_LINE:
                                log.error("Pixels per line (width) must be %d!" % PIXELS_PER_LINE)

                            page.write(ff.read(bytes_to_read))
                            thumbnail = ff.read(thumbnail_bytes) # thrown away for now (should be 0 read)
                            page.seek(0)

                            try:
                                data = page.read(bytes_to_read)                                
                            except IOError:
                                log.error("Unable to read fax file.")
                                fax_send_state = FAX_SEND_STATE_ERROR
                                break

                            if data == b'':
                                log.error("No data!")
                                fax_send_state = FAX_SEND_STATE_ERROR
                                break
                            
                            pageConfigURI = self.dev.readAttributeFromXml(jobListURI,"j:job-faxpcsendstatus-resourceuri")
                            log.debug("pageConfigURI:[%s]" %pageConfigURI)  

                            pageConfig = pageConfigXML %(page_num,hort_dpi,vert_dpi)
                            xmldata = self.format_http_post(pageConfigURI,len(pageConfig),pageConfig)
                            log.log_data(xmldata) 
                           
                            self.dev.openLEDM()
                            try:
                                self.dev.writeLEDM(xmldata)
                            except Error:
                                fax_send_state = FAX_SEND_STATE_ERROR
                                self.dev.closeLEDM() 
                                break

                            response = BytesIO()
                            try:
                                while self.dev.readLEDM(512, response, timeout=5):
                                    pass
                            except Error:
                                fax_send_state = FAX_SEND_STATE_ERROR
                                self.dev.closeLEDM()
                                break

                            self.dev.closeLEDM()
                            response = (response.getvalue())
                            log.log_data(response)
                            if self.get_error_code(response) != HTTP_ACCEPTED:
                                fax_send_state = FAX_SEND_STATE_ERROR
                                log.error("Page config data is not accepted by the device")
                                break                                                    
                                                   
                            pageImageURI = self.dev.readAttributeFromXml(jobListURI,"j:job-faxpcsendstatus-resourceuri")                                
                            while(True):
                                if self.check_for_cancel():
                                    fax_send_state = FAX_SEND_STATE_ABORT
                                    break
 
                                Status, Fax_State = self.checkForError(jobListURI)
                                if Status == FAX_SEND_STATE_ERROR and (Fax_State == STATUS_ERROR_IN_TRANSMITTING or
                                    Fax_State == STATUS_ERROR_IN_CONNECTING or Fax_State == STATUS_ERROR_PROBLEM_IN_FAXLINE or
                                    Fax_State == STATUS_JOB_CANCEL):
                                    log.debug("setting state to FAX_SEND_STATE_ERROR")
                                    fax_send_state = FAX_SEND_STATE_ERROR
                                    error_state = Fax_State
                                    break
                                elif Status == FAX_SEND_STATE_SUCCESS:
                                    break  
                         
                            if fax_send_state == FAX_SEND_STATE_ABORT or fax_send_state  == FAX_SEND_STATE_ERROR:
                                break
                          
                            
                            xmldata = self.format_http_post(pageImageURI,len(data),"","application/octet-stream")
                            log.debug("Sending Page Image XML Data [%s] to the device" %xmldata)                           
                            self.dev.openLEDM()
                            self.dev.writeLEDM(xmldata)
                            log.debug("Sending Raw Data to printer............")
                            try:
                                self.dev.writeLEDM(data)
                            except Error:
                                fax_send_state = FAX_SEND_STATE_ERROR
                                self.dev.closeLEDM() 
                                break  
                              
                            response = BytesIO()
                            try:
                                while self.dev.readLEDM(512, response, timeout=10):
                                    pass
                            except Error:
                                fax_send_state = FAX_SEND_STATE_ERROR
                                self.dev.closeLEDM()
                                break
                            
                            self.dev.closeLEDM()
                            response = response.getvalue()
                            log.log_data(response)
    
                            if self.get_error_code(response) != HTTP_ACCEPTED:
                                log.error("Image Data is not accepted by the device")
                                fax_send_state = FAX_SEND_STATE_ERROR
                                break                   
                                               
                            page.truncate(0)
                            page.seek(0)                           

                        else:
                            fax_send_state = FAX_SEND_STATE_ENDJOB


                    elif fax_send_state == FAX_SEND_STATE_ENDJOB: # -------------- EndJob (110, 70, 0)
                        fax_send_state = FAX_SEND_STATE_SUCCESS
                        

                    elif fax_send_state == FAX_SEND_STATE_CANCELJOB: # -------------- CancelJob (110, 80, 0)
                        log.debug("%s State: CancelJob" % ("*"*20))                        
                        
                        xmldata = cancelJobXML %(jobListURI)                        
                        data = self.format_http_put(jobListURI,len(xmldata),xmldata)
                        log.log_data(data)
                        
                        self.dev.openLEDM()
                        self.dev.writeLEDM(to_bytes_utf8(data))
                        
                        response = BytesIO()
                        try:
                            while self.dev.readLEDM(512, response, timeout=10):
                                pass
                        except Error:
                            fax_send_state = FAX_SEND_STATE_ERROR
                            self.dev.closeLEDM()
                            break
                        self.dev.closeLEDM()
                        response = response.getvalue()
                        log.log_data(response)

                        if self.get_error_code(response) == HTTP_OK:
                            fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
                        else:
                            fax_send_state = FAX_SEND_STATE_ERROR
                            log.error("Job Cancel Request Failed")
                          

                    elif fax_send_state == FAX_SEND_STATE_CLOSE_SESSION: # -------------- Close session (110, 170, 0)
                        log.debug("%s State: Close session" % ("*"*20))
                        log.debug("Closing session...")                       

                        try:
                            ff.close()
                        except NameError:
                            pass

                        #time.sleep(1)

                        self.dev.closeLEDM()
                        self.dev.close()

                        fax_send_state = FAX_SEND_STATE_DONE # Exit inner state machine


            elif state == STATE_CLEANUP: # --------------------------------- Cleanup (120, 0, 0)
                log.debug("%s State: Cleanup" % ("*"*20))

                if self.remove_temp_file:
                    log.debug("Removing merged file: %s" % self.f)
                    try:
                        os.remove(self.f)
                        log.debug("Removed")
                    except OSError:
                        log.debug("Not found")

                state = STATE_DONE # Exit outer state machine
Beispiel #11
0
def buildEmbeddedPML(pml):
    return to_bytes_utf8('').join([UEL, PJL_ENTER_LANG, RESET, pml, RESET, UEL])
Beispiel #12
0
def buildPCLCmd(punc, letter1, letter2, data=None, value=None):
    if data is None:
        return to_bytes_utf8('').join([ESC, to_bytes_utf8(punc), to_bytes_utf8(letter1), to_bytes_utf8(str(value)), to_bytes_utf8(letter2)])
    return to_bytes_utf8('').join([ESC, to_bytes_utf8(punc), to_bytes_utf8(letter1), to_bytes_utf8(str(len(data))), to_bytes_utf8(letter2), data])
Beispiel #13
0
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
#
# Author: Don Welch
#

# Std Lib
import struct

# Local
from base import pml
from base.sixext import to_bytes_utf8

ESC = to_bytes_utf8('\x1b')
RESET = to_bytes_utf8('\x1bE')
UEL = to_bytes_utf8('\x1b%-12345X')
PJL_ENTER_LANG = to_bytes_utf8("@PJL ENTER LANGUAGE=PCL3GUI\n")
PJL_BEGIN_JOB = to_bytes_utf8('@PJL JOB NAME="unnamed"\n')
PJL_END_JOB = to_bytes_utf8('@PJL EOJ\n')

def buildPCLCmd(punc, letter1, letter2, data=None, value=None):
    if data is None:
        return to_bytes_utf8('').join([ESC, to_bytes_utf8(punc), to_bytes_utf8(letter1), to_bytes_utf8(str(value)), to_bytes_utf8(letter2)])
    return to_bytes_utf8('').join([ESC, to_bytes_utf8(punc), to_bytes_utf8(letter1), to_bytes_utf8(str(len(data))), to_bytes_utf8(letter2), data])


def buildEmbeddedPML(pml):
    return to_bytes_utf8('').join([UEL, PJL_ENTER_LANG, RESET, pml, RESET, UEL])
Beispiel #14
0
    def run(self):
        #results = {} # {'file' : error_code,...}

        STATE_DONE = 0
        STATE_ABORTED = 10
        STATE_SUCCESS = 20
        STATE_BUSY = 25
        STATE_READ_SENDER_INFO = 30
        STATE_PRERENDER = 40
        STATE_COUNT_PAGES = 50
        STATE_NEXT_RECIPIENT = 60
        STATE_COVER_PAGE = 70
        STATE_SINGLE_FILE = 80
        STATE_MERGE_FILES = 90
        STATE_SINGLE_FILE = 100
        STATE_SEND_FAX = 110
        STATE_CLEANUP = 120
        STATE_ERROR = 130

        next_recipient = self.next_recipient_gen()

        state = STATE_READ_SENDER_INFO
        self.rendered_file_list = []

        while state != STATE_DONE: # --------------------------------- Fax state machine
            if self.check_for_cancel():
                state = STATE_ABORTED

            log.debug("STATE=(%d, 0, 0)" % state)

            if state == STATE_ABORTED: # --------------------------------- Aborted (10, 0, 0)
                log.error("Aborted by user.")
                self.write_queue((STATUS_IDLE, 0, ''))
                state = STATE_CLEANUP


            elif state == STATE_SUCCESS: # --------------------------------- Success (20, 0, 0)
                log.debug("Success.")
                self.write_queue((STATUS_COMPLETED, 0, ''))
                state = STATE_CLEANUP


            elif state == STATE_ERROR: # --------------------------------- Error (130, 0, 0)
                log.error("Error, aborting.")
                self.write_queue((STATUS_ERROR, 0, ''))
                state = STATE_CLEANUP


            elif state == STATE_BUSY: # --------------------------------- Busy (25, 0, 0)
                log.error("Device busy, aborting.")
                self.write_queue((STATUS_BUSY, 0, ''))
                state = STATE_CLEANUP


            elif state == STATE_READ_SENDER_INFO: # --------------------------------- Get sender info (30, 0, 0)
                log.debug("%s State: Get sender info" % ("*"*20))
                state = STATE_PRERENDER
                try:
                    try:
                        self.dev.open()
                    except Error as e:
                        log.error("Unable to open device (%s)." % e.msg)
                        state = STATE_ERROR
                    else:
                        try:
                            self.sender_name = self.dev.station_name
                            log.debug("Sender name=%s" % self.sender_name)
                            self.sender_fax = self.dev.phone_num
                            log.debug("Sender fax=%s" % self.sender_fax)
                        except Error:
                            log.error("HTTP GET failed!")
                            state = STATE_ERROR

                finally:
                    self.dev.close()


            elif state == STATE_PRERENDER: # --------------------------------- Pre-render non-G4 files (40, 0, 0)
                log.debug("%s State: Pre-render non-G4 files" % ("*"*20))
                state = self.pre_render(STATE_COUNT_PAGES)

            elif state == STATE_COUNT_PAGES: # --------------------------------- Get total page count (50, 0, 0)
                log.debug("%s State: Get total page count" % ("*"*20))
                state = self.count_pages(STATE_NEXT_RECIPIENT)

            elif state == STATE_NEXT_RECIPIENT: # --------------------------------- Loop for multiple recipients (60, 0, 0)
                log.debug("%s State: Next recipient" % ("*"*20))
                state = STATE_COVER_PAGE

                try:
                    recipient = next(next_recipient)
                    log.debug("Processing for recipient %s" % recipient['name'])
                    self.write_queue((STATUS_SENDING_TO_RECIPIENT, 0, recipient['name']))
                except StopIteration:
                    state = STATE_SUCCESS
                    log.debug("Last recipient.")
                    continue

                recipient_file_list = self.rendered_file_list[:]


            elif state == STATE_COVER_PAGE: # --------------------------------- Create cover page (70, 0, 0)
                log.debug("%s State: Render cover page" % ("*"*20))
                state = self.cover_page(recipient)


            elif state == STATE_SINGLE_FILE: # --------------------------------- Special case for single file (no merge) (80, 0, 0)
                log.debug("%s State: Handle single file" % ("*"*20))
                state = self.single_file(STATE_SEND_FAX)

            elif state == STATE_MERGE_FILES: # --------------------------------- Merge multiple G4 files (90, 0, 0)
                log.debug("%s State: Merge multiple files" % ("*"*20))
                state = self.merge_files(STATE_SEND_FAX)

            elif state == STATE_SEND_FAX: # --------------------------------- Send fax state machine (110, 0, 0)
                log.debug("%s State: Send fax" % ("*"*20))
                state = STATE_NEXT_RECIPIENT

                FAX_SEND_STATE_DONE = 0
                FAX_SEND_STATE_ABORT = 10
                FAX_SEND_STATE_ERROR = 20
                FAX_SEND_STATE_BUSY = 25
                FAX_SEND_STATE_SUCCESS = 30
                FAX_SEND_STATE_DEVICE_OPEN = 40
                FAX_SEND_STATE_BEGINJOB = 50
                FAX_SEND_STATE_DOWNLOADPAGES = 60
                FAX_SEND_STATE_ENDJOB = 70
                FAX_SEND_STATE_CANCELJOB = 80
                FAX_SEND_STATE_CLOSE_SESSION = 170

                monitor_state = False
                fax_send_state = FAX_SEND_STATE_DEVICE_OPEN

                while fax_send_state != FAX_SEND_STATE_DONE:

                    if self.check_for_cancel():
                        log.error("Fax send aborted.")
                        fax_send_state = FAX_SEND_STATE_ABORT

                    if monitor_state:
                        fax_state = self.getFaxDownloadState()
                        if not fax_state in (pml.UPDN_STATE_XFERACTIVE, pml.UPDN_STATE_XFERDONE):
                            log.error("D/L error state=%d" % fax_state)
                            fax_send_state = FAX_SEND_STATE_ERROR
                            state = STATE_ERROR

                    log.debug("STATE=(%d, %d, 0)" % (STATE_SEND_FAX, fax_send_state))

                    if fax_send_state == FAX_SEND_STATE_ABORT: # -------------- Abort (110, 10, 0)
                        monitor_state = False
                        fax_send_state = FAX_SEND_STATE_CANCELJOB
                        state = STATE_ABORTED

                    elif fax_send_state == FAX_SEND_STATE_ERROR: # -------------- Error (110, 20, 0)
                        log.error("Fax send error.")
                        monitor_state = False
                        fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
                        state = STATE_ERROR

                    elif fax_send_state == FAX_SEND_STATE_BUSY: # -------------- Busy (110, 25, 0)
                        log.error("Fax device busy.")
                        monitor_state = False
                        fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
                        state = STATE_BUSY

                    elif fax_send_state == FAX_SEND_STATE_SUCCESS: # -------------- Success (110, 30, 0)
                        log.debug("Fax send success.")
                        monitor_state = False
                        fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
                        state = STATE_NEXT_RECIPIENT

                    elif fax_send_state == FAX_SEND_STATE_DEVICE_OPEN: # -------------- Device open (110, 40, 0)
                        log.debug("%s State: Open device" % ("*"*20))
                        fax_send_state = FAX_SEND_STATE_BEGINJOB
                        try:
                            self.dev.open()
                        except Error as e:
                            log.error("Unable to open device (%s)." % e.msg)
                            fax_send_state = FAX_SEND_STATE_ERROR
                        else:
                            if self.dev.device_state == DEVICE_STATE_NOT_FOUND:
                                fax_send_state = FAX_SEND_STATE_ERROR

                    elif fax_send_state == FAX_SEND_STATE_BEGINJOB: # -------------- BeginJob (110, 50, 0)
                        log.debug("%s State: BeginJob" % ("*"*20))

                        try:
                            ff = open(self.f, 'rb')
                        except IOError:
                            log.error("Unable to read fax file.")
                            fax_send_state = FAX_SEND_STATE_ERROR
                            continue

                        try:
                            header = ff.read(FILE_HEADER_SIZE)
                        except IOError:
                            log.error("Unable to read fax file.")
                            fax_send_state = FAX_SEND_STATE_ERROR
                            continue

                        magic, version, total_pages, hort_dpi, vert_dpi, page_size, \
                            resolution, encoding, reserved1, reserved2 = self.decode_fax_header(header)

                        if magic != b'hplip_g3':
                            log.error("Invalid file header. Bad magic.")
                            fax_send_state = FAX_SEND_STATE_ERROR
                        else:
                            log.debug("Magic=%s Ver=%d Pages=%d hDPI=%d vDPI=%d Size=%d Res=%d Enc=%d" %
                                      (magic, version, total_pages, hort_dpi, vert_dpi, page_size,
                                       resolution, encoding))

                        job_id = self.job_id
                        delay = 0
                        faxnum = recipient['fax']
                        speeddial = 0

                        if resolution == RESOLUTION_STD:
                            res = "STANDARD"
                        elif resolution == RESOLUTION_FINE:
                            res = "FINE"
                        elif resolution == RESOLUTION_300DPI:
                            res = "SUPERFINE"

                        soap = utils.cat(
"""<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><Fax:BeginJob xmlns:Fax="urn:Fax"><ticket xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Fax:Ticket"><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:string">$job_id</jobId><resolution xsi:type="Fax:Resolution">$res</resolution><delay xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:positiveInteger">$delay</delay><phoneNumber xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:string">$faxnum</phoneNumber><speedDial xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:positiveInteger">$speeddial</speedDial></ticket></Fax:BeginJob></SOAP-ENV:Body></SOAP-ENV:Envelope>""")

                        data = self.format_http(soap.encode('utf-8'))

                        log.log_data(data)

                        if log.is_debug():
                            open('beginjob.log', 'wb').write(data)
                        self.dev.openSoapFax()
                        self.dev.writeSoapFax(data)
                        ret = BytesIO()

                        while self.dev.readSoapFax(8192, ret, timeout=5):
                            pass

                        ret = ret.getvalue()

                        if log.is_debug():
                            open('beginjob_ret.log', 'wb').write(ret)
                        log.log_data(ret)
                        self.dev.closeSoapFax()

                        if self.get_error_code(ret.decode('utf-8')) == HTTP_OK:
                            fax_send_state = FAX_SEND_STATE_DOWNLOADPAGES
                        else:
                            fax_send_state = FAX_SEND_STATE_ERROR


                    elif fax_send_state == FAX_SEND_STATE_DOWNLOADPAGES: # -------------- DownloadPages (110, 60, 0)
                        log.debug("%s State: DownloadPages" % ("*"*20))
                        page = BytesIO()
                        for p in range(total_pages):

                            if self.check_for_cancel():
                                fax_send_state = FAX_SEND_STATE_ABORT

                            if fax_send_state == FAX_SEND_STATE_ABORT:
                                break

                            try:
                                header = ff.read(PAGE_HEADER_SIZE)
                            except IOError:
                                log.error("Unable to read fax file.")
                                fax_send_state = FAX_SEND_STATE_ERROR
                                continue

                            page_num, ppr, rpp, bytes_to_read, thumbnail_bytes, reserved2 = \
                                self.decode_page_header(header)

                            log.debug("Page=%d PPR=%d RPP=%d BPP=%d Thumb=%d" %
                                      (page_num, ppr, rpp, bytes_to_read, thumbnail_bytes))

                            if ppr != PIXELS_PER_LINE:
                                log.error("Pixels per line (width) must be %d!" % PIXELS_PER_LINE)

                            page.write(ff.read(bytes_to_read))
                            thumbnail = ff.read(thumbnail_bytes) # thrown away for now (should be 0 read)
                            page.seek(0)

                            try:
                                data = page.read(bytes_to_read)
                            except IOError:
                                log.error("Unable to read fax file.")
                                fax_send_state = FAX_SEND_STATE_ERROR
                                break

                            if data == b'':
                                log.error("No data!")
                                fax_send_state = FAX_SEND_STATE_ERROR
                                break

                            height = rpp
                            job_id = self.job_id

                            soap = utils.cat(
"""<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string" SOAP-ENV:mustUnderstand="1">$job_id</jobId></SOAP-ENV:Header><SOAP-ENV:Body><Fax:DownloadPage xmlns:Fax="urn:Fax"><height xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:positiveInteger">$height</height></Fax:DownloadPage></SOAP-ENV:Body></SOAP-ENV:Envelope>""")

                            m = dime.Message()
                            m.add_record(dime.Record(b"cid:id0", b"http://schemas.xmlsoap.org/soap/envelope/",
                                dime.TYPE_T_URI, to_bytes_utf8(soap)))

                            m.add_record(dime.Record(b"", b"image/g4fax", dime.TYPE_T_MIME, data))

                            output = BytesIO()
                            m.generate(output)
                            data = self.format_http(output.getvalue(), content_type="application/dime")
                            log.log_data(data)
                            if log.is_debug():
                                           open('downloadpages%d.log' % p, 'wb').write(data)
                            try:
                                self.dev.writeSoapFax(data)
                            except Error:
                                fax_send_state = FAX_SEND_STATE_ERROR

                            ret = BytesIO()

                            try:
                                while self.dev.readSoapFax(8192, ret, timeout=5):
                                    pass
                            except Error:
                                fax_send_state = FAX_SEND_STATE_ERROR

                            ret = ret.getvalue()

                            if log.is_debug():
                                open('downloadpages%d_ret.log' % p, 'wb').write(ret)

                            log.log_data(ret)
                            self.dev.closeSoapFax()

                            if self.get_error_code(ret.decode('utf-8')) != HTTP_OK:
                                fax_send_state = FAX_SEND_STATE_ERROR
                                break

                            page.truncate(0)
                            page.seek(0)

                        else:
                            fax_send_state = FAX_SEND_STATE_ENDJOB


                    elif fax_send_state == FAX_SEND_STATE_ENDJOB: # -------------- EndJob (110, 70, 0)
                        log.debug("%s State: EndJob" % ("*"*20))

                        job_id = self.job_id

                        soap = utils.cat(
"""<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string" SOAP-ENV:mustUnderstand="1">$job_id</jobId></SOAP-ENV:Header><SOAP-ENV:Body><Fax:EndJob xmlns:Fax="urn:Fax"><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">$job_id</jobId></Fax:EndJob></SOAP-ENV:Body></SOAP-ENV:Envelope>""")

                        data = self.format_http(soap.encode('utf-8'))

                        log.log_data(data)

                        if log.is_debug():
                            open('endjob.log', 'wb').write(data)

                        self.dev.writeSoapFax(data)
                        ret = BytesIO()

                        while self.dev.readSoapFax(8192, ret, timeout=5):
                            pass

                        ret = ret.getvalue()

                        if log.is_debug():
                            open('endjob_ret.log', 'wb').write(ret)

                        log.log_data(ret)
                        self.dev.closeSoapFax()

                        if self.get_error_code(ret.decode('utf-8')) == HTTP_OK:
                            fax_send_state = FAX_SEND_STATE_SUCCESS
                        else:
                            fax_send_state = FAX_SEND_STATE_ERROR

                    elif fax_send_state == FAX_SEND_STATE_CANCELJOB: # -------------- CancelJob (110, 80, 0)
                        log.debug("%s State: CancelJob" % ("*"*20))

                        job_id = self.job_id

                        soap = utils.cat(
"""<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string" SOAP-ENV:mustUnderstand="1">$job_id</jobId></SOAP-ENV:Header><SOAP-ENV:Body><Fax:CancelJob xmlns:Fax="urn:Fax"><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">$job_id</jobId></Fax:CancelJob></SOAP-ENV:Body></SOAP-ENV:Envelope>""")

                        data = self.format_http(soap.encode('utf-8'))

                        log.log_data(data)

                        if log.is_debug():
                            open('canceljob.log', 'wb').write(data)

                        self.dev.writeSoapFax(data)
                        ret = BytesIO()

                        while self.dev.readSoapFax(8192, ret, timeout=5):
                            pass

                        ret = ret.getvalue()

                        if log.is_debug():
                            open('canceljob_ret.log', 'wb').write(ret)

                        log.log_data(ret)
                        self.dev.closeSoapFax()

                        if self.get_error_code(ret.decode('utf-8')) == HTTP_OK:
                            fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
                        else:
                            fax_send_state = FAX_SEND_STATE_ERROR


                    elif fax_send_state == FAX_SEND_STATE_CLOSE_SESSION: # -------------- Close session (110, 170, 0)
                        log.debug("%s State: Close session" % ("*"*20))
                        log.debug("Closing session...")

                        try:
                            mm.close()
                        except NameError:
                            pass

                        try:
                            ff.close()
                        except NameError:
                            pass

                        time.sleep(1)

                        self.dev.closeSoapFax()
                        self.dev.close()

                        fax_send_state = FAX_SEND_STATE_DONE # Exit inner state machine


            elif state == STATE_CLEANUP: # --------------------------------- Cleanup (120, 0, 0)
                log.debug("%s State: Cleanup" % ("*"*20))

                if self.remove_temp_file:
                    log.debug("Removing merged file: %s" % self.f)
                    try:
                        os.remove(self.f)
                        log.debug("Removed")
                    except OSError:
                        log.debug("Not found")

                state = STATE_DONE # Exit outer state machine
Beispiel #15
0
def buildEmbeddedPML2(pml):
    return to_bytes_utf8('').join([
        RESET, UEL, PJL_BEGIN_JOB, PJL_ENTER_LANG, RESET, pml, RESET,
        PJL_END_JOB, RESET, UEL
    ])
Beispiel #16
0
def buildEmbeddedPML2(pml):
    return to_bytes_utf8('').join([RESET, UEL, PJL_BEGIN_JOB, PJL_ENTER_LANG, RESET, pml, RESET, PJL_END_JOB, RESET, UEL])
Beispiel #17
0
def buildDynamicCounter(counter):
    #return ''.join([UEL, PJL_ENTER_LANG, ESC, '*o5W\xc0\x01', struct.pack(">I", counter)[1:], UEL])
    return to_bytes_utf8('').join([
        UEL, PJL_ENTER_LANG, ESC, b'*o5W\xc0\x01',
        struct.pack(">I", counter)[1:], PJL_END_JOB, UEL
    ])
Beispiel #18
0
def buildDynamicCounter(counter):
    #return ''.join([UEL, PJL_ENTER_LANG, ESC, '*o5W\xc0\x01', struct.pack(">I", counter)[1:], UEL])
    return to_bytes_utf8('').join([UEL, PJL_ENTER_LANG, ESC, b'*o5W\xc0\x01', struct.pack(">I", counter)[1:], PJL_END_JOB, UEL])
Beispiel #19
0
    def run(self):

        STATE_DONE = 0
        STATE_ABORTED = 10
        STATE_SUCCESS = 20
        STATE_BUSY = 25
        STATE_READ_SENDER_INFO = 30
        STATE_PRERENDER = 40
        STATE_COUNT_PAGES = 50
        STATE_NEXT_RECIPIENT = 60
        STATE_COVER_PAGE = 70
        STATE_SINGLE_FILE = 80
        STATE_MERGE_FILES = 90
        STATE_SINGLE_FILE = 100
        STATE_SEND_FAX = 110
        STATE_CLEANUP = 120
        STATE_ERROR = 130

        next_recipient = self.next_recipient_gen()

        state = STATE_READ_SENDER_INFO
        error_state = STATUS_ERROR
        self.rendered_file_list = []
        num_tries = 0

        while state != STATE_DONE:  # --------------------------------- Fax state machine
            if self.check_for_cancel():
                state = STATE_ABORTED

            log.debug("STATE=(%d, 0, 0)" % state)

            if state == STATE_ABORTED:  # ----------------------------- Aborted (10, 0, 0)
                log.error("Aborted by user.")
                self.write_queue((STATUS_IDLE, 0, ''))
                state = STATE_CLEANUP

            elif state == STATE_SUCCESS:  # --------------------------- Success (20, 0, 0)
                log.debug("Success.")
                self.write_queue((STATUS_COMPLETED, 0, ''))
                state = STATE_CLEANUP

            elif state == STATE_ERROR:  # ----------------------------- Error (130, 0, 0)
                log.error("Error, aborting.")
                self.write_queue((error_state, 0, ''))
                state = STATE_CLEANUP

            elif state == STATE_BUSY:  # ------------------------------ Busy (25, 0, 0)
                log.error("Device busy, aborting.")
                self.write_queue((STATUS_BUSY, 0, ''))
                state = STATE_CLEANUP

            elif state == STATE_READ_SENDER_INFO:  # ------------------ Get sender info (30, 0, 0)
                log.debug("%s State: Get sender info" % ("*" * 20))
                state = STATE_PRERENDER
                try:
                    try:
                        self.dev.open()
                    except Error as e:
                        log.error("Unable to open device (%s)." % e.msg)
                        state = STATE_ERROR
                    else:
                        try:
                            self.sender_name = self.dev.station_name
                            log.debug("Sender name=%s" % self.sender_name)
                            self.sender_fax = self.dev.phone_num
                            log.debug("Sender fax=%s" % self.sender_fax)
                        except Error:
                            log.error("LEDM GET failed!")
                            state = STATE_ERROR

                finally:
                    self.dev.close()

            elif state == STATE_PRERENDER:  # --------------------------------- Pre-render non-G4 files (40, 0, 0)
                log.debug("%s State: Pre-render non-G4 files" % ("*" * 20))
                state = self.pre_render(STATE_COUNT_PAGES)

            elif state == STATE_COUNT_PAGES:  # -------------------------------- Get total page count (50, 0, 0)
                log.debug("%s State: Get total page count" % ("*" * 20))
                state = self.count_pages(STATE_NEXT_RECIPIENT)

            elif state == STATE_NEXT_RECIPIENT:  # ----------------------------- Loop for multiple recipients (60, 0, 0)
                log.debug("%s State: Next recipient" % ("*" * 20))
                state = STATE_COVER_PAGE

                try:
                    recipient = next(next_recipient)
                    log.debug("Processing for recipient %s" %
                              recipient['name'])
                    self.write_queue(
                        (STATUS_SENDING_TO_RECIPIENT, 0, recipient['name']))
                except StopIteration:
                    state = STATE_SUCCESS
                    log.debug("Last recipient.")
                    continue

                recipient_file_list = self.rendered_file_list[:]

            elif state == STATE_COVER_PAGE:  # ---------------------------------- Create cover page (70, 0, 0)
                log.debug("%s State: Render cover page" % ("*" * 20))
                state = self.cover_page(recipient)

            elif state == STATE_SINGLE_FILE:  # --------------------------------- Special case for single file (no merge) (80, 0, 0)
                log.debug("%s State: Handle single file" % ("*" * 20))
                state = self.single_file(STATE_SEND_FAX)

            elif state == STATE_MERGE_FILES:  # --------------------------------- Merge multiple G4 files (90, 0, 0)
                log.debug("%s State: Merge multiple files" % ("*" * 20))
                state = self.merge_files(STATE_SEND_FAX)

            elif state == STATE_SEND_FAX:  # ------------------------------------ Send fax state machine (110, 0, 0)
                log.debug("%s State: Send fax" % ("*" * 20))
                state = STATE_NEXT_RECIPIENT

                FAX_SEND_STATE_DONE = 0
                FAX_SEND_STATE_ABORT = 10
                FAX_SEND_STATE_ERROR = 20
                FAX_SEND_STATE_BUSY = 25
                FAX_SEND_STATE_SUCCESS = 30
                FAX_SEND_STATE_DEVICE_OPEN = 40
                FAX_SEND_STATE_BEGINJOB = 50
                FAX_SEND_STATE_DOWNLOADPAGES = 60
                FAX_SEND_STATE_ENDJOB = 70
                FAX_SEND_STATE_CANCELJOB = 80
                FAX_SEND_STATE_CLOSE_SESSION = 170

                monitor_state = False
                fax_send_state = FAX_SEND_STATE_DEVICE_OPEN

                while fax_send_state != FAX_SEND_STATE_DONE:

                    if self.check_for_cancel():
                        log.error("Fax send aborted.")
                        fax_send_state = FAX_SEND_STATE_ABORT

                    if monitor_state:
                        fax_state = self.getFaxDownloadState()
                        if not fax_state in (pml.UPDN_STATE_XFERACTIVE,
                                             pml.UPDN_STATE_XFERDONE):
                            log.error("D/L error state=%d" % fax_state)
                            fax_send_state = FAX_SEND_STATE_ERROR
                            state = STATE_ERROR

                    log.debug("STATE=(%d, %d, 0)" %
                              (STATE_SEND_FAX, fax_send_state))

                    if fax_send_state == FAX_SEND_STATE_ABORT:  # ----------------- Abort (110, 10, 0)
                        monitor_state = False
                        fax_send_state = FAX_SEND_STATE_CANCELJOB
                        state = STATE_ABORTED

                    elif fax_send_state == FAX_SEND_STATE_ERROR:  # --------------- Error (110, 20, 0)
                        log.error("Fax send error.")
                        monitor_state = False
                        fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
                        state = STATE_ERROR

                    elif fax_send_state == FAX_SEND_STATE_BUSY:  # ---------------- Busy (110, 25, 0)
                        log.error("Fax device busy.")
                        monitor_state = False
                        fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
                        state = STATE_BUSY

                    elif fax_send_state == FAX_SEND_STATE_SUCCESS:  # ------------- Success (110, 30, 0)
                        log.debug("Fax send success.")
                        monitor_state = False
                        fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
                        state = STATE_NEXT_RECIPIENT

                    elif fax_send_state == FAX_SEND_STATE_DEVICE_OPEN:  # --------- Device open (110, 40, 0)
                        log.debug("%s State: Open device" % ("*" * 20))
                        fax_send_state = FAX_SEND_STATE_BEGINJOB
                        try:
                            self.dev.open()
                        except Error as e:
                            log.error("Unable to open device (%s)." % e.msg)
                            fax_send_state = FAX_SEND_STATE_ERROR
                        else:
                            if self.dev.device_state == DEVICE_STATE_NOT_FOUND:
                                fax_send_state = FAX_SEND_STATE_ERROR

                    elif fax_send_state == FAX_SEND_STATE_BEGINJOB:  # -------------- BeginJob (110, 50, 0)
                        log.debug("%s State: BeginJob" % ("*" * 20))
                        try:
                            ff = open(self.f, 'rb')
                        except IOError:
                            log.error("Unable to read fax file.")
                            fax_send_state = FAX_SEND_STATE_ERROR
                            continue

                        try:
                            header = ff.read(FILE_HEADER_SIZE)
                        except IOError:
                            log.error("Unable to read fax file.")
                            fax_send_state = FAX_SEND_STATE_ERROR
                            continue

                        magic, version, total_pages, hort_dpi, vert_dpi, page_size, \
                            resolution, encoding, reserved1, reserved2 = self.decode_fax_header(header)

                        if magic != to_bytes_utf8('hplip_g3'):
                            log.error("Invalid file header. Bad magic.")
                            fax_send_state = FAX_SEND_STATE_ERROR
                        else:
                            log.debug(
                                "Magic=%s Ver=%d Pages=%d hDPI=%d vDPI=%d Size=%d Res=%d Enc=%d"
                                % (magic, version, total_pages, hort_dpi,
                                   vert_dpi, page_size, resolution, encoding))

                        faxnum = recipient['fax']

                        createJob = createJobXML % (faxnum, total_pages)
                        data = self.format_http_post("/FaxPCSend/Job",
                                                     len(createJob), createJob)
                        log.log_data(data)

                        self.dev.openLEDM()
                        self.dev.writeLEDM(to_bytes_utf8(data))
                        response = BytesIO()
                        try:
                            while self.dev.readLEDM(512, response, timeout=5):
                                pass
                        except Error:
                            fax_send_state = FAX_SEND_STATE_ERROR
                            self.dev.closeLEDM()
                            break
                        self.dev.closeLEDM()

                        response = response.getvalue()
                        log.log_data(response)
                        if self.get_error_code(response) == HTTP_CREATED:
                            fax_send_state = FAX_SEND_STATE_DOWNLOADPAGES
                        elif self.get_error_code(
                                response
                        ) == HTTP_SERVICE_UNAVALIABLE and num_tries <= MAX_TRIES:
                            fax_send_state = FAX_SEND_STATE_BEGINJOB
                            num_tries += 1
                        else:
                            if num_tries > MAX_TRIES:
                                log.error(
                                    "HTTP ERROR CODE: 531, Server Temporary Unavailable"
                                )
                            fax_send_state = FAX_SEND_STATE_ERROR
                            log.error("Create Job request failed")
                            break
                        pos = response.find(b"/Jobs/JobList/", 0,
                                            len(response))
                        pos1 = response.find(b"Content-Length", 0,
                                             len(response))
                        pos2 = response.find(b"Cache-Control", 0,
                                             len(response))
                        jobListURI = response[pos:pos1].strip()
                        jobListURI = jobListURI.replace(b'\r', b'').replace(
                            b'\n', b'')
                        if jobListURI == '':
                            jobListURI = response[pos:pos2].strip()
                            jobListURI = jobListURI.replace(b'\r',
                                                            b'').replace(
                                                                b'\n', b'')
                            log.debug("jobListURI = [%s] type=%s" %
                                      (jobListURI, type(jobListURI)))
                        if type(jobListURI) != str:
                            jobListURI = jobListURI.decode('utf-8')

                    elif fax_send_state == FAX_SEND_STATE_DOWNLOADPAGES:  # -------------- DownloadPages (110, 60, 0)
                        log.debug("%s State: DownloadPages" % ("*" * 20))
                        page = BytesIO()
                        log.debug("Total Number of pages are:%d" % total_pages)
                        for p in range(total_pages):

                            if self.check_for_cancel():
                                fax_send_state = FAX_SEND_STATE_ABORT

                            if fax_send_state == FAX_SEND_STATE_ABORT:
                                break

                            try:
                                header = ff.read(PAGE_HEADER_SIZE)
                            except IOError:
                                log.error("Unable to read fax file.")
                                fax_send_state = FAX_SEND_STATE_ERROR
                                continue

                            page_num, ppr, rpp, bytes_to_read, thumbnail_bytes, reserved2 = \
                                self.decode_page_header(header)

                            log.debug("Page=%d PPR=%d RPP=%d BPP=%d Thumb=%d" %
                                      (page_num, ppr, rpp, bytes_to_read,
                                       thumbnail_bytes))

                            if ppr != PIXELS_PER_LINE:
                                log.error(
                                    "Pixels per line (width) must be %d!" %
                                    PIXELS_PER_LINE)

                            page.write(ff.read(bytes_to_read))
                            thumbnail = ff.read(
                                thumbnail_bytes
                            )  # thrown away for now (should be 0 read)
                            page.seek(0)

                            try:
                                data = page.read(bytes_to_read)
                            except IOError:
                                log.error("Unable to read fax file.")
                                fax_send_state = FAX_SEND_STATE_ERROR
                                break

                            if data == b'':
                                log.error("No data!")
                                fax_send_state = FAX_SEND_STATE_ERROR
                                break

                            pageConfigURI = self.dev.readAttributeFromXml(
                                jobListURI,
                                "j:job-faxpcsendstatus-resourceuri")
                            log.debug("pageConfigURI:[%s]" % pageConfigURI)

                            pageConfig = pageConfigXML % (page_num, hort_dpi,
                                                          vert_dpi)
                            xmldata = self.format_http_post(
                                pageConfigURI, len(pageConfig), pageConfig)
                            log.log_data(xmldata)

                            self.dev.openLEDM()
                            try:
                                self.dev.writeLEDM(xmldata)
                            except Error:
                                fax_send_state = FAX_SEND_STATE_ERROR
                                self.dev.closeLEDM()
                                break

                            response = BytesIO()
                            try:
                                while self.dev.readLEDM(512,
                                                        response,
                                                        timeout=5):
                                    pass
                            except Error:
                                fax_send_state = FAX_SEND_STATE_ERROR
                                self.dev.closeLEDM()
                                break

                            self.dev.closeLEDM()
                            response = (response.getvalue())
                            log.log_data(response)
                            if self.get_error_code(response) != HTTP_ACCEPTED:
                                fax_send_state = FAX_SEND_STATE_ERROR
                                log.error(
                                    "Page config data is not accepted by the device"
                                )
                                break

                            pageImageURI = self.dev.readAttributeFromXml(
                                jobListURI,
                                "j:job-faxpcsendstatus-resourceuri")
                            while (True):
                                if self.check_for_cancel():
                                    fax_send_state = FAX_SEND_STATE_ABORT
                                    break

                                Status, Fax_State = self.checkForError(
                                    jobListURI)
                                if Status == FAX_SEND_STATE_ERROR and (
                                        Fax_State
                                        == STATUS_ERROR_IN_TRANSMITTING or
                                        Fax_State == STATUS_ERROR_IN_CONNECTING
                                        or Fax_State
                                        == STATUS_ERROR_PROBLEM_IN_FAXLINE
                                        or Fax_State == STATUS_JOB_CANCEL):
                                    log.debug(
                                        "setting state to FAX_SEND_STATE_ERROR"
                                    )
                                    fax_send_state = FAX_SEND_STATE_ERROR
                                    error_state = Fax_State
                                    break
                                elif Status == FAX_SEND_STATE_SUCCESS:
                                    break

                            if fax_send_state == FAX_SEND_STATE_ABORT or fax_send_state == FAX_SEND_STATE_ERROR:
                                break

                            xmldata = self.format_http_post(
                                pageImageURI, len(data), "",
                                "application/octet-stream")
                            log.debug(
                                "Sending Page Image XML Data [%s] to the device"
                                % xmldata)
                            self.dev.openLEDM()
                            self.dev.writeLEDM(xmldata)
                            log.debug(
                                "Sending Raw Data to printer............")
                            try:
                                self.dev.writeLEDM(data)
                            except Error:
                                fax_send_state = FAX_SEND_STATE_ERROR
                                self.dev.closeLEDM()
                                break

                            response = BytesIO()
                            try:
                                while self.dev.readLEDM(512,
                                                        response,
                                                        timeout=10):
                                    pass
                            except Error:
                                fax_send_state = FAX_SEND_STATE_ERROR
                                self.dev.closeLEDM()
                                break

                            self.dev.closeLEDM()
                            response = response.getvalue()
                            log.log_data(response)

                            if self.get_error_code(response) != HTTP_ACCEPTED:
                                log.error(
                                    "Image Data is not accepted by the device")
                                fax_send_state = FAX_SEND_STATE_ERROR
                                break

                            page.truncate(0)
                            page.seek(0)

                        else:
                            fax_send_state = FAX_SEND_STATE_ENDJOB

                    elif fax_send_state == FAX_SEND_STATE_ENDJOB:  # -------------- EndJob (110, 70, 0)
                        fax_send_state = FAX_SEND_STATE_SUCCESS

                    elif fax_send_state == FAX_SEND_STATE_CANCELJOB:  # -------------- CancelJob (110, 80, 0)
                        log.debug("%s State: CancelJob" % ("*" * 20))

                        xmldata = cancelJobXML % (jobListURI)
                        data = self.format_http_put(jobListURI, len(xmldata),
                                                    xmldata)
                        log.log_data(data)

                        self.dev.openLEDM()
                        self.dev.writeLEDM(to_bytes_utf8(data))

                        response = BytesIO()
                        try:
                            while self.dev.readLEDM(512, response, timeout=10):
                                pass
                        except Error:
                            fax_send_state = FAX_SEND_STATE_ERROR
                            self.dev.closeLEDM()
                            break
                        self.dev.closeLEDM()
                        response = response.getvalue()
                        log.log_data(response)

                        if self.get_error_code(response) == HTTP_OK:
                            fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
                        else:
                            fax_send_state = FAX_SEND_STATE_ERROR
                            log.error("Job Cancel Request Failed")

                    elif fax_send_state == FAX_SEND_STATE_CLOSE_SESSION:  # -------------- Close session (110, 170, 0)
                        log.debug("%s State: Close session" % ("*" * 20))
                        log.debug("Closing session...")

                        try:
                            ff.close()
                        except NameError:
                            pass

                        #time.sleep(1)

                        self.dev.closeLEDM()
                        self.dev.close()

                        fax_send_state = FAX_SEND_STATE_DONE  # Exit inner state machine

            elif state == STATE_CLEANUP:  # --------------------------------- Cleanup (120, 0, 0)
                log.debug("%s State: Cleanup" % ("*" * 20))

                if self.remove_temp_file:
                    log.debug("Removing merged file: %s" % self.f)
                    try:
                        os.remove(self.f)
                        log.debug("Removed")
                    except OSError:
                        log.debug("Not found")

                state = STATE_DONE  # Exit outer state machine
Beispiel #20
0
    def run(self):
        #results = {} # {'file' : error_code,...}

        STATE_DONE = 0
        STATE_ABORTED = 10
        STATE_SUCCESS = 20
        STATE_BUSY = 25
        STATE_READ_SENDER_INFO = 30
        STATE_PRERENDER = 40
        STATE_COUNT_PAGES = 50
        STATE_NEXT_RECIPIENT = 60
        STATE_COVER_PAGE = 70
        STATE_SINGLE_FILE = 80
        STATE_MERGE_FILES = 90
        STATE_SINGLE_FILE = 100
        STATE_SEND_FAX = 110
        STATE_CLEANUP = 120
        STATE_ERROR = 130

        next_recipient = self.next_recipient_gen()

        state = STATE_READ_SENDER_INFO
        self.rendered_file_list = []

        while state != STATE_DONE: # --------------------------------- Fax state machine
            if self.check_for_cancel():
                state = STATE_ABORTED

            log.debug("STATE=(%d, 0, 0)" % state)

            if state == STATE_ABORTED: # --------------------------------- Aborted (10, 0, 0)
                log.error("Aborted by user.")
                self.write_queue((STATUS_IDLE, 0, ''))
                state = STATE_CLEANUP


            elif state == STATE_SUCCESS: # --------------------------------- Success (20, 0, 0)
                log.debug("Success.")
                self.write_queue((STATUS_COMPLETED, 0, ''))
                state = STATE_CLEANUP


            elif state == STATE_ERROR: # --------------------------------- Error (130, 0, 0)
                log.error("Error, aborting.")
                self.write_queue((STATUS_ERROR, 0, ''))
                state = STATE_CLEANUP


            elif state == STATE_BUSY: # --------------------------------- Busy (25, 0, 0)
                log.error("Device busy, aborting.")
                self.write_queue((STATUS_BUSY, 0, ''))
                state = STATE_CLEANUP


            elif state == STATE_READ_SENDER_INFO: # --------------------------------- Get sender info (30, 0, 0)
                log.debug("%s State: Get sender info" % ("*"*20))
                state = STATE_PRERENDER
                try:
                    try:
                        self.dev.open()
                    except Error as e:
                        log.error("Unable to open device (%s)." % e.msg)
                        state = STATE_ERROR
                    else:
                        try:
                            self.sender_name = self.dev.station_name
                            log.debug("Sender name=%s" % self.sender_name)
                            self.sender_fax = self.dev.phone_num
                            log.debug("Sender fax=%s" % self.sender_fax)
                        except Error:
                            log.error("HTTP GET failed!")
                            state = STATE_ERROR

                finally:
                    self.dev.close()


            elif state == STATE_PRERENDER: # --------------------------------- Pre-render non-G4 files (40, 0, 0)
                log.debug("%s State: Pre-render non-G4 files" % ("*"*20))
                state = self.pre_render(STATE_COUNT_PAGES)

            elif state == STATE_COUNT_PAGES: # --------------------------------- Get total page count (50, 0, 0)
                log.debug("%s State: Get total page count" % ("*"*20))
                state = self.count_pages(STATE_NEXT_RECIPIENT)

            elif state == STATE_NEXT_RECIPIENT: # --------------------------------- Loop for multiple recipients (60, 0, 0)
                log.debug("%s State: Next recipient" % ("*"*20))
                state = STATE_COVER_PAGE

                try:
                    recipient = next(next_recipient)
                    log.debug("Processing for recipient %s" % recipient['name'])
                    self.write_queue((STATUS_SENDING_TO_RECIPIENT, 0, recipient['name']))
                except StopIteration:
                    state = STATE_SUCCESS
                    log.debug("Last recipient.")
                    continue

                recipient_file_list = self.rendered_file_list[:]


            elif state == STATE_COVER_PAGE: # --------------------------------- Create cover page (70, 0, 0)
                log.debug("%s State: Render cover page" % ("*"*20))
                state = self.cover_page(recipient)


            elif state == STATE_SINGLE_FILE: # --------------------------------- Special case for single file (no merge) (80, 0, 0)
                log.debug("%s State: Handle single file" % ("*"*20))
                state = self.single_file(STATE_SEND_FAX)

            elif state == STATE_MERGE_FILES: # --------------------------------- Merge multiple G4 files (90, 0, 0)
                log.debug("%s State: Merge multiple files" % ("*"*20))
                state = self.merge_files(STATE_SEND_FAX)

            elif state == STATE_SEND_FAX: # --------------------------------- Send fax state machine (110, 0, 0)
                log.debug("%s State: Send fax" % ("*"*20))
                state = STATE_NEXT_RECIPIENT

                FAX_SEND_STATE_DONE = 0
                FAX_SEND_STATE_ABORT = 10
                FAX_SEND_STATE_ERROR = 20
                FAX_SEND_STATE_BUSY = 25
                FAX_SEND_STATE_SUCCESS = 30
                FAX_SEND_STATE_DEVICE_OPEN = 40
                FAX_SEND_STATE_BEGINJOB = 50
                FAX_SEND_STATE_DOWNLOADPAGES = 60
                FAX_SEND_STATE_ENDJOB = 70
                FAX_SEND_STATE_CANCELJOB = 80
                FAX_SEND_STATE_CLOSE_SESSION = 170

                monitor_state = False
                fax_send_state = FAX_SEND_STATE_DEVICE_OPEN

                while fax_send_state != FAX_SEND_STATE_DONE:

                    if self.check_for_cancel():
                        log.error("Fax send aborted.")
                        fax_send_state = FAX_SEND_STATE_ABORT

                    if monitor_state:
                        fax_state = self.getFaxDownloadState()
                        if not fax_state in (pml.UPDN_STATE_XFERACTIVE, pml.UPDN_STATE_XFERDONE):
                            log.error("D/L error state=%d" % fax_state)
                            fax_send_state = FAX_SEND_STATE_ERROR
                            state = STATE_ERROR

                    log.debug("STATE=(%d, %d, 0)" % (STATE_SEND_FAX, fax_send_state))

                    if fax_send_state == FAX_SEND_STATE_ABORT: # -------------- Abort (110, 10, 0)
                        monitor_state = False
                        fax_send_state = FAX_SEND_STATE_CANCELJOB
                        state = STATE_ABORTED

                    elif fax_send_state == FAX_SEND_STATE_ERROR: # -------------- Error (110, 20, 0)
                        log.error("Fax send error.")
                        monitor_state = False
                        fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
                        state = STATE_ERROR

                    elif fax_send_state == FAX_SEND_STATE_BUSY: # -------------- Busy (110, 25, 0)
                        log.error("Fax device busy.")
                        monitor_state = False
                        fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
                        state = STATE_BUSY

                    elif fax_send_state == FAX_SEND_STATE_SUCCESS: # -------------- Success (110, 30, 0)
                        log.debug("Fax send success.")
                        monitor_state = False
                        fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
                        state = STATE_NEXT_RECIPIENT

                    elif fax_send_state == FAX_SEND_STATE_DEVICE_OPEN: # -------------- Device open (110, 40, 0)
                        log.debug("%s State: Open device" % ("*"*20))
                        fax_send_state = FAX_SEND_STATE_BEGINJOB
                        try:
                            self.dev.open()
                        except Error as e:
                            log.error("Unable to open device (%s)." % e.msg)
                            fax_send_state = FAX_SEND_STATE_ERROR
                        else:
                            if self.dev.device_state == DEVICE_STATE_NOT_FOUND:
                                fax_send_state = FAX_SEND_STATE_ERROR

                    elif fax_send_state == FAX_SEND_STATE_BEGINJOB: # -------------- BeginJob (110, 50, 0)
                        log.debug("%s State: BeginJob" % ("*"*20))

                        try:
                            ff = open(self.f, 'rb')
                        except IOError:
                            log.error("Unable to read fax file.")
                            fax_send_state = FAX_SEND_STATE_ERROR
                            continue

                        try:
                            header = ff.read(FILE_HEADER_SIZE)
                        except IOError:
                            log.error("Unable to read fax file.")
                            fax_send_state = FAX_SEND_STATE_ERROR
                            continue

                        magic, version, total_pages, hort_dpi, vert_dpi, page_size, \
                            resolution, encoding, reserved1, reserved2 = self.decode_fax_header(header)

                        if magic != b'hplip_g3':
                            log.error("Invalid file header. Bad magic.")
                            fax_send_state = FAX_SEND_STATE_ERROR
                        else:
                            log.debug("Magic=%s Ver=%d Pages=%d hDPI=%d vDPI=%d Size=%d Res=%d Enc=%d" %
                                      (magic, version, total_pages, hort_dpi, vert_dpi, page_size,
                                       resolution, encoding))

                        job_id = self.job_id
                        delay = 0
                        faxnum = recipient['fax']
                        speeddial = 0

                        if resolution == RESOLUTION_STD:
                            res = "STANDARD"
                        elif resolution == RESOLUTION_FINE:
                            res = "FINE"
                        elif resolution == RESOLUTION_300DPI:
                            res = "SUPERFINE"

                        soap = utils.cat(
"""<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><Fax:BeginJob xmlns:Fax="urn:Fax"><ticket xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Fax:Ticket"><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:string">$job_id</jobId><resolution xsi:type="Fax:Resolution">$res</resolution><delay xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:positiveInteger">$delay</delay><phoneNumber xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:string">$faxnum</phoneNumber><speedDial xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:positiveInteger">$speeddial</speedDial></ticket></Fax:BeginJob></SOAP-ENV:Body></SOAP-ENV:Envelope>""")

                        data = self.format_http(soap.encode('utf-8'))

                        log.log_data(data)

                        if log.is_debug():
                            open('beginjob.log', 'wb').write(data)
                        self.dev.openSoapFax()
                        self.dev.writeSoapFax(data)
                        ret = BytesIO()

                        while self.dev.readSoapFax(8192, ret, timeout=5):
                            pass

                        ret = ret.getvalue()

                        if log.is_debug():
                            open('beginjob_ret.log', 'wb').write(ret)
                        log.log_data(ret)
                        self.dev.closeSoapFax()

                        if self.get_error_code(ret.decode('utf-8')) == HTTP_OK:
                            fax_send_state = FAX_SEND_STATE_DOWNLOADPAGES
                        else:
                            fax_send_state = FAX_SEND_STATE_ERROR


                    elif fax_send_state == FAX_SEND_STATE_DOWNLOADPAGES: # -------------- DownloadPages (110, 60, 0)
                        log.debug("%s State: DownloadPages" % ("*"*20))
                        page = BytesIO()
                        for p in range(total_pages):

                            if self.check_for_cancel():
                                fax_send_state = FAX_SEND_STATE_ABORT

                            if fax_send_state == FAX_SEND_STATE_ABORT:
                                break

                            try:
                                header = ff.read(PAGE_HEADER_SIZE)
                            except IOError:
                                log.error("Unable to read fax file.")
                                fax_send_state = FAX_SEND_STATE_ERROR
                                continue

                            page_num, ppr, rpp, bytes_to_read, thumbnail_bytes, reserved2 = \
                                self.decode_page_header(header)

                            log.debug("Page=%d PPR=%d RPP=%d BPP=%d Thumb=%d" %
                                      (page_num, ppr, rpp, bytes_to_read, thumbnail_bytes))

                            if ppr != PIXELS_PER_LINE:
                                log.error("Pixels per line (width) must be %d!" % PIXELS_PER_LINE)

                            page.write(ff.read(bytes_to_read))
                            thumbnail = ff.read(thumbnail_bytes) # thrown away for now (should be 0 read)
                            page.seek(0)

                            try:
                                data = page.read(bytes_to_read)
                            except IOError:
                                log.error("Unable to read fax file.")
                                fax_send_state = FAX_SEND_STATE_ERROR
                                break

                            if data == b'':
                                log.error("No data!")
                                fax_send_state = FAX_SEND_STATE_ERROR
                                break

                            height = rpp
                            job_id = self.job_id

                            soap = utils.cat(
"""<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string" SOAP-ENV:mustUnderstand="1">$job_id</jobId></SOAP-ENV:Header><SOAP-ENV:Body><Fax:DownloadPage xmlns:Fax="urn:Fax"><height xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:positiveInteger">$height</height></Fax:DownloadPage></SOAP-ENV:Body></SOAP-ENV:Envelope>""")

                            m = dime.Message()
                            m.add_record(dime.Record(b"cid:id0", b"http://schemas.xmlsoap.org/soap/envelope/",
                                dime.TYPE_T_URI, to_bytes_utf8(soap)))

                            m.add_record(dime.Record(b"", b"image/g4fax", dime.TYPE_T_MIME, data))

                            output = BytesIO()
                            m.generate(output)
                            data = self.format_http(output.getvalue(), content_type="application/dime")
                            log.log_data(data)
                            if log.is_debug():
                                           open('downloadpages%d.log' % p, 'wb').write(data)
                            try:
                                self.dev.writeSoapFax(data)
                            except Error:
                                fax_send_state = FAX_SEND_STATE_ERROR

                            ret = BytesIO()

                            try:
                                while self.dev.readSoapFax(8192, ret, timeout=5):
                                    pass
                            except Error:
                                fax_send_state = FAX_SEND_STATE_ERROR

                            ret = ret.getvalue()

                            if log.is_debug():
                                open('downloadpages%d_ret.log' % p, 'wb').write(ret)

                            log.log_data(ret)
                            self.dev.closeSoapFax()

                            if self.get_error_code(ret.decode('utf-8')) != HTTP_OK:
                                fax_send_state = FAX_SEND_STATE_ERROR
                                break

                            page.truncate(0)
                            page.seek(0)

                        else:
                            fax_send_state = FAX_SEND_STATE_ENDJOB


                    elif fax_send_state == FAX_SEND_STATE_ENDJOB: # -------------- EndJob (110, 70, 0)
                        log.debug("%s State: EndJob" % ("*"*20))

                        job_id = self.job_id

                        soap = utils.cat(
"""<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string" SOAP-ENV:mustUnderstand="1">$job_id</jobId></SOAP-ENV:Header><SOAP-ENV:Body><Fax:EndJob xmlns:Fax="urn:Fax"><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">$job_id</jobId></Fax:EndJob></SOAP-ENV:Body></SOAP-ENV:Envelope>""")

                        data = self.format_http(soap.encode('utf-8'))

                        log.log_data(data)

                        if log.is_debug():
                            open('endjob.log', 'wb').write(data)

                        self.dev.writeSoapFax(data)
                        ret = BytesIO()

                        while self.dev.readSoapFax(8192, ret, timeout=5):
                            pass

                        ret = ret.getvalue()

                        if log.is_debug():
                            open('endjob_ret.log', 'wb').write(ret)

                        log.log_data(ret)
                        self.dev.closeSoapFax()

                        if self.get_error_code(ret.decode('utf-8')) == HTTP_OK:
                            fax_send_state = FAX_SEND_STATE_SUCCESS
                        else:
                            fax_send_state = FAX_SEND_STATE_ERROR

                    elif fax_send_state == FAX_SEND_STATE_CANCELJOB: # -------------- CancelJob (110, 80, 0)
                        log.debug("%s State: CancelJob" % ("*"*20))

                        job_id = self.job_id

                        soap = utils.cat(
"""<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string" SOAP-ENV:mustUnderstand="1">$job_id</jobId></SOAP-ENV:Header><SOAP-ENV:Body><Fax:CancelJob xmlns:Fax="urn:Fax"><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">$job_id</jobId></Fax:CancelJob></SOAP-ENV:Body></SOAP-ENV:Envelope>""")

                        data = self.format_http(soap.encode('utf-8'))

                        log.log_data(data)

                        if log.is_debug():
                            open('canceljob.log', 'wb').write(data)

                        self.dev.writeSoapFax(data)
                        ret = BytesIO()

                        while self.dev.readSoapFax(8192, ret, timeout=5):
                            pass

                        ret = ret.getvalue()

                        if log.is_debug():
                            open('canceljob_ret.log', 'wb').write(ret)

                        log.log_data(ret)
                        self.dev.closeSoapFax()

                        if self.get_error_code(ret.decode('utf-8')) == HTTP_OK:
                            fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
                        else:
                            fax_send_state = FAX_SEND_STATE_ERROR


                    elif fax_send_state == FAX_SEND_STATE_CLOSE_SESSION: # -------------- Close session (110, 170, 0)
                        log.debug("%s State: Close session" % ("*"*20))
                        log.debug("Closing session...")

                        try:
                            mm.close()
                        except NameError:
                            pass

                        try:
                            ff.close()
                        except NameError:
                            pass

                        time.sleep(1)

                        self.dev.closeSoapFax()
                        self.dev.close()

                        fax_send_state = FAX_SEND_STATE_DONE # Exit inner state machine


            elif state == STATE_CLEANUP: # --------------------------------- Cleanup (120, 0, 0)
                log.debug("%s State: Cleanup" % ("*"*20))

                if self.remove_temp_file:
                    log.debug("Removing merged file: %s" % self.f)
                    try:
                        os.remove(self.f)
                        log.debug("Removed")
                    except OSError:
                        log.debug("Not found")

                state = STATE_DONE # Exit outer state machine