3
Z$x                 @   s   d dl Z d dlZd dlZd dlZd dlZd dlZd dlZddlmZ ddlm	Z	 d dl
mZ G dd dZdd	 Zd
d ZG dd dZG dd deZdd Zdd Zdd Zdd Zdd Zdd Zdd Zedkre  dS )    N   )_debugprint)config)reducec               @   s   e Zd ZddgZdd Zdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Zd/ddZd0ddZdd Zdd Zd d! Zd"d# Zd$d% Zd1d'd(Zd2d)d*Zd3d+d,Zd-d. ZdS )4Printeroptionslocalc             K   sX   || _ || _g | _t|dk}d}|rB| jf | | jr>d}nd}|rN| j  d| _dS )z
        @param name: printer name
        @type name: string
        @param connection: CUPS connection
        @type connection: CUPS.Connection object
        @param kw: printer attributes
        @type kw: dict indexed by string
        r   TFN)name
connectionclass_memberslenupdateis_classgetAttributes_ppd)selfr	   r
   kwZhave_kwZfetch_attrs r   9/usr/lib/python3/dist-packages/cupshelpers/cupshelpers.py__init__   s    	zPrinter.__init__c             C   s   | j d k	rtj| j  d S )N)r   osunlink)r   r   r   r   __del__9   s    
zPrinter.__del__c             C   s
   d| j  S )Nz<cupshelpers.Printer "%s">)r	   )r   r   r   r   __repr__=   s    zPrinter.__repr__c          	   C   sv   dd }d}t |}x\tjD ]R}|j|r|||d  }|| jkrFq|dkrRd}t| |t| jtt|@  qW d S )Nc             S   s   | j  S )N)lower)strr   r   r   _ascii_lowerB   s    z+Printer._expand_flags.<locals>._ascii_lowerZCUPS_PRINTER_classr   )	r   cups__dict__
startswith_flags_blacklistsetattrbooltypegetattr)r   r   prefixZprefix_lengthr	   Z	attr_namer   r   r   _expand_flags@   s    

  zPrinter._expand_flagsc             K   s   |j dd| _| jtjk| _|j dd| _|j dd| _|j dd| _|j dd| _|j d	d| _	|j d
d| _
|j dd| _t
| jtkr| jg| _| j  | jdkr| j | _| `|j dg | _t
| jtkr| jg| _| jj  || _dS )z
        Update object from printer attributes.

        @param kw: printer attributes
        @type kw: dict indexed by string
        zprinter-stater   z
device-uri zprinter-infozprinter-is-sharedNzprinter-locationzprinter-make-and-modelzprinter-typezprinter-uri-supportedzmember-names)getstater   ZIPP_PRINTER_STOPPEDenabledZ
device_uriinfoZ	is_sharedlocationmake_and_modelr$   uri_supportedlistr'   Z
not_sharedr   sortother_attributes)r   r   r   r   r   r   S   s(    




zPrinter.updatec             C   s  | j j| j}i | _i | _dddgfddddddgfd| _x|j D ]\}}|jd	r|d
td	  }|d krtqF|j	|d d
p| jj	|d
pd}t
|trtdd |}|| j|< |d |kr||d  }||f| j|< qF|jd rF|dkrF|dkrF|dkrF|jd rF|| j|< qFW |j	dd!\| _| _|j	ddg| _|j	dd| _|j	ddg| _|j	ddppd| _|j	ddg| _d| _g | _d|kr|d | _d| _nd|kr|d | _dj| j| _| jf | d
S )"z
        Fetch further attributes for the printer.

        Normally only a small set of attributes is fetched.  This
        method is for fetching more.
        FalseTruenoneZsinglezsingle-thickZdoublezdouble-thick)Z	landscapezpage-borderz-defaultN
job-sheetsprinter-error-policyprinter-op-policynotify-eventsdocument-formatnotify-lease-durationz
-supportedr(   c             S   s   | d | S )N,r   )xyr   r   r   <lambda>   s    z'Printer.getAttributes.<locals>.<lambda>zjob-sheets-defaultzrequesting-user-name-zjob-sheets-supportedzprinter-error-policy-supporteddefaultzprinter-op-policy-supportedTzrequesting-user-name-allowedFzrequesting-user-name-deniedz, )r6   r7   r8   r9   r:   r;   )r5   r5   )r
   ZgetPrinterAttributesr	   Z
attributesr2   Zpossible_attributesitemsendswithr   r)   
isinstancer0   r   r    Zjob_sheet_startZjob_sheet_endZjob_sheets_supportedZerror_policyZerror_policy_supportedZ	op_policyZop_policy_supportedZdefault_allowexcept_usersjoinZexcept_users_stringr   )r   attrskeyvaluer	   Z	supportedr   r   r   r   o   s`    

   





zPrinter.getAttributesc             C   sR   | j d jdsdS | j d dd }|jdd }|jdd }|dkrNd}|S )	zc
        Find out which server defines this printer.

        @returns: server URI or None
        r   zipp://N   /:zlocalhost.localdomainZ	localhost)r/   r    split)r   urir   r   r   	getServer   s    zPrinter.getServerc             C   s   d}| j dkrpy | jj| j| _ tj| j }W n@ tjk
rn } z"|j\}}|tjkr\d}n W Y dd}~X nX |dkr| j dk	rtj| j }|S )z
        Obtain the printer's PPD.

        @returns: cups.PPD object, or False for raw queues
        @raise cups.IPPError: IPP error
        NF)	r   r
   getPPDr	   r   ZPPDIPPErrorargsZIPP_NOT_FOUND)r   resultZemargsemr   r   r   rO      s    


zPrinter.getPPDc             C   sD   t |tr.tjtj}|dkr.t|j|d}| jj| j	|| dS )z
        Set a printer's option.

        @param name: option name
        @type name: string
        @param value: option value
        @type value: option-specific
        .N)
rC   floatlocalenl_langinfo	RADIXCHARr   replacer
   ZaddPrinterOptionDefaultr	   )r   r	   rH   Z	radixcharr   r   r   	setOption   s
    	
zPrinter.setOptionc             C   s   | j j| j| dS )zh
        Unset a printer's option.

        @param name: option name
        @type name: string
        N)r
   ZdeletePrinterOptionDefaultr	   )r   r	   r   r   r   unsetOption   s    zPrinter.unsetOptionNc             C   s>   |r| j j| j n&|r,| j j| j|d n| j j| j dS )z
        Set the printer's enabled state.

        @param on: whether it will be enabled
        @type on: bool
        @param reason: reason for this state
        @type reason: string
        )reasonN)r
   enablePrinterr	   ZdisablePrinter)r   onr]   r   r   r   
setEnabled   s
    	zPrinter.setEnabledc             C   s>   |r| j j| j n&|r,| j j| j|d n| j j| j dS )z
        Set the printer's accepting state.

        @param on: whether it will be accepting
        @type on: bool
        @param reason: reason for this state
        @type reason: string
        )r]   N)r
   
acceptJobsr	   Z
rejectJobs)r   r_   r]   r   r   r   setAccepting  s
    	zPrinter.setAcceptingc             C   s   | j j| j| dS )zy
        Set the printer's shared state.

        @param on: whether it will be accepting
        @type on: bool
        N)r
   ZsetPrinterSharedr	   )r   r_   r   r   r   	setShared  s    zPrinter.setSharedc             C   s   | j j| j| dS )zs
        Set the printer's error policy.

        @param policy: error policy
        @type policy: string
        N)r
   ZsetPrinterErrorPolicyr	   )r   policyr   r   r   setErrorPolicy  s    zPrinter.setErrorPolicyc             C   s   | j j| j| dS )z{
        Set the printer's operation policy.

        @param policy: operation policy
        @type policy: string
        N)r
   ZsetPrinterOpPolicyr	   )r   rd   r   r   r   setOperationPolicy'  s    zPrinter.setOperationPolicyc             C   s   | j j| j|| dS )z
        Set the printer's job sheets.

        @param start: start sheet
        @type start: string
        @param end: end sheet
        @type end: string
        N)r
   ZsetPrinterJobSheetsr	   )r   startendr   r   r   setJobSheets0  s    	zPrinter.setJobSheetsc             C   s   t |trX|j }dd |D }g }x|D ]}|j| q*W dd |D }dd |D }|rn| jj| j| n| jj| j| dS )z
        Set access control list.

        @param allow: whether to allow by default, otherwise deny
        @type allow: bool
        @param except_users: exception list
        @type except_users: string list
        c             S   s   g | ]}|j d qS )r<   )rL   ).0ur   r   r   
<listcomp>F  s    z%Printer.setAccess.<locals>.<listcomp>c             S   s   g | ]}|j  qS r   )strip)rj   rk   r   r   r   rl   J  s    c             S   s   g | ]}|r|qS r   r   )rj   Z_fr   r   r   rl   K  s    N)rC   r   rL   extendr
   ZsetPrinterUsersDeniedr	   ZsetPrinterUsersAllowed)r   ZallowrD   Zusersrk   r   r   r   	setAccess;  s    	

zPrinter.setAccessFc       	      C   s   g }y@ydddg}| j j|d}W n tk
r@   | j j }Y nX W n tjk
rZ   |S X x|j D ]\}}y"|d }||jdd d }W n   wfY nX || jkrqf| sd|krf|d dkrf|j| |dk	rft	||krfP qfW |S )	z
        Find out whether jobs are queued for this printer.

        @param only_tests: whether to restrict search to test pages
        @type only_tests: bool
        @returns: list of job IDs
        zjob-idzjob-printer-urizjob-name)requested_attributesrJ   r   Nz	Test Page)
r
   getJobs	TypeErrorr   rP   rA   rindexr	   appendr   )	r   
only_testslimitretrjobsidrF   rM   r   r   r   
jobsQueuedR  s0    


zPrinter.jobsQueuedc             C   s   g }yFydddg}| j jd|d}W n" tk
rF   | j jdd}Y nX W n tjk
r`   |S X x|j D ]|\}}y"|d }||jdd d	 }W n   wlY nX || jkrql|jdtj	tj
k rql|j| |d	k	rlt||krlP qlW |S )
zo
        Find out whether there are preserved jobs for this printer.

        @return: list of job IDs
        zjob-idzjob-printer-uriz	job-stateZ	completed)
which_jobsrp   )r|   rJ   r   N)r
   rq   rr   r   rP   rA   rs   r	   r)   ZIPP_JOB_PENDINGZIPP_JOB_COMPLETEDrt   r   )r   rv   rw   rx   ry   rz   rF   rM   r   r   r   jobsPreservedw  s2    


zPrinter.jobsPreservedc             C   s   | j d|dS )zl
        Find out whether test jobs are queued for this printer.

        @returns: list of job IDs
        T)ru   rv   )r{   )r   rv   r   r   r   testsQueued  s    zPrinter.testsQueuedc       
       C   st  | j j| j tj R}yd}| j j||j d W nJ tjk
r } z,|j	\}|tj
tjgkrfdS tj|W Y dd}~X nX |jd dd |j D }d}d}xN|D ]F}|jdr|jd	d
 }	|	| jkrd|dd  ||< d}|d
7 }qW |rf|jd |jdd |D  |j  |j  |jd y| j j||j d W n tjk
rd   dS X |S Q R X dS )z9
        Set this printer as the system default.
        z/admin/conf/lpoptions)fdFNr   c             S   s   g | ]}|j d qS )zUTF-8)decode)rj   liner   r   r   rl     s    z(Printer.setAsDefault.<locals>.<listcomp>zDefault  r   zDest    Tc             S   s   g | ]}|j d qS )zUTF-8)encode)rj   r   r   r   r   rl     s    )r
   
setDefaultr	   tempfileZTemporaryFileZgetFilefilenor   Z	HTTPErrorrQ   ZHTTP_NOT_FOUNDZHTTP_AUTHORIZATION_CANCELEDseek	readlinesr    rL   
writelinestruncateflushZputFile)
r   fresourcerS   slinesZchangedir   r	   r   r   r   setAsDefault  s@    





zPrinter.setAsDefault)N)N)FN)N)N)__name__
__module____qualname__r!   r   r   r   r'   r   r   rN   rO   r[   r\   r`   rb   rc   re   rf   ri   ro   r{   r}   r~   r   r   r   r   r   r      s,   D	

			
%
#
r   c             C   s\   | j  }| j }xF|j D ]:\}}t|| f|}|||< ||kr|| |_|jj  qW |S )z
    Obtain a list of printers.

    @param connection: CUPS connection
    @type connection: CUPS.Connection object
    @returns: L{Printer} list
    )getPrintersZ
getClassesrA   r   r   r1   )r
   Zprintersclassesr	   Zprinterr   r   r   r     s    
r   c          	   C   s   i }| j d}x<|D ]4}|jddkr(q|j dd\}}|j ||j < qW d|krd|jd|d  d|kr||jd|d  d|kr|jd	|d  xdD ]}|j|d qW |d	 dkrg |d	< n|d	 j d|d	< |S )z
    Parse an IEEE 1284 Device ID, so that it may be indexed by field name.

    @param id: IEEE 1284 Device ID, without the two leading length bytes
    @type id: string
    @returns: dict indexed by field name
    ;rK   r   ZMANUFACTURERMFGZMODELMDLzCOMMAND SETCMDCLSDESSNSPJr(   r<   )	r   r   r   r   r   r   r   r   r   )rL   findrm   
setdefault)rz   id_dictpiecesZpiecer	   rH   r   r   r   parseDeviceID  s&    



r   c               @   s(   e Zd ZdZdd Zdd Zdd ZdS )	Devicez.
    This class represents a CUPS device.
    c             K   s   || _ |jdd| _|jdd| _|jdd| _|jdd| _|jdd| _|jd}|d | _t	|d	k| _
t| j| _|jd
}|dkr| jjdd r||d d | jd< dS )z~
        @param uri: device URI
        @type uri: string
        @param kw: device attributes
        @type kw: dict
        zdevice-classr(   zdevice-infozdevice-make-and-modelz	device-idzdevice-locationrK   r   r   zserial=r      Nr   )rM   r)   Zdevice_classr,   r.   rz   r-   rL   r$   r   r   r   r   r   )r   rM   r   Z
uri_piecesr   r   r   r   r     s    


zDevice.__init__c             C   s
   d| j  S )Nz<cupshelpers.Device "%s">)rM   )r   r   r   r   r     s    zDevice.__repr__c             C   s  |dkrdS | j |j kr&|j r"dS dS | j}|dkrt| jjddkrJd}n*| jjddkr`d	}n| jjd
dkrtd}|dkr| jj jddkrd}|j}|dkr|jjddkrd}n*|jjddkrd	}n|jjd
dkrd}|dkr|jj jddkrd}| j  r||kr|dkr(dS |dkr6dS |dkrDdS |dkrRdS |dkr`dS |dkrndS |dkr|dS |dkrdS |dkrdS |dkrdS |dkrdS |dkrdS |dkrdS |dkrdS |d	krdS |d	krdS |dkrdS |dkrdS |dkr$dS |dkr2dS |dkr@dS |dkrNdS |dkr\dS |dkrjdS |dkrxdS |dkrdS t| jt|jk }|s| j|jk }|S )z9
        Compare devices by order of preference.
        NTFZdnssdz._ippr   Zdnssdiz._pdl-datastreamZdnssdsz	._printerZdnssdlZusbZfaxZusbfaxserialZparallelZhpZhpfaxZippsZippZsocketZlpdr   r   r   r   r   r   r   r   )r   r$   rM   r   r   r#   rz   r,   )r   otherstypeZotyperR   r   r   r   __lt__!  s    


























zDevice.__lt__N)r   r   r   __doc__r   r   r   r   r   r   r   r     s   r   c               @   s   e Zd Zdd Zdd ZdS )_GetDevicesCallc             C   sH   d|kr*|j d| _| j|d< |jf |S d | _|jf |}| j||S )NZreply_handler)r)   _client_reply_handler_reply_handler
getDevices)r   r
   kwdsrR   r   r   r   call  s    
z_GetDevicesCall.callc             C   sb   xD|j  D ]8\}}t|f|}|||< |jdkr
|jdkr
|j|_q
W | jrZ| j|| n|S d S )Nr(   )rA   r   r,   r.   r   )r   r
   ZdevicesrM   datadevicer   r   r   r     s    z_GetDevicesCall._reply_handlerN)r   r   r   r   r   r   r   r   r   r     s   
r   c             K   s   t  }|j| |S )z
    Obtain a list of available CUPS devices.

    @param connection: CUPS connection
    @type connection: cups.Connection object
    @returns: a list of L{Device} objects
    @raise cups.IPPError: IPP Error
    )r   r   )r
   r   opr   r   r   r     s    	r   c             C   s.   | j | | j| | j dkr*| j| dS )a  
    Set a new printer enabled, accepting jobs, and (if necessary) the
    default printer.

    @param connection: CUPS connection
    @type connection: cups.Connection object
    @param name: printer name
    @type name: string
    @raise cups.IPPError: IPP error
    N)r^   ra   Z
getDefaultr   )r
   r	   r   r   r   activateNewPrinter  s    

r   c                s    fdd  fdd}x|| D ]v}|j dkr2q"|j|j }|r"|j|jkr"|j}xB|jD ]8}|d |kr\|j|j | tdt|j t|f  q\W q"W dS )	z
    Copy default options between PPDs.

    @param ppd1: source PPD
    @type ppd1: cups.PPD object
    @param ppd2: destination PPD
    @type ppd2: cups.PPD object
    c                s0   | j d d  }x| jD ]}|j | qW |S )N)r   Z	subgroupsrn   )groupr   g)getPPDGroupOptionsr   r   r     s    z*copyPPDOptions.<locals>.getPPDGroupOptionsc             3   s,   x&| j D ]}x |D ]
}|V  qW qW d S )N)ZoptionGroups)ppdr   option)r   r   r   iteratePPDOptions  s    z)copyPPDOptions.<locals>.iteratePPDOptionsZ
PageRegionchoicezset %s = %sN)keywordZ
findOptionZuiZ	defchoicechoices
markOptionr   repr)Zppd1Zppd2r   r   Z
new_optionrH   r   r   )r   r   copyPPDOptions  s    	
r   c             C   s   d}ddddddg}x|D ]}||krd}qW ylt d	}xV|D ]N}|jd
rNq>|j j jdrfd}q>|j j jdr~d}q>|j dkr>P q>W |j  W n   Y nX y| jd| td|  W n   td|  Y nX dS )z
    Set the PPD page size according to locale.

    @param ppd: PPD
    @type ppd: cups.PPD object
    @param language: language, as given by the first element of
    locale.setlocale
    @type language: string
    ZA4CZPOSIXZenZen_USZen_CAZfr_CAZLetterz/etc/papersize#Za4letterr(   ZPageSizezset PageSize = %sz*Failed to set PageSize (%s not available?)N)openr    rm   r   closer   r   )r   Zlanguagesizer   Zeachr   r   r   r   r   setPPDPageSize  s0    


r   c                s:  ddd}g   fdd}d }}| j d}|r`|jjdd	}|jd
d}|jdd}|jdd}|jdd ks|jdd!krd	}|jd}x|D ]}|j jd}	x|	D ]}
|
j jd}|d }||}|s|| qtjj|dkrt	|}d}d}xT||k rP|| }|j
|rD|t	|d }||}|sB|| P |d7 } qW qW |sP qW |sn| r6tjdd\}}tj| | j| tj|dtj tj|d}d}x|D ]z}|j
|r|t	|d j jd}y|jd\}}}W n   wY nX ||tjd }|s|tjd |  qW  S )"z
    Check that all relevant executables for a PPD are installed.

    @param ppd: PPD
    @type ppd: cups.PPD object
    @returns: string list, representing missing executables
    /usr/bin:/binc          (   S   s   | dkrdS | j d}|d3kr*| d | } t| dkr:dS | d dkrttj| tjrdtd|   | S td	|   d S | j d
d4krdS | d5krdS xJ|jdD ]<}|jtjj	tjj	 |  }tj|tjrtd|  |S qW td2| |f  d S )6N-Zbuiltin%r   r   truerJ   z	%s: foundz%s: NOT found=rK   rU   [aliasbindbreakcdcontinuedeclareechoelseevalexecexitexportfiifkillletr   popdprintfpushdpwdreadreadonlysetshiftshoptsourcetestthentrapr$   ulimitumaskunaliasunsetwaitz%s: NOT found in %sr   r   )'rK   rU   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r$   r   r   r   r   r   )
r   r   r   accessX_OKr   rL   rstrippathsep)r	   r   pZ	componentfiler   r   r   	pathcheck	  s<    
     z%missingExecutables.<locals>.pathcheckc                s,   | j d}|dkr| d | }  j|  d S )Nr   r   r   )r   rt   )exer   )exes_to_installr   r   add_missing/  s    
z'missingExecutables.<locals>.add_missingNZFoomaticRIPCommandLinez&&
r(   z&quot;"z&lt;<z&gt;>(r   &r   |r   r   Zgsz-sIjsServer=T)textZrtz*cupsFilter:z/filter:/usr/lib64/cups/filterz/filter/)r   r   r   )ZfindAttrrH   rZ   r   rL   rm   r   r   basenamer   r    r   Zmkstempr   ZwriteFdlseekSEEK_SETfdopenr   Zcupsserverbindir)r   r   r   r   ZexepathattrZcmdlineZpipespipeZcmdscmdrQ   ZargnZargisearchargZtmpfdZtmpfnamer   r   ZmimetypeZcostr   )r   r   missingExecutables  sr    
$	







r  c             C   s   t | }g |fS )z
    Check that all relevant executables for a PPD are installed.

    @param ppd: PPD
    @type ppd: cups.PPD object
    @returns: string list pair, representing missing packages and
    missing executables
    )r  )r   Zexecutablesr   r   r   missingPackagesAndExecutables  s    	r  c              C   s0   t j } x"t| j D ]}t|j|j qW d S )N)r   Z
Connectionr   valuesprintrM   r   )cr   r   r   r   _main  s    r  __main__)r   pprintr   r   restringrW   r(   r   r   	functoolsr   r   r   r   r   objectr   r   r   r   r   r  r  r  r   r   r   r   r   <module>   s.   0   7  ( 