SafeQ Workstation Client Protocol Specification
Protocol Level 4
Generic
Protocol is message oriented. Client opens connection to server. Client sends request and server returns response.
Each request from client MUST contain prefix %%%SafeQ-.
Each request from client MUST be terminated by '\n'.
Request MAY continue on next line only in defined cases, like sending block of data with defined length.
All requests MUST be encoded in UTF-8.
Request header is CASE INSENSITIVE. E.g. %%%SafeQ-Get-SomethingFancy equals to %%%safeq-get-somethingfancy, but it is recommended to use CammelCase syntax which you can see in this document.
Extra spaces in value part of request are NOT ignored and they're considered as part of value. E.g.: '%%%SafeQ-Something: hello \n' will produce value ' hello '
Communication
Client MUST initiate communication with following header:
%%%SafeQ-Check:\nServer just ignore this message and it keeps connection alive. This command serves client to determine which server is available for printing.
Client MUST send following request to initiate communication by protocol level 4.
%%%SafeQ-ProtocolLevel:4\nThis is necessary, because it allows SafeQ to determine proper processor for protocol.
Client MAY request encrypted communication - see section Encryption.
Client MAY send information about its version:
%%%SafeQ-Version:Windows 2.0\nClient MAY send information that communication will be compressed in ZIP:
%%%SafeQ-Compression:ZIP\nClient MUST send data in chunks. Each chunk must begin with header:
%%%SafeQ-Data:<length in bytes>\nThen client MUST send amount of data declared in header.
Client MUST send length 0 when it finishes sending data:
%%%SafeQ-Data:0\nClient MAY send information about job (only in case job parsing is enabled):
%%%SafeQ-JobInfo:<number of pages> [info about page 1] [info about page 2] ...\nWhere information about each page is in the following format:
<Page Number>|<Number of copies>|<Duplex>|<Paper size>|<DPI>|<Width in pixels>x<Height in pixels>|<Color information availability>[|<Color/Mono>]Getting values from server
Client MAY ask server for specific values with Get request. Where <VARIABLE> is replaced by name of variable
%%%SafeQ-Get-<VARIABLE>:\nWhen server does not support requested value it MUST send:
%%%SafeQ-Unknown:\nWhen server supports value it MUST send reponse with:
%%%SafeQ-<VARIABLE>:<VALUE>\nSupported Get-* requests
Retrieve job status - request:
%%%SafeQ-Get-JobStatus:\nResponse:
%%%SafeQ-JobStatus:[OK|Abort]\nRetrieve job size - request:
%%%SafeQ-Get-JobSize:\nResponse:
%%%SafeQ-JobSize:<SIZE>\nRetrieve link for browser - request:
%%%SafeQ-Get-BrowserLink:\nResponse:
%%%SafeQ-BrowserLink:<LINK-URL_ENCODED>\nNote: Size of browser window should be determined on client side from the HTML element body.
Retrieve permission for job parsing on client side:
%%%SafeQ-Get-JobParsing:\nResponse in case client is allowed to parse job:
%%%SafeQ-JobParsing:1\nRequest for license feature:
%%%SafeQ-Get-License:[Compression|Encryption]\nResponse:
%%%SafeQ-License:[Enabled|Disabled]\nRequest for graceful disconnect:
%%%SafeQ-Get-ConnectionClose:\nResponse:
%%%SafeQ-ConnectionClose:OK\nEncryption
Client MAY request encryption - via TLS - STARTTLS. (Further info about STARTTLS - http://en.wikipedia.org/wiki/STARTTLS)
%%%SafeQ-Get-Encryption:TLS\nServer MUST respond:
in case of success %%%SafeQ-Encryption:OK\n
in case of failure %%%SafeQ-Encryption:FAILED\n
After acknowledging encryption from server side client MUST initiate TLS handshake.
Authentication
It is possible to authenticate user. The Client MUST send at least one of the following headers:
%%%SafeQ-Login:<LOGIN>\n%%%SafeQ-Password:<PASSWORD>\n%%%SafeQ-Card:<CARD>\nClient MUST send request for verification of above user credentials:
%%%SafeQ-Get-Authentication:<METHOD>\nMethods: LOGIN, PASSWORD, CARD
Server MUST respond:
in case of success %%%SafeQ-Authentication:OK\n
in case of failure %%%SafeQ-Authentication:FAILED\n
in case of email duplicity %%%SafeQ-Authentication:FAILED DUPLICATE EMAIL\n
If CARD is used, SafeQ server (CML/ORS) does not convert the card numbers received in any way before searching for them in the database/cache.
Trusted client
The simplest way how to authenticate user is to send his SafeQ login in header.
%%%SafeQ-For:<LOGIN>\nQueue specification
Client MAY specify printing queue (e.g.: Secure):
%%%SafeQ-LP:<QUEUE-NAME>\nTags
It is possible to set tags to job by sending following command.
It is possible to add user tag to queue name. Add tag name after queue name, delimiter is semicolon:
%%%SafeQ-LP:<QUEUE-NAME>:<TAG-NAME>\nYou can specify more tags, delimiter is comma. Do not add any extra spaces:
%%%SafeQ-LP:<QUEUE-NAME>:<TAG-NAME>,<TAG-NAME>,<TAG-NAME>\nTags are case sensitive.
Document
It is possible to set further information to document by following headers.
Set document title:
%%%SafeQ-Title:<TITLE>\nSet note to document. Note MUST not contain EOL:
%%%SafeQ-Note:<TEXT>\nSet name of sender's machine to the job:
%%%Safeq-MachineName:<TEXT>\nIn case job is cancelled by user (job may be incomplete), the following header is sent (before end of job data header - %%%SafeQ-Data:0\n):
%%%SafeQ-JobStatus:Cancelled\nClient MUST NOT send any further SafeQ-Data block with non-zero size of data block. If such a block occurs then server terminates connection because of protocol violation.
Finishing options
It is possible to set finishing options by sending following commands before sending last block of data.
Set number of copies:
%%%SafeQ-Finishing-Copies:<NUMBER>\nSet job as duplex:
%%%SafeQ-Finishing-Duplex:<DUPLEX-VALUE>\nWhere <DUPLEX-VALUE> is one of: None, ShortEdge, LongEdge
Set job as black and white:
%%%SafeQ-Finishing-BW:<BOOLEAN>\nSet job to use stapler:
%%%SafeQ-Finishing-Stapler:<BOOLEAN>\nValues
STRING - any string, it must not contain \n character
NUMBER - long number in Java, not float
BOOLEAN - true or false
Examples
It is possible to send job from command line. You can use netcat tool. Just store data into file in Unix format (\n as line delimiter).
Netcat command:
nc localhost 9100 < job-file.txtNetcat with timeout 2 seconds (Win):
nc \-w 2 localhost 9100 < job-file.txtSimple job with "testuser" account
%%%SafeQ-Check:%%%SafeQ-ProtocolLevel:4%%%SafeQ-For:testuser%%%SafeQ-Title:Test Page%%%SafeQ-Version:Windows 2.0%%%SafeQ-Note:Note%%%SafeQ-Domain:YSOFT%%%SafeQ-MachineName:PC054%%%SafeQ-Get-BrowserLink:%%%SafeQ-JobID:2%%%SafeQ-Data:3abc%%%SafeQ-Data:0Some comments on .NET implementation
The protocol works wit sessions, one session = one TCP connection. The best way to send
// all commands of the session encoded in UTF-8byte [][] commands;// The memory stream capacity must be exactly the total size of input buffers (no trailing '\0' characters)using (var stream = new MemoryStream(commands.Select(c => c.Length).Sum())){foreach (var cmd in commands){stream.Write(cmd);}}// Everything must be inside one TCP connectionvar connection = new TcpClient(address, port).GetStream();var buffer = stream.GetBuffer();connection.Write(buffer, 0, buffer.Length);connection.Close();Protocol Level 3 and older
YSoft SafeQ is able to receive data using TCP data stream. This stream, sent by YSoft SafeQ Client, contains some text fields (metadata), followed by raw print job data. Here is an example of data stream including most frequently used metadata:
%%%SmartQ-CodePage: codepage%%%SmartQ-For: username%%%SmartQ-Title: title%%%SmartQ-LP: queue%%%SmartQ-Sec: secureid%%%SmartQ-Domain: domain%%%SmartQ-JobID: jobid%%%SmartQ-Zip: zip<raw print job data>Legend:
codepage: encoding mode for subsequent text fields - value "65001" means UTF-8.
username: login name of the user.
queue: queue on YSoft SafeQ server, where job will be stored (note: queue must match queue on YSoft SafeQ).
title: print job title.
secureid: unique security identifier obtained by user authentication (replaces username).
domain: specifies domain of workstation, which is sending the print job to SafeQ.
jobid: local job identifier.
zip: indicates that following print job data is compressed.