Changeset b01b6d1
- Timestamp:
- Jan 11, 2012, 12:51:51 AM (12 years ago)
- Branches:
- no-cups
- Children:
- be6ff03
- Parents:
- ffbe41d
- git-author:
- Jessica B. Hamrick <jhamrick@…> (01/11/12 00:51:51)
- git-committer:
- Jessica B. Hamrick <jhamrick@…> (01/11/12 00:51:51)
- Location:
- server/lib/gutenbach
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
server/lib/gutenbach/ipp/attributes/operation.py
re58af05 rb01b6d1 3 3 'RequestingUserName', 4 4 'IppAttributeFidelity', 5 'LastDocument' 5 'LastDocument', 6 'Limit', 7 'RequestedAttributes', 8 'WhichJobs', 9 'MyJobs', 10 'DocumentName', 11 'Compression', 12 'DocumentFormat', 13 'DocumentNaturalLanguage', 6 14 ] 7 15 … … 28 36 'last-document', 29 37 [Value(IntegerTags.BOOLEAN, val)]) 38 39 def Limit(val): 40 return Attribute( 41 'limit', 42 [Value(IntegerTags.INTEGER, val)]) 43 44 def RequestedAttributes(*vals): 45 return Attribute( 46 'requested-attributes', 47 [Value(CharacterStringTags.KEYWORD, val) for val in vals]) 48 49 def WhichJobs(val): 50 return Attribute( 51 'which-jobs', 52 [Value(CharacterStringTags.KEYWORD, val)]) 53 54 def MyJobs(val): 55 return Attribute( 56 'my-jobs', 57 [Value(IntegerTags.BOOLEAN, val)]) 58 59 def DocumentName(val): 60 return Attribute( 61 'document-name', 62 [Value(CharacterStringTags.NAME_WITHOUT_LANGUAGE, val)]) 63 64 def Compression(val): 65 return Attribute( 66 'compression', 67 [Value(CharacterStringTags.KEYWORD, val)]) 68 69 def DocumentFormat(val): 70 return Attribute( 71 'document-format', 72 [Value(CharacterStringTags.MIME_MEDIA_TYPE, val)]) 73 74 def DocumentNaturalLanguage(val): 75 return Attribute( 76 'document-natural-language', 77 [Value(CharacterStringTags.NATURAL_LANGUAGE, val)]) -
server/lib/gutenbach/ipp/core/errors.py
r1037115 rb01b6d1 43 43 44 44 45 from .constants import ErrorCodes 45 from .constants import ErrorCodes, AttributeTags 46 from .attributegroup import AttributeGroup 46 47 47 48 class IPPException(Exception): … … 106 107 def __init__(self, message, attrs): 107 108 self.message = message 108 self.bad_attrs = attrs 109 if hasattr(attrs, '__iter__'): 110 self.bad_attrs = attrs 111 else: 112 self.bad_attrs = [attrs] 109 113 110 114 def update_response(self, response): 111 pass 115 super(ClientErrorAttributes, self).update_response(response) 116 response.attribute_groups.append( 117 AttributeGroup( 118 AttributeTags.UNSUPPORTED, 119 self.bad_attrs)) 112 120 113 121 class ClientErrorUriSchemeNotSupported(IPPClientException): -
server/lib/gutenbach/server/errors.py
re58af05 rb01b6d1 1 1 __all__ = [ 2 2 'InvalidJobException', 3 'InvalidPrinterStateException' 3 'InvalidPrinterStateException', 4 'InvalidJobStateException', 4 5 ] 5 6 … … 7 8 def __init__(self, jobid): 8 9 self.jobid = jobid 9 10 10 def __str__(self): 11 return "Job with id '%d' does not exist!" % self.jobid11 return "Job does not exist: %d" % self.jobid 12 12 13 13 class InvalidPrinterStateException(Exception): 14 def __init__(self, message): 15 self.message = message 14 def __init__(self, state): 15 self.state = hex(state) 16 def __str__(self): 17 return "Invalid printer state: %s" % self.state 16 18 19 class InvalidJobStateException(Exception): 20 def __init__(self, state): 21 self.state = hex(state) 17 22 def __str__(self): 18 return self.message23 return "Invalid job state: %s" % self.state -
server/lib/gutenbach/server/job.py
rce2abc5 rb01b6d1 1 1 from . import InvalidJobException, InvalidPrinterStateException 2 from gutenbach.ipp import JobStates as States 2 3 import os 3 4 import gutenbach.ipp as ipp … … 21 22 ] 22 23 23 def __init__(self, jid, printer, creator="", name="", size=0): 24 """Initialize a Gutenbach job. 25 26 This sets the status to 'initializing' and optionally sets the 27 document to print to the value of document. 24 def __init__(self, job_id=-1, printer=None, creator=None, name=None, size=None): 25 """Create an empty Gutenbach job. 28 26 29 27 """ 30 28 31 self.jid = jid 32 self.printer = printer 33 34 self.creator = creator 35 self.name = name 36 self.size = size 29 self.printer = printer 30 self.player = None 31 32 self.id = job_id 33 self.creator = creator 34 self.name = name 35 self.size = size 36 self.status = States.HELD 37 37 38 38 self.document = None 39 39 self.document_name = None 40 self.player = None 41 42 self.status = ipp.JobStates.HELD 43 44 def __getattr__(self, attr): 40 self.document_format = None 41 self.document_natural_language = None 42 self.compression = None 43 44 def __repr__(self): 45 return str(self) 46 47 def __str__(self): 48 return "<Job %d '%s'>" % (self.id, self.name) 49 50 ###################################################################### 51 ### Properties ### 52 ###################################################################### 53 54 @property 55 def id(self): 56 """Unique job identifier. Should be a positive integer, 57 except when unassigned, when it defaults to -1. 58 59 """ 60 return self._id 61 @id.setter 62 def id(self, val): 45 63 try: 46 return self.__getattribute__(attr) 47 except AttributeError: 48 pass 49 return self.__getattribute__(attr.replace("-", "_")) 50 51 def __hasattr__(self, attr): 64 self._id = int(val) 65 except TypeError: 66 self._id = -1 67 68 @property 69 def creator(self): 70 """The user who created the job; analogous to the IPP 71 requesting-user-name. 72 73 """ 74 return self._creator 75 @creator.setter 76 def creator(self, val): 77 if val is None: 78 self._creator = "" 79 else: 80 self._creator = str(val) 81 82 @property 83 def name(self): 84 """The job's name. 85 86 """ 87 return self._name 88 @name.setter 89 def name(self, val): 90 if val is None: 91 self._name = "" 92 else: 93 self._name = str(val) 94 95 @property 96 def size(self): 97 """The size of the job in bytes. 98 99 """ 100 if self.document: 101 size = os.path.getsize(self.document.name) 102 else: 103 size = self._size 104 return size 105 @size.setter 106 def size(self, val): 52 107 try: 53 getattr(self, attr) 54 return True 55 except AttributeError: 56 return False 57 58 #### Job attributes 59 60 @property 61 def job_id(self): 62 return ipp.JobId(self.jid) 63 64 @property 65 def job_name(self): 66 return ipp.JobName(self.name) 67 68 # XXX: we need to actually calculate this! 69 @property 70 def job_originating_user_name(self): 71 return ipp.JobOriginatingUserName(self.creator) 72 73 # XXX: we need to actually calculate this! 74 @property 75 def job_k_octets(self): 76 return ipp.JobKOctets(self.size) 77 78 @property 79 def job_state(self): 80 return ipp.JobState(self.status) 81 82 @property 83 def job_printer_uri(self): 84 return ipp.JobPrinterUri(self.printer.uri) 85 86 def get_job_attributes(self, request=None): 87 if request and 'requested-attributes' in request: 88 requested = [] 89 for value in request['requested-attributes'].values: 90 if value.value in self.attributes: 91 requested.append(value.value) 92 else: 93 requested = self.attributes 94 95 attributes = [getattr(self, attr) for attr in requested] 96 return attributes 97 98 ####### 108 self._size = int(val) 109 except TypeError: 110 self._size = 0 111 112 ###################################################################### 113 ### Methods ### 114 ###################################################################### 99 115 100 116 def play(self): 101 117 logger.info("playing job %s" % str(self)) 102 118 # TODO: add external call to music player 103 self.status = ipp.JobStates.PROCESSING119 self.status = States.PROCESSING 104 120 self.player = subprocess.Popen( 105 121 "/usr/bin/mplayer -quiet %s" % self.document.name, … … 114 130 #logger.debug(self.player.stdout) 115 131 self.player = None 116 self.printer.complete_job(self. jid)132 self.printer.complete_job(self.id) 117 133 118 134 def finish(self): 119 135 logger.info("finished job %s" % str(self)) 120 self.status = ipp.JobStates.COMPLETE 121 122 def __repr__(self): 123 return str(self) 124 125 def __str__(self): 126 return "<Job %d '%s'>" % (self.jid if self.jid is not None else -1, self.name) 136 self.status = States.COMPLETE 137 138 ###################################################################### 139 ### IPP Attributes ### 140 ###################################################################### 141 142 @property 143 def job_id(self): 144 return ipp.JobId(self.id) 145 146 @property 147 def job_name(self): 148 return ipp.JobName(self.name) 149 150 # XXX: we need to actually calculate this! 151 @property 152 def job_originating_user_name(self): 153 return ipp.JobOriginatingUserName(self.creator) 154 155 # XXX: we need to actually calculate this! 156 @property 157 def job_k_octets(self): 158 return ipp.JobKOctets(self.size) 159 160 @property 161 def job_state(self): 162 return ipp.JobState(self.status) 163 164 @property 165 def job_printer_uri(self): 166 return ipp.JobPrinterUri(self.printer.uri) 167 168 169 ###################################################################### 170 ### IPP Operations ### 171 ###################################################################### 172 173 def cancel_job(self): 174 pass 175 176 def send_document(self, 177 document, 178 document_name=None, 179 document_format=None, 180 document_natural_language=None, 181 requesting_user_name=None, 182 compression=None, 183 last_document=None): 184 185 if self.status != States.HELD: 186 raise InvalidJobStateException(self.status) 187 188 self.document = document 189 self.document_name = str(document_name) 190 self.document_format = str(document_format) 191 self.document_natural_language = str(document_natural_language) 192 self.creator = str(requesting_user_name) 193 self.compression = str(compression) 194 self.status = States.PENDING 195 196 logger.debug("document for job %d is '%s'" % (self.id, self.document_name)) 197 198 def send_uri(self): 199 pass 200 201 def get_job_attributes(self, requested_attributes=None): 202 if requested_attributes is None: 203 requested = self.attributes 204 else: 205 requested = [a for a in self.attributes if a in requested_attributes] 206 207 _attributes = [attr.replace("-", "_") for attr in requested] 208 attributes = [getattr(self, attr) for attr in _attributes] 209 return attributes 210 211 def set_job_attributes(self): 212 pass 213 214 def restart_job(self): 215 pass 216 217 def promote_job(self): 218 pass -
server/lib/gutenbach/server/printer.py
rffbe41d rb01b6d1 1 1 from . import InvalidJobException, InvalidPrinterStateException 2 2 from . import Job 3 from gutenbach.ipp import PrinterStates as States 3 4 import gutenbach.ipp as ipp 4 5 import logging … … 43 44 ] 44 45 45 46 46 def __init__(self, name): 47 47 48 48 self.name = name 49 self.uri = "ipp://localhost:8000/printers/" + self.name50 49 self.time_created = int(time.time()) 51 self.state = "idle"50 self.state = States.IDLE 52 51 53 52 self.finished_jobs = [] … … 56 55 57 56 # cups ignores jobs with id 0, so we have to start at 1 58 self._next_jobid = 1 59 60 def __getattr__(self, attr): 61 try: 62 return self.__getattribute__(attr) 63 except AttributeError: 64 pass 65 return self.__getattribute__(attr.replace("-", "_")) 66 67 def __hasattr__(self, attr): 68 try: 69 getattr(self, attr) 70 return True 71 except AttributeError: 72 return False 73 74 ## Printer attributes 75 76 @property 77 def printer_uri_supported(self): 78 return ipp.PrinterUriSupported(self.uri) 79 80 @property 81 def uri_authentication_supported(self): 82 return ipp.UriAuthenticationSupported("none") 83 84 @property 85 def uri_security_supported(self): 86 return ipp.UriSecuritySupported("none") 87 88 @property 89 def printer_name(self): 90 return ipp.PrinterName(self.name) 91 92 @property 93 def printer_state(self): 94 return ipp.PrinterState(ipp.constants.PrinterStates.IDLE) 95 96 @property 97 def printer_state_reasons(self): 98 return ipp.PrinterStateReasons("none") 99 100 @property 101 def ipp_versions_supported(self): 102 return ipp.IppVersionsSupported("1.0", "1.1") 103 104 # XXX: We should query ourself for the supported operations 105 @property 106 def operations_supported(self): 107 return ipp.OperationsSupported(ipp.OperationCodes.GET_JOBS) 108 109 @property 110 def charset_configured(self): 111 return ipp.CharsetConfigured("utf-8") 112 113 @property 114 def charset_supported(self): 115 return ipp.CharsetSupported("utf-8") 116 117 @property 118 def natural_language_configured(self): 119 return ipp.NaturalLanguageConfigured("en-us") 120 121 @property 122 def generated_natural_language_supported(self): 123 return ipp.GeneratedNaturalLanguageSupported("en-us") 124 125 @property 126 def document_format_default(self): 127 return ipp.DocumentFormatDefault("application/octet-stream") 128 129 @property 130 def document_format_supported(self): 131 return ipp.DocumentFormatSupported("application/octet-stream", "audio/mp3") 132 133 @property 134 def printer_is_accepting_jobs(self): 135 return ipp.PrinterIsAcceptingJobs(True) 136 137 @property 138 def queued_job_count(self): 139 return ipp.QueuedJobCount(len(self.active_jobs)) 140 141 @property 142 def pdl_override_supported(self): 143 return ipp.PdlOverrideSupported("not-attempted") 144 145 @property 146 def printer_up_time(self): 147 return ipp.PrinterUpTime(int(time.time()) - self.time_created) 148 149 @property 150 def compression_supported(self): 151 return ipp.CompressionSupported("none") 152 153 @property 154 def multiple_operation_time_out(self): 155 return ipp.MultipleOperationTimeOut(240) 156 157 @property 158 def multiple_document_jobs_supported(self): 159 return ipp.MultipleDocumentJobsSupported(False) 160 161 ## Printer operations 162 163 def get_printer_attributes(self, request=None): 164 if request and 'requested-attributes' in request: 165 requested = [] 166 for value in request['requested-attributes'].values: 167 if value.value in self.attributes: 168 requested.append(value.value) 169 else: 170 requested = self.attributes 171 172 attributes = [getattr(self, attr) for attr in requested] 173 return attributes 174 175 def create_job(self, request): 176 operation = request.attribute_groups[0] 177 kwargs = {} 178 179 # requesting username 180 if 'requesting-user-name' in operation: 181 username_attr = operation['requesting-user-name'] 182 username = username_attr.values[0].value 183 if username_attr != ipp.RequestingUserName(username): 184 raise ipp.errors.ClientErrorBadRequest(str(username_attr)) 185 kwargs['creator'] = username 186 187 # job name 188 if 'job-name' in operation: 189 job_name_attr = operation['job-name'] 190 job_name = job_name_attr.values[0].value 191 if job_name_attr != ipp.JobName(job_name): 192 raise ipp.errors.ClientErrorBadRequest(str(job_name_attr)) 193 kwargs['name'] = job_name 194 195 # job size 196 if 'job-k-octets' in operation: 197 job_k_octets_attr = operation['job-k-octets'] 198 job_k_octets = job_k_octets_attr.values[0].value 199 if job_k_octets_attr != ipp.JobKOctets(job_k_octets): 200 raise ipp.errors.ClientErrorBadRequest(str(job_k_octets_attr)) 201 kwargs['size'] = job_k_octets 202 203 job_id = self._next_jobid 204 self._next_jobid += 1 205 206 job = Job(job_id, self, **kwargs) 207 self.jobs[job_id] = job 208 self.active_jobs.append(job_id) 57 self._next_jobid = 1 58 59 def __repr__(self): 60 return str(self) 61 62 def __str__(self): 63 return "<Printer '%s'>" % self.name 64 65 ###################################################################### 66 ### Properties ### 67 ###################################################################### 68 69 @property 70 def uris(self): 71 uris = ["ipp://localhost:8000/printers/" + self.name, 72 "ipp://localhost/printers/" + self.name] 73 return uris 74 75 @property 76 def uri(self): 77 return self.uris[0] 78 79 @property 80 def next_job(self): 81 if len(self.active_jobs) == 0: 82 job = None 83 else: 84 job = self.active_jobs[0] 209 85 return job 210 86 211 def send_document(self, jobid, document): 212 job = self.jobs[jobid] 213 if job.status != ipp.JobStates.HELD: 214 raise InvalidPrinterStateException( 215 "Invalid job state: %d" % job.status) 216 job.document = document 217 logger.debug("document for job %d is '%s'" % (jobid, job.document.name)) 218 job.status = ipp.JobStates.PENDING 219 220 def print_job(self, job): 221 pass 87 ###################################################################### 88 ### Methods ### 89 ###################################################################### 222 90 223 91 def complete_job(self, jobid): … … 225 93 self.finished_jobs.append(job) 226 94 job.finish() 227 return job. jid95 return job.id 228 96 229 97 def start_job(self, jobid): 230 98 job = self.jobs[self.active_jobs[0]] 231 99 if job.status != ipp.JobStates.PENDING: 232 raise InvalidPrinterStateException( 233 "Invalid job state: %s" % job.status) 100 raise InvalidPrinterStateException(job.status) 234 101 job.play() 235 236 @property237 def next_job(self):238 if len(self.active_jobs) == 0:239 job = None240 else:241 job = self.active_jobs[0]242 return job243 102 244 103 def stop(self): … … 255 114 return self.jobs[jobid] 256 115 257 def get_jobs(self): 258 print self.active_jobs 259 jobs = [self.jobs[job_id] for job_id in self.active_jobs] 260 return jobs 261 262 # def __repr__(self): 263 # return str(self) 264 265 # def __str__(self): 266 # return "<Printer '%s'>" % self.name 116 ###################################################################### 117 ### IPP Attributes ### 118 ###################################################################### 119 120 @property 121 def printer_uri_supported(self): 122 return ipp.PrinterUriSupported(self.uri) 123 124 @property 125 def uri_authentication_supported(self): 126 return ipp.UriAuthenticationSupported("none") 127 128 @property 129 def uri_security_supported(self): 130 return ipp.UriSecuritySupported("none") 131 132 @property 133 def printer_name(self): 134 return ipp.PrinterName(self.name) 135 136 @property 137 def printer_state(self): 138 return ipp.PrinterState(self.state) 139 140 @property 141 def printer_state_reasons(self): 142 return ipp.PrinterStateReasons("none") 143 144 @property 145 def ipp_versions_supported(self): 146 return ipp.IppVersionsSupported("1.0", "1.1") 147 148 # XXX: We should query ourself for the supported operations 149 @property 150 def operations_supported(self): 151 return ipp.OperationsSupported(ipp.OperationCodes.GET_JOBS) 152 153 @property 154 def charset_configured(self): 155 return ipp.CharsetConfigured("utf-8") 156 157 @property 158 def charset_supported(self): 159 return ipp.CharsetSupported("utf-8") 160 161 @property 162 def natural_language_configured(self): 163 return ipp.NaturalLanguageConfigured("en-us") 164 165 @property 166 def generated_natural_language_supported(self): 167 return ipp.GeneratedNaturalLanguageSupported("en-us") 168 169 @property 170 def document_format_default(self): 171 return ipp.DocumentFormatDefault("application/octet-stream") 172 173 @property 174 def document_format_supported(self): 175 return ipp.DocumentFormatSupported("application/octet-stream", "audio/mp3") 176 177 @property 178 def printer_is_accepting_jobs(self): 179 return ipp.PrinterIsAcceptingJobs(True) 180 181 @property 182 def queued_job_count(self): 183 return ipp.QueuedJobCount(len(self.active_jobs)) 184 185 @property 186 def pdl_override_supported(self): 187 return ipp.PdlOverrideSupported("not-attempted") 188 189 @property 190 def printer_up_time(self): 191 return ipp.PrinterUpTime(int(time.time()) - self.time_created) 192 193 @property 194 def compression_supported(self): 195 return ipp.CompressionSupported("none") 196 197 @property 198 def multiple_operation_time_out(self): 199 return ipp.MultipleOperationTimeOut(240) 200 201 @property 202 def multiple_document_jobs_supported(self): 203 return ipp.MultipleDocumentJobsSupported(False) 204 205 206 ###################################################################### 207 ### IPP Operations ### 208 ###################################################################### 209 210 def print_job(self): 211 pass 212 213 def validate_job(self): 214 pass 215 216 def get_jobs(self, requesting_user_name="", which_jobs=None): 217 # Filter by the which-jobs attribute 218 if which_jobs is None: 219 jobs = self.jobs.values() 220 elif which_jobs == "completed": 221 jobs = [self.jobs[job_id] for job_id in self.finished_jobs] 222 elif which_jobs == "not-completed": 223 jobs = [self.jobs[job_id] for job_id in self.active_jobs] 224 else: 225 raise ipp.errors.ClientErrorAttributes( 226 which_jobs, ipp.WhichJobs(which_jobs)) 227 228 # Filter by username 229 if requesting_user_name is None: 230 user_jobs = jobs 231 else: 232 user_jobs = [job for job in jobs if job.creator == requesting_user_name] 233 234 return user_jobs 235 236 def print_uri(self): 237 pass 238 239 def create_job(self, requesting_user_name="", job_name="", job_k_octets=0): 240 job_id = self._next_jobid 241 self._next_jobid += 1 242 243 job = Job(job_id, 244 self, 245 creator=requesting_user_name, 246 name=job_name, 247 size=job_k_octets) 248 249 self.jobs[job_id] = job 250 self.active_jobs.append(job_id) 251 self.state = States.PROCESSING 252 253 return job 254 255 def pause_printer(self): 256 pass 257 258 def resume_printer(self): 259 pass 260 261 def get_printer_attributes(self, requested_attributes=None): 262 if requested_attributes is None: 263 requested = self.attributes 264 else: 265 requested = [a for a in self.attributes if a in requested_attributes] 266 267 _attributes = [attr.replace("-", "_") for attr in requested] 268 attributes = [getattr(self, attr) for attr in _attributes] 269 return attributes 270 271 def set_printer_attributes(self): 272 pass -
server/lib/gutenbach/server/requests.py
rffbe41d rb01b6d1 37 37 return response 38 38 39 def verify_attribute(attr, cls, length=1): 40 vals = [val.value for val in attr.values] 41 if attr != cls(*vals): 42 raise ipp.errors.ClientErrorBadRequest(str(attr)) 43 if length is not None and len(vals) != length: 44 raise ipp.errors.ClientErrorBadRequest(str(attr)) 45 return vals 46 39 47 class GutenbachRequestHandler(object): 40 48 … … 56 64 # check charset 57 65 charset_attr = operation.attributes[0] 58 expected = ipp.AttributesCharset(charset_attr.values[0].value) 59 if charset_attr != expected: 60 raise ipp.errors.ClientErrorBadRequest(str(charset_attr)) 61 if charset_attr.values[0].value != 'utf-8': 66 charset = verify_attribute(charset_attr, ipp.AttributesCharset)[0] 67 if charset != 'utf-8': 62 68 raise ipp.errors.ClientErrorAttributes(str(charset_attr)) 63 69 64 70 # check for attributes-natural-language 65 71 natlang_attr = operation.attributes[1] 66 expected = ipp.AttributesNaturalLanguage(natlang_attr.values[0].value) 67 if natlang_attr != expected: 68 raise ipp.errors.ClientErrorBadRequest(str(natlang_attr)) 69 if natlang_attr.values[0].value != 'en-us': 72 natlang = verify_attribute(natlang_attr, ipp.AttributesNaturalLanguage)[0] 73 if natlang != 'en-us': 70 74 raise ipp.errors.ClientErrorAttributes(str(natlang_attr)) 71 75 … … 213 217 operation = request.attribute_groups[0] 214 218 219 # initialize operation attribute variables 220 printer_name = None 221 user = None 222 limit = None 223 attributes = None 224 which_jobs = None 225 my_jobs = None 226 215 227 # requested printer uri 216 228 if 'printer-uri' not in operation: 217 229 raise ipp.errors.ClientErrorBadRequest("Missing 'printer-uri' attribute") 218 uri_attr = operation['printer-uri'] 219 printer_name = uri_attr.values[0].value.split("/")[-1] 220 if uri_attr != ipp.PrinterUri(uri_attr.values[0].value): 221 raise ipp.errors.ClientErrorBadRequest(str(uri_attr)) 222 if printer_name != self.printer.name: 223 raise ipp.errors.ClientErrorAttributes(str(uri_attr), uri_attr) 224 230 printer_uri = verify_attribute(operation['printer-uri'], ipp.PrinterUri)[0] 231 if printer_uri not in self.printer.uris: 232 raise ipp.errors.ClientErrorAttributes( 233 str(operation['printer-uri']), operation['printer-uri']) 234 235 # optional attributes 236 if 'limit' in operation: 237 limit = verify_attribute( 238 operation['limit'], ipp.Limit)[0] 239 240 if 'requested-attributes' in operation: 241 attributes = verify_attribute( 242 operation['requested-attributes'], ipp.RequestedAttributes, length=None) 243 244 if 'which-jobs' in operation: 245 which_jobs = verify_attribute( 246 operation['which-jobs'], ipp.WhichJobs)[0] 247 248 if 'my-jobs' in operation: 249 my_jobs = verify_attribute( 250 operation['my-jobs'], ipp.MyJobs)[0] 251 252 if 'requesting-user-name' in operation: 253 user = verify_attribute( 254 operation['requesting-user-name'], ipp.RequestingUserName)[0] 255 # ignore if we're not filtering jobs by user 256 if not my_jobs: 257 user = None 258 225 259 # get the job attributes and add them to the response 226 for job in self.printer.get_jobs(): 227 attrs = job.get_job_attributes(operation) 260 jobs = self.printer.get_jobs( 261 which_jobs=which_jobs, 262 requesting_user_name=user) 263 for job in jobs: 264 attrs = job.get_job_attributes(requested_attributes=attributes) 228 265 response.attribute_groups.append(ipp.AttributeGroup( 229 266 ipp.AttributeTags.JOB, attrs)) … … 283 320 operation = request.attribute_groups[0] 284 321 322 printer_uri = None 323 requesting_user_name = None 324 job_name = None 325 ipp_attribute_fidelity=None 326 job_k_octets = None 327 285 328 # requested printer uri 286 329 if 'printer-uri' not in operation: 287 330 raise ipp.errors.ClientErrorBadRequest("Missing 'printer-uri' attribute") 288 uri_attr = operation['printer-uri'] 289 printer_name = uri_attr.values[0].value.split("/")[-1] 290 if uri_attr != ipp.PrinterUri(uri_attr.values[0].value): 291 raise ipp.errors.ClientErrorBadRequest(str(uri_attr)) 292 if printer_name != self.printer.name: 293 raise ipp.errors.ClientErrorAttributes(str(uri_attr), uri_attr) 331 printer_uri = verify_attribute(operation['printer-uri'], ipp.PrinterUri)[0] 332 if printer_uri not in self.printer.uris: 333 raise ipp.errors.ClientErrorAttributes( 334 str(operation['printer-uri']), operation['printer-uri']) 335 336 if 'requesting-user-name' in operation: 337 user_name = verify_attribute( 338 operation['requesting-user-name'], ipp.RequestingUserName)[0] 339 340 if 'job-name' in operation: 341 job_name = verify_attribute( 342 operation['job-name'], ipp.JobName)[0] 343 344 if 'job-k-octets' in operation: 345 job_k_octets = verify_attribute( 346 operation['job-k-octets'], ipp.JobKOctets)[0] 347 348 if 'ipp-attribute-fidelity' in operation: 349 pass # don't care 350 if 'job-impressions' in operation: 351 pass # don't care 352 if 'job-media-sheets' in operation: 353 pass # don't care 294 354 295 355 # get attributes from the printer and add to response 296 job = self.printer.create_job(request) 356 job = self.printer.create_job( 357 requesting_user_name=requesting_user_name, 358 job_name=job_name, 359 job_k_octets=job_k_octets) 297 360 response.attribute_groups.append(ipp.AttributeGroup( 298 ipp.AttributeTags.JOB, job.get_job_attributes( operation)))361 ipp.AttributeTags.JOB, job.get_job_attributes())) 299 362 300 363 @handler_for(ipp.OperationCodes.PAUSE_PRINTER) … … 345 408 operation = request.attribute_groups[0] 346 409 410 printer_uri = None 411 requesting_user_name = None 412 requested_attributes = None 413 document_format = None 414 347 415 # requested printer uri 348 416 if 'printer-uri' not in operation: 349 417 raise ipp.errors.ClientErrorBadRequest("Missing 'printer-uri' attribute") 350 uri_attr = operation['printer-uri'] 351 printer_name = uri_attr.values[0].value.split("/")[-1] 352 if uri_attr != ipp.PrinterUri(uri_attr.values[0].value): 353 raise ipp.errors.ClientErrorBadRequest(str(uri_attr)) 354 if printer_name != self.printer.name: 355 raise ipp.errors.ClientErrorAttributes(str(uri_attr), uri_attr) 356 printer = self.printer 418 printer_uri = verify_attribute(operation['printer-uri'], ipp.PrinterUri)[0] 419 if printer_uri not in self.printer.uris: 420 raise ipp.errors.ClientErrorAttributes( 421 str(operation['printer-uri']), operation['printer-uri']) 422 423 # optional attributes 424 if 'requesting-user-name' in operation: 425 user_name = verify_attribute( 426 operation['requesting-user-name'], ipp.RequestingUserName)[0] 427 428 if 'requested-attributes' in operation: 429 requested_attributes = verify_attribute( 430 operation['requested-attributes'], ipp.RequestedAttributes, length=None) 431 432 if 'document-format' in operation: 433 pass # XXX: todo 357 434 358 435 # get attributes from the printer and add to response 359 436 response.attribute_groups.append(ipp.AttributeGroup( 360 ipp.AttributeTags.PRINTER, printer.get_printer_attributes(operation))) 437 ipp.AttributeTags.PRINTER, 438 self.printer.get_printer_attributes( 439 requested_attributes=requested_attributes))) 361 440 362 441 @handler_for(ipp.OperationCodes.SET_PRINTER_ATTRIBUTES) … … 372 451 @handler_for(ipp.OperationCodes.SEND_DOCUMENT) 373 452 def send_document(self, request, response): 453 """3.3.1 Send-Document Operation 454 455 This OPTIONAL operation allows a client to create a 456 multi-document Job object that is initially 'empty' (contains 457 no documents). In the Create-Job response, the Printer object 458 returns the Job object's URI (the 'job-uri' attribute) and the 459 Job object's 32-bit identifier (the 'job-id' attribute). For 460 each new document that the client desires to add, the client 461 uses a Send-Document operation. Each Send- Document Request 462 contains the entire stream of document data for one document. 463 464 If the Printer supports this operation but does not support 465 multiple documents per job, the Printer MUST reject subsequent 466 Send-Document operations supplied with data and return the 467 'server-error-multiple- document-jobs-not-supported'. However, 468 the Printer MUST accept the first document with a 'true' or 469 'false' value for the 'last-document' operation attribute (see 470 below), so that clients MAY always submit one document jobs 471 with a 'false' value for 'last-document' in the first 472 Send-Document and a 'true' for 'last-document' in the second 473 Send-Document (with no data). 474 475 Since the Create-Job and the send operations (Send-Document or 476 Send- URI operations) that follow could occur over an 477 arbitrarily long period of time for a particular job, a client 478 MUST send another send operation within an IPP Printer defined 479 minimum time interval after the receipt of the previous 480 request for the job. If a Printer object supports the 481 Create-Job and Send-Document operations, the Printer object 482 MUST support the 'multiple-operation-time-out' attribute (see 483 section 4.4.31). This attribute indicates the minimum number 484 of seconds the Printer object will wait for the next send 485 operation before taking some recovery action. 486 487 An IPP object MUST recover from an errant client that does not 488 supply a send operation, sometime after the minimum time 489 interval specified by the Printer object's 490 'multiple-operation-time-out' attribute. 491 492 Access Rights: The authenticated user (see section 8.3) 493 performing this operation must either be the job owner (as 494 determined in the Create-Job operation) or an operator or 495 administrator of the Printer object (see Sections 1 and 496 8.5). Otherwise, the IPP object MUST reject the operation and 497 return: 'client-error-forbidden', 'client- 498 error-not-authenticated', or 'client-error-not-authorized' as 499 appropriate. 500 501 Request 502 ------- 503 504 Group 1: Operation Attributes 505 REQUIRED 'attributes-charset' 506 REQUIRED 'attributes-natural-language' 507 REQUIRED 'job-id' (uri) 508 OPTIONAL 'printer-uri' (uri) 509 OPTIONAL 'requesting-user-name' (name(MAX)) 510 OPTIONAL 'document-name' (name(MAX)) 511 OPTIONAL 'compression' (type3 keyword) 512 OPTIONAL 'document-format' (mimeMediaType) 513 OPTIONAL 'document-natural-language' (naturalLanguage) 514 OPTIONAL 'last-document' (boolean) 515 Group 2: Document Content 516 517 Response 518 -------- 519 520 Group 1: Operation Attributes 521 OPTIONAL 'status-message' (text(255)) 522 OPTIONAL 'detailed-status-message' (text(MAX)) 523 REQUIRED 'attributes-charset' 524 REQUIRED 'attributes-natural-language' 525 Group 2: Unsupported Attributes 526 Group 3: Job Object Attributes 527 REQUIRED 'job-uri' (uri) 528 REQUIRED 'job-id' (integer(1:MAX)) 529 REQUIRED 'job-state' (type1 enum) 530 REQUIRED 'job-state-reasons' (1setOf type2 keyword) 531 OPTIONAL 'job-state-message' (text(MAX)) 532 OPTIONAL 'number-of-intervening-jobs' (integer(0:MAX)) 533 534 """ 535 374 536 operation = request.attribute_groups[0] 375 537 376 # requested printer uri377 if 'printer-uri' in operation:378 uri_attr = operation['printer-uri']379 printer_name = uri_attr.values[0].value.split("/")[-1]380 if uri_attr != ipp.PrinterUri(uri_attr.values[0].value):381 raise ipp.errors.ClientErrorBadRequest(str(uri_attr))382 if printer_name != self.printer.name:383 raise ipp.errors.ClientErrorAttributes(str(uri_attr), uri_attr)384 printer = self.printer 385 538 job_id = None 539 printer_uri = None 540 requesting_user_name = None 541 document_name = None 542 compression = None 543 document_format = None 544 document_natural_language = None 545 last_document = None 546 547 # required attributes 386 548 if 'job-id' not in operation: 387 549 raise ipp.errors.ClientErrorBadRequest("Missing 'job-id' attribute") 388 job_id_attr = operation['job-id'] 389 job_id = job_id_attr.values[0].value 390 if job_id_attr != ipp.JobId(job_id_attr.values[0].value): 391 raise ipp.errors.ClientErrorBadRequest(str(job_id_attr)) 392 if job_id not in printer.jobs: 393 raise ipp.errors.ClientErrorAttributes(str(job_id_attr)) 394 job = printer.jobs[job_id] 550 job_id = verify_attribute(operation['job-id'], ipp.JobId)[0] 395 551 396 552 if 'last-document' not in operation: 397 553 raise ipp.errors.ClientErrorBadRequest("Missing 'last-document' attribute") 398 last_attr = operation['last-document'] 399 last = last_attr.values[0].value 400 if last_attr != ipp.LastDocument(last): 401 raise ipp.errors.ClientErrorBadRequest(str(last_attr)) 402 if not last: 554 last_document = verify_attribute(operation['last-document'], ipp.LastDocument)[0] 555 if not last_document: 403 556 raise ipp.errors.ServerErrorMultipleJobsNotSupported 404 557 405 printer.send_document(job_id, request.data) 406 attrs = job.get_job_attributes() 558 # optional attributes 559 if 'printer-uri' in operation: 560 printer_uri = verify_attribute(operation['printer-uri'], ipp.PrinterUri)[0] 561 if printer_uri not in self.printer.uris: 562 raise ipp.errors.ClientErrorAttributes( 563 str(operation['printer-uri']), operation['printer-uri']) 564 565 if 'requesting-user-name' in operation: 566 user_name = verify_attribute( 567 operation['requesting-user-name'], ipp.RequestingUserName)[0] 568 569 if 'document-name' in operation: 570 document_name = verify_attribute( 571 operation['document-name'], ipp.DocumentName)[0] 572 573 if 'compression' in operation: 574 compression = verify_attribute( 575 operation['compression'], ipp.Compression)[0] 576 577 if 'document-format' in operation: 578 document_format = verify_attribute( 579 operation['document-format'], ipp.DocumentFormat)[0] 580 581 if 'document-natural-language' in operation: 582 document_natural_language = verify_attribute( 583 operation['document_natural_language'], 584 ipp.DocumentNaturalLanguage)[0] 585 586 job = self.printer.get_job(job_id) 587 job.send_document( 588 request.data, 589 requesting_user_name=user_name, 590 document_name=document_name, 591 compression=compression, 592 document_format=document_format, 593 document_natural_language=document_natural_language, 594 last_document=last_document) 595 407 596 response.attribute_groups.append(ipp.AttributeGroup( 408 ipp.AttributeTags.JOB, attrs))597 ipp.AttributeTags.JOB, job.get_job_attributes())) 409 598 410 599 @handler_for(ipp.OperationCodes.SEND_URI) … … 414 603 @handler_for(ipp.OperationCodes.GET_JOB_ATTRIBUTES) 415 604 def get_job_attributes(self, request, response): 605 """3.3.4 Get-Job-Attributes Operation 606 607 This REQUIRED operation allows a client to request the values 608 of attributes of a Job object and it is almost identical to 609 the Get- Printer-Attributes operation (see section 3.2.5). The 610 only differences are that the operation is directed at a Job 611 object rather than a Printer object, there is no 612 'document-format' operation attribute used when querying a Job 613 object, and the returned attribute group is a set of Job 614 object attributes rather than a set of Printer object 615 attributes. 616 617 For Jobs, the possible names of attribute groups are: 618 - 'job-template': the subset of the Job Template attributes 619 that apply to a Job object (the first column of the table 620 in Section 4.2) that the implementation supports for Job 621 objects. 622 - 'job-description': the subset of the Job Description 623 attributes specified in Section 4.3 that the 624 implementation supports for Job objects. 625 - 'all': the special group 'all' that includes all 626 attributes that the implementation supports for Job 627 objects. 628 629 Since a client MAY request specific attributes or named 630 groups, there is a potential that there is some overlap. For 631 example, if a client requests, 'job-name' and 632 'job-description', the client is actually requesting the 633 'job-name' attribute once by naming it explicitly, and once by 634 inclusion in the 'job-description' group. In such cases, the 635 Printer object NEED NOT return the attribute only once in the 636 response even if it is requested multiple times. The client 637 SHOULD NOT request the same attribute in multiple ways. 638 639 It is NOT REQUIRED that a Job object support all attributes 640 belonging to a group (since some attributes are 641 OPTIONAL). However it is REQUIRED that each Job object support 642 all these group names. 643 644 Request 645 ------- 646 647 Group 1: Operation Attributes 648 REQUIRED 'attributes-charset' 649 REQUIRED 'attributes-natural-language' 650 REQUIRED 'job-id' (uri) 651 OPTIONAL 'printer-uri' (uri) 652 OPTIONAL 'requesting-user-name' (name(MAX)) 653 OPTIONAL 'requested-attributes' (1setOf keyword) 654 655 Response 656 -------- 657 658 Group 1: Operation Attributes 659 OPTIONAL 'status-message' (text(255)) 660 OPTIONAL 'detailed-status-message' (text(MAX)) 661 REQUIRED 'attributes-charset' 662 REQUIRED 'attributes-natural-language' 663 Group 2: Unsupported Attributes 664 Group 3: Job Object Attributes 665 666 """ 667 416 668 operation = request.attribute_groups[0] 417 669 418 # requested printer uri 419 if 'printer-uri' not in operation: 420 raise ipp.errors.ClientErrorBadRequest("Missing 'printer-uri' attribute") 421 uri_attr = operation['printer-uri'] 422 printer_name = uri_attr.values[0].value.split("/")[-1] 423 if uri_attr != ipp.PrinterUri(uri_attr.values[0].value): 424 raise ipp.errors.ClientErrorBadRequest(str(uri_attr)) 425 if printer_name != self.printer.name: 426 raise ipp.errors.ClientErrorAttributes(str(uri_attr), uri_attr) 427 printer = self.printer 428 670 job_id = None 671 printer_uri = None 672 requesting_user_name = None 673 requested_attributes = None 674 675 # required attributes 429 676 if 'job-id' not in operation: 430 677 raise ipp.errors.ClientErrorBadRequest("Missing 'job-id' attribute") 431 job_id_attr = operation['job-id'] 432 job_id = job_id_attr.values[0].value 433 if job_id_attr != ipp.JobId(job_id_attr.values[0].value): 434 raise ipp.errors.ClientErrorBadRequest(str(job_id_attr)) 435 if job_id not in printer.jobs: 436 raise ipp.errors.ClientErrorAttributes(str(job_id_attr)) 437 job = printer.get_job(job_id) 678 job_id = verify_attribute(operation['job-id'], ipp.JobId)[0] 679 680 # optional attributes 681 if 'printer-uri' in operation: 682 printer_uri = verify_attribute(operation['printer-uri'], ipp.PrinterUri)[0] 683 if printer_uri not in self.printer.uris: 684 raise ipp.errors.ClientErrorAttributes( 685 str(operation['printer-uri']), operation['printer-uri']) 686 687 # optional attributes 688 if 'requesting-user-name' in operation: 689 user_name = verify_attribute( 690 operation['requesting-user-name'], ipp.RequestingUserName)[0] 691 692 if 'requested-attributes' in operation: 693 requested_attributes = verify_attribute( 694 operation['requested-attributes'], ipp.RequestedAttributes, length=None) 438 695 439 696 # get the job attributes and add them to the response 440 attrs = job.get_job_attributes(operation) 697 job = self.printer.get_job(job_id) 698 attrs = job.get_job_attributes(requested_attributes=requested_attributes) 441 699 response.attribute_groups.append(ipp.AttributeGroup( 442 700 ipp.AttributeTags.JOB, attrs)) … … 487 745 488 746 operation = request.attribute_groups[0] 489 printer = self.printer 747 requested_attributes = None 748 749 if 'requested-attributes' in operation: 750 requested_attributes = verify_attribute( 751 operation['requested-attributes'], ipp.RequestedAttributes, length=None) 490 752 491 753 # get attributes from the printer and add to response 754 attrs = self.printer.get_printer_attributes( 755 requested_attributes=requested_attributes) 492 756 response.attribute_groups.append(ipp.AttributeGroup( 493 ipp.AttributeTags.PRINTER, printer.get_printer_attributes(operation)))757 ipp.AttributeTags.PRINTER, attrs)) 494 758 495 759 @handler_for(ipp.OperationCodes.CUPS_GET_PRINTERS) … … 504 768 """ 505 769 506 operation = request.attribute_groups[0]507 508 770 # get attributes from the printer and add to response 509 771 response.attribute_groups.append(ipp.AttributeGroup( 510 ipp.AttributeTags.PRINTER, self.printer.get_printer_attributes( operation)))772 ipp.AttributeTags.PRINTER, self.printer.get_printer_attributes())) 511 773 512 774 @handler_for(ipp.OperationCodes.CUPS_GET_CLASSES)
Note: See TracChangeset
for help on using the changeset viewer.