class PrinterManager(object):
    BOUNDARY = mimetools.choose_boundary()
    CRLF = '\r\n'
    requestors = None
    cachedPrinterDetails = {}
    reservedCapabilityWords = set((
        'Duplex', 'Resolution', 'Attribute', 'Choice', 'ColorDevice', 'ColorModel', 'ColorProfile',
        'Copyright', 'CustomMedia', 'Cutter', 'Darkness', 'DriverType', 'FileName', 'Filter',
        'Filter', 'Finishing', 'Font', 'Group', 'HWMargins', 'InputSlot', 'Installable',
        'LocAttribute', 'ManualCopies', 'Manufacturer', 'MaxSize', 'MediaSize', 'MediaType',
        'MinSize', 'ModelName', 'ModelNumber', 'Option', 'PCFileName', 'SimpleColorProfile',
        'Throughput', 'UIConstraints', 'VariablePaperSize', 'Version', 'Color', 'Background',
        'Stamp', 'DestinationColorProfile'
    ))
    URIFormatLatest = 9999
    URIFormat20140308 = 3
    URIFormat20140307 = 2
    URIFormat20140210 = 1
    backendDescription =\
        'network %s "%s" "Google Cloud Print" "MFG:Google;MDL:Cloud Print;DES:GoogleCloudPrint;"'

    def __init__(self, requestors):
        """Create an instance of PrinterManager, with authorised requestor

        Args:
          requestors: list or CloudPrintRequestor instance, A list of
          requestors, or a single requestor to use for all Cloud Print
          requests.
        """
        self._cupsHelper = CUPSHelper()
        if requestors is not None:
            if isinstance(requestors, list):
                self.requestors = requestors
            else:
                self.requestors = [requestors]

    def getCUPSPrintersForAccount(self, account):
        cupsprinters = self._cupsHelper.getPrinters()
        accountPrinters = []
        for cupsprinter in cupsprinters:
            printer = self.getPrinterByURI(cupsprinters[cupsprinter]['device-uri'])
            if printer is not None:
                if printer.getAccount() == account:
                    accountPrinters.append(cupsprinters[cupsprinter])
        return accountPrinters

    def getPrinter(self, printerId, accountName):
        """Fetch one printer, including capabilities.

        Args:
          printerId: something like e64b1063-80e7-a87e-496c-3caa8cb7d736
          accountName: email address (account) printer is associated with

        Returns:
          A Printer object, or None if printer not found."""

        for requestor in self.requestors:
            if accountName != requestor.getAccount():
                continue

            response = requestor.printer(printerId)
            if response is None or not response['success'] \
                    or 'printers' not in response or not response['printers']:
                break

            return Printer(response['printers'][0], requestor, self._cupsHelper)

        return None

    def getPrinters(self, accountName=None):
        """Fetch a list of printers

        Returns:
          list: list of printers for the accounts.
        """
        if not hasattr(self, '_printers'):
            self._printers = []
            for requestor in self.requestors:
                if accountName is not None and accountName != requestor.getAccount():
                    continue

                responseobj = requestor.search()
                if 'printers' in responseobj:
                    for printer_info in responseobj['printers']:
                        self._printers.append(Printer(printer_info, requestor, self._cupsHelper))

        return self._printers

    def sanitizePrinterName(self, name):
        """Sanitizes printer name for CUPS

        Args:
          name: string, name of printer from Google Cloud Print

        Returns:
          string: CUPS-friendly name for the printer
        """
        return re.sub('[^a-zA-Z0-9\-_]', '', name.encode('ascii', 'replace').replace(' ', '_'))

    def addPrinter(self, printername, printer, location=None, ppd=None):
        """Adds a printer to CUPS

        Args:
          printername: string, name of the printer to add
          printer: Printer, CCP Printer object
          uri: string, uri of the Cloud Print device
          location: string, location of printer

        Returns:
          None
        """
        errorMessage = ""
        # fix printer name
        printername = self.sanitizePrinterName(printername)
        result = None
        printerppdname = None
        try:
            if ppd is None:
                printerppdname = printer.getPPDName()
            else:
                printerppdname = ppd
            if not location:
                location = printer.getLocation()
            if not location:
                location = 'Google Cloud Print'

            result = self._cupsHelper.addPrinter(
                printer, printername, location, printerppdname)
        except Exception as error:
            result = False
            errorMessage = error
        if result:
            print "Added " + printername
            return True
        else:
            print "Error adding: " + printername, errorMessage
            return False

    @staticmethod
    def _getAccountNameAndPrinterIdFromURI(uri):
        splituri = uri.rsplit('/', 2)
        accountName = urllib.unquote(splituri[1])
        printerId = urllib.unquote(splituri[2])
        return accountName, printerId

    def parseLegacyURI(self, uristring, requestors):
        """Parses previous CUPS Cloud Print URIs, only used for upgrades

        Args:
          uristring: string, uri of the Cloud Print device

        Returns:
          string: account name
          string: google cloud print printer name
          string: google cloud print printer id
          int: format id
        """
        formatId = None
        printerName = None
        accountName = None
        printerId = None
        uri = urlparse(uristring)
        pathparts = uri.path.strip('/').split('/')
        if uri.scheme == Utils.OLD_PROTOCOL_NAME:
            if len(pathparts) == 2:
                formatId = PrinterManager.URIFormat20140307
                printerId = urllib.unquote(pathparts[1])
                accountName = urllib.unquote(pathparts[0])
                printerName = urllib.unquote(uri.netloc)
            else:
                if urllib.unquote(uri.netloc) not in Auth.GetAccountNames(requestors):
                    formatId = PrinterManager.URIFormat20140210
                    printerName = urllib.unquote(uri.netloc)
                    accountName = urllib.unquote(pathparts[0])
                else:
                    formatId = PrinterManager.URIFormat20140308
                    printerId = urllib.unquote(pathparts[0])
                    printerName = None
                    accountName = urllib.unquote(uri.netloc)
        elif uri.scheme == Utils.PROTOCOL_NAME:
            formatId = PrinterManager.URIFormatLatest
            printerId = urllib.unquote(pathparts[0])
            printerName = None
            accountName = urllib.unquote(uri.netloc)

        return accountName, printerName, printerId, formatId

    def findRequestorForAccount(self, account):
        """Searches the requestors in the printer object for the requestor for a specific account

        Args:
          account: string, account name
        Return:
          requestor: Single requestor object for the account, or None if no account found
        """
        for requestor in self.requestors:
            if requestor.getAccount() == account:
                return requestor

    def getPrinterByURI(self, uri):
        accountName, printerId = self._getAccountNameAndPrinterIdFromURI(uri)
        return self.getPrinter(printerId, accountName)

    def getPrinterIDByDetails(self, account, printerid):
        """Gets printer id and requestor by printer

        Args:
          uri: string, printer uri
        Return:
          printer id: Single requestor object for the account, or None if no account found
          requestor: Single requestor object for the account
        """
        # find requestor based on account
        requestor = self.findRequestorForAccount(urllib.unquote(account))
        if requestor is None:
            return None, None

        if printerid is not None:
            return printerid, requestor
        else:
            return None, None
        else:
            add_account = True
        if not add_account:
            if not options.interactive:
                break
            answer = raw_input("Add more accounts (Y/N)? ")
            if answer.lower().startswith("y"):
                add_account = True
            else:
                break
        if add_account:
            Auth.AddAccount(None, userid=options.user)

    for requestor in requestors:
        addedCount = 0
        cupsprinters = cupsHelper.getPrinters()
        prefix = ""
        printer_manager = PrinterManager(requestor)
        printers = printer_manager.getPrinters()
        if printers is None:
            print "Sorry, no printers were found on your Google Cloud Print account."
            continue

        if options.add_all.lower() == "y":
            answer = "y"
        else:
            answer = raw_input("Add all Google Cloud Print printers from %s to CUPS (Y/N)? " %
                               requestor.getAccount())

        if not answer.lower().startswith("y"):
            answer = 1
class PrinterManager(object):
    BOUNDARY = mimetools.choose_boundary()
    CRLF = '\r\n'
    requestors = None
    cachedPrinterDetails = {}
    reservedCapabilityWords = set(
        ('Duplex', 'Resolution', 'Attribute', 'Choice', 'ColorDevice',
         'ColorModel', 'ColorProfile', 'Copyright', 'CustomMedia', 'Cutter',
         'Darkness', 'DriverType', 'FileName', 'Filter', 'Filter', 'Finishing',
         'Font', 'Group', 'HWMargins', 'InputSlot', 'Installable',
         'LocAttribute', 'ManualCopies', 'Manufacturer', 'MaxSize',
         'MediaSize', 'MediaType', 'MinSize', 'ModelName', 'ModelNumber',
         'Option', 'PCFileName', 'SimpleColorProfile', 'Throughput',
         'UIConstraints', 'VariablePaperSize', 'Version', 'Color',
         'Background', 'Stamp', 'DestinationColorProfile'))
    URIFormatLatest = 9999
    URIFormat20140308 = 3
    URIFormat20140307 = 2
    URIFormat20140210 = 1
    backendDescription =\
        'network %s "%s" "Google Cloud Print" "MFG:Google;MDL:Cloud Print;DES:GoogleCloudPrint;"'

    def __init__(self, requestors):
        """Create an instance of PrinterManager, with authorised requestor

        Args:
          requestors: list or CloudPrintRequestor instance, A list of
          requestors, or a single requestor to use for all Cloud Print
          requests.
        """
        self._cupsHelper = CUPSHelper()
        if requestors is not None:
            if isinstance(requestors, list):
                self.requestors = requestors
            else:
                self.requestors = [requestors]

    def getCUPSPrintersForAccount(self, account):
        cupsprinters = self._cupsHelper.getPrinters()
        accountPrinters = []
        for cupsprinter in cupsprinters:
            printer = self.getPrinterByURI(
                cupsprinters[cupsprinter]['device-uri'])
            if printer is not None:
                if printer.getAccount() == account:
                    accountPrinters.append(cupsprinters[cupsprinter])
        return accountPrinters

    def getPrinter(self, printerId, accountName):
        """Fetch one printer, including capabilities.

        Args:
          printerId: something like e64b1063-80e7-a87e-496c-3caa8cb7d736
          accountName: email address (account) printer is associated with

        Returns:
          A Printer object, or None if printer not found."""

        for requestor in self.requestors:
            if accountName != requestor.getAccount():
                continue

            response = requestor.printer(printerId)
            if response is None or not response['success'] \
                    or 'printers' not in response or not response['printers']:
                break

            return Printer(response['printers'][0], requestor,
                           self._cupsHelper)

        return None

    def getPrinters(self, accountName=None):
        """Fetch a list of printers

        Returns:
          list: list of printers for the accounts.
        """
        if not hasattr(self, '_printers'):
            self._printers = []
            for requestor in self.requestors:
                if accountName is not None and accountName != requestor.getAccount(
                ):
                    continue

                responseobj = requestor.search()
                if 'printers' in responseobj:
                    for printer_info in responseobj['printers']:
                        self._printers.append(
                            Printer(printer_info, requestor, self._cupsHelper))

        return self._printers

    def sanitizePrinterName(self, name):
        """Sanitizes printer name for CUPS

        Args:
          name: string, name of printer from Google Cloud Print

        Returns:
          string: CUPS-friendly name for the printer
        """
        return re.sub('[^a-zA-Z0-9\-_]', '',
                      name.encode('ascii', 'replace').replace(' ', '_'))

    def addPrinter(self, printername, printer, location=None, ppd=None):
        """Adds a printer to CUPS

        Args:
          printername: string, name of the printer to add
          printer: Printer, CCP Printer object
          uri: string, uri of the Cloud Print device
          location: string, location of printer

        Returns:
          None
        """
        errorMessage = ""
        # fix printer name
        printername = self.sanitizePrinterName(printername)
        result = None
        printerppdname = None
        try:
            if ppd is None:
                printerppdname = printer.getPPDName()
            else:
                printerppdname = ppd
            if not location:
                location = printer.getLocation()
            if not location:
                location = 'Google Cloud Print'

            result = self._cupsHelper.addPrinter(printer, printername,
                                                 location, printerppdname)
        except Exception as error:
            result = False
            errorMessage = error
        if result:
            print "Added " + printername
            return True
        else:
            print "Error adding: " + printername, errorMessage
            return False

    @staticmethod
    def _getAccountNameAndPrinterIdFromURI(uri):
        splituri = uri.rsplit('/', 2)
        accountName = urllib.unquote(splituri[1])
        printerId = urllib.unquote(splituri[2])
        return accountName, printerId

    def parseLegacyURI(self, uristring, requestors):
        """Parses previous CUPS Cloud Print URIs, only used for upgrades

        Args:
          uristring: string, uri of the Cloud Print device

        Returns:
          string: account name
          string: google cloud print printer name
          string: google cloud print printer id
          int: format id
        """
        formatId = None
        printerName = None
        accountName = None
        printerId = None
        uri = urlparse(uristring)
        pathparts = uri.path.strip('/').split('/')
        if uri.scheme == Utils.OLD_PROTOCOL_NAME:
            if len(pathparts) == 2:
                formatId = PrinterManager.URIFormat20140307
                printerId = urllib.unquote(pathparts[1])
                accountName = urllib.unquote(pathparts[0])
                printerName = urllib.unquote(uri.netloc)
            else:
                if urllib.unquote(
                        uri.netloc) not in Auth.GetAccountNames(requestors):
                    formatId = PrinterManager.URIFormat20140210
                    printerName = urllib.unquote(uri.netloc)
                    accountName = urllib.unquote(pathparts[0])
                else:
                    formatId = PrinterManager.URIFormat20140308
                    printerId = urllib.unquote(pathparts[0])
                    printerName = None
                    accountName = urllib.unquote(uri.netloc)
        elif uri.scheme == Utils.PROTOCOL_NAME:
            formatId = PrinterManager.URIFormatLatest
            printerId = urllib.unquote(pathparts[0])
            printerName = None
            accountName = urllib.unquote(uri.netloc)

        return accountName, printerName, printerId, formatId

    def findRequestorForAccount(self, account):
        """Searches the requestors in the printer object for the requestor for a specific account

        Args:
          account: string, account name
        Return:
          requestor: Single requestor object for the account, or None if no account found
        """
        for requestor in self.requestors:
            if requestor.getAccount() == account:
                return requestor

    def getPrinterByURI(self, uri):
        accountName, printerId = self._getAccountNameAndPrinterIdFromURI(uri)
        return self.getPrinter(printerId, accountName)

    def getPrinterIDByDetails(self, account, printerid):
        """Gets printer id and requestor by printer

        Args:
          uri: string, printer uri
        Return:
          printer id: Single requestor object for the account, or None if no account found
          requestor: Single requestor object for the account
        """
        # find requestor based on account
        requestor = self.findRequestorForAccount(urllib.unquote(account))
        if requestor is None:
            return None, None

        if printerid is not None:
            return printerid, requestor
        else:
            return None, None
Exemple #4
0
        else:
            add_account = True
        if not add_account:
            if not options.interactive:
                break
            answer = raw_input("Add more accounts (Y/N)? ")
            if answer.lower().startswith("y"):
                add_account = True
            else:
                break
        if add_account:
            Auth.AddAccount(None, userid=options.user)

    for requestor in requestors:
        addedCount = 0
        cupsprinters = cupsHelper.getPrinters()
        prefix = ""
        printer_manager = PrinterManager(requestor)
        printers = printer_manager.getPrinters()
        if printers is None:
            print "Sorry, no printers were found on your Google Cloud Print account."
            continue

        if options.add_all.lower() == "y":
            answer = "y"
        else:
            answer = raw_input(
                "Add all Google Cloud Print printers from %s to CUPS (Y/N)? " %
                requestor.getAccount())

        if not answer.lower().startswith("y"):