66using Microsoft . Extensions . Options ;
77using SharpIpp . Exceptions ;
88using SharpIppNextServer . Models ;
9+ using System . Text ;
910
1011namespace SharpIppNextServer . Services ;
1112
@@ -35,7 +36,7 @@ public async Task ProcessRequestAsync(Stream inputStream, Stream outputStream)
3536 IIppResponseMessage response = await GetResponseAsync ( request ) ;
3637 IIppResponseMessage rawResponse = await sharpIppServer . CreateRawResponseAsync ( response ) ;
3738 ImproveRawResponse ( request , rawResponse ) ;
38- await sharpIppServer . SendRawResponseAsync ( response , outputStream ) ;
39+ await sharpIppServer . SendRawResponseAsync ( rawResponse , outputStream ) ;
3940 }
4041 catch ( IppRequestException ex )
4142 {
@@ -97,22 +98,24 @@ private void ImproveRawResponse(IIppRequest request, IIppResponseMessage rawResp
9798
9899 private void ImproveGetPrinterAttributesRawResponse ( GetPrinterAttributesRequest request , IIppResponseMessage rawResponse )
99100 {
100- if ( request . OperationAttributes is null
101- || request . OperationAttributes . RequestedAttributes is null || request . OperationAttributes . RequestedAttributes . Length == 0
102- || request . OperationAttributes . RequestedAttributes . All ( x => x == string . Empty )
103- || request . OperationAttributes . RequestedAttributes . Any ( x => x == "all" ) )
104- return ;
105101 var section = rawResponse . Sections . FirstOrDefault ( x => x . Tag == SectionTag . PrinterAttributesTag ) ;
106102 if ( section is null )
107103 return ;
108- foreach ( var attributeName in request . OperationAttributes . RequestedAttributes . Where ( x => ! string . IsNullOrEmpty ( x ) ) )
109- {
110- var attribute = section . Attributes . FirstOrDefault ( x => x . Name == attributeName ) ;
111- if ( attribute is not null )
112- continue ;
113- section . Attributes . Add ( new IppAttribute ( Tag . NoValue , attributeName , NoValue . Instance ) ) ;
114- logger . LogDebug ( "{name} attribute has been added with no value." , attributeName ) ;
115- }
104+ bool IsRequired ( string attributeName ) => ! section . Attributes . Any ( x => x . Name . Equals ( attributeName ) )
105+ && IsAttributeRequired ( request , attributeName ) ;
106+ var options = printerOptions . Value ;
107+ if ( IsRequired ( "printer-device-id" ) )
108+ section . Attributes . Add ( new IppAttribute ( Tag . TextWithoutLanguage , "printer-device-id" , GetPrinterDeviceId ( ) ) ) ;
109+ if ( IsRequired ( "printer-uuid" ) )
110+ section . Attributes . Add ( new IppAttribute ( Tag . Uri , "printer-uuid" , $ "urn:uuid:{ options . UUID } ") ) ;
111+ if ( IsRequired ( "printer-dns-sd-name" ) )
112+ section . Attributes . Add ( new IppAttribute ( Tag . NameWithoutLanguage , "printer-dns-sd-name" , options . DnsSdName ) ) ;
113+ if ( IsRequired ( "printer-make-and-model" ) )
114+ section . Attributes . Add ( new IppAttribute ( Tag . TextWithoutLanguage , "printer-make-and-model" , options . Name ) ) ;
115+ if ( IsRequired ( "printer-firmware-name" ) )
116+ section . Attributes . Add ( new IppAttribute ( Tag . NameWithoutLanguage , "printer-firmware-name" , options . FirmwareName ) ) ;
117+ if ( IsRequired ( "printer-firmware-string-version" ) )
118+ section . Attributes . Add ( new IppAttribute ( Tag . TextWithoutLanguage , "printer-firmware-string-version" , options . FirmwareName ) ) ;
116119 }
117120
118121 private ValidateJobResponse GetValidateJobResponse ( ValidateJobRequest request )
@@ -126,6 +129,22 @@ private ValidateJobResponse GetValidateJobResponse(ValidateJobRequest request)
126129 } ;
127130 }
128131
132+ private static string GetPrinterDeviceId ( )
133+ {
134+ return new StringBuilder ( )
135+ . Append ( "MFG:danielklecha;" ) //Manufacturer
136+ . Append ( "MDL:SharpIppNext1;" ) //Model
137+ . Append ( "CMD:Automatic,JPEG;" ) //Command Set
138+ . Append ( "CLS:PRINTER" ) //Class
139+ . Append ( "DES:SIN1;" ) //Designator or Description
140+ . Append ( "CID:SharpIppNext_1;" ) //Compatible ID
141+ . Append ( "LEDMDIS:USB#FF#CC#00,USB#07#01#02,USB#FF#04#01;" ) //Legacy Device ID String
142+ . Append ( "SN:SIN279BJ23J07PX;" ) //Serial Number
143+ . Append ( "S:038000C480a00001002c240005ac1400032;" ) //Status
144+ . Append ( "Z:05000008000009,12000,17000000000000,181;" ) //Vendor-Specific
145+ . ToString ( ) ;
146+ }
147+
129148 private async Task < SendUriResponse > GetSendUriResponseAsync ( SendUriRequest request )
130149 {
131150 var response = new SendUriResponse
@@ -318,20 +337,21 @@ private async Task<HoldJobResponse> GetHoldJobResponseAsync(HoldJobRequest reque
318337 return response ;
319338 }
320339
340+ private static bool IsAttributeRequired ( GetPrinterAttributesRequest request , string attributeName )
341+ {
342+ return request . OperationAttributes is null
343+ || request . OperationAttributes . RequestedAttributes is null
344+ || request . OperationAttributes . RequestedAttributes . Length == 0
345+ || request . OperationAttributes . RequestedAttributes . All ( x => x == string . Empty )
346+ || request . OperationAttributes . RequestedAttributes . Any ( x => x . Equals ( "all" , StringComparison . InvariantCultureIgnoreCase ) )
347+ || request . OperationAttributes . RequestedAttributes . Contains ( attributeName ) ;
348+ }
349+
321350 private GetPrinterAttributesResponse GetGetPrinterAttributesResponse ( GetPrinterAttributesRequest request )
322351 {
323352 var options = printerOptions . Value ;
324353 var allAttributes = PrinterAttribute . GetAttributes ( request . Version ) . ToList ( ) ;
325- bool IsRequired ( string attributeName )
326- {
327- if ( request . OperationAttributes is null )
328- return true ;
329- if ( request . OperationAttributes . RequestedAttributes is null || request . OperationAttributes . RequestedAttributes . Length == 0 )
330- return true ;
331- if ( request . OperationAttributes . RequestedAttributes . All ( x => x == string . Empty ) )
332- return true ;
333- return request . OperationAttributes . RequestedAttributes . Contains ( attributeName ) ;
334- }
354+ bool IsRequired ( string attributeName ) => IsAttributeRequired ( request , attributeName ) ;
335355 logger . LogInformation ( "System returned printer attributes" ) ;
336356 return new GetPrinterAttributesResponse
337357 {
@@ -379,7 +399,7 @@ bool IsRequired(string attributeName)
379399 PrinterLocation = ! IsRequired ( PrinterAttribute . PrinterLocation ) ? null : "Internet" ,
380400 PrintScalingDefault = ! IsRequired ( PrinterAttribute . PrintScalingDefault ) ? null : options . PrintScaling . FirstOrDefault ( ) ,
381401 PrintScalingSupported = ! IsRequired ( PrinterAttribute . PrintScalingSupported ) ? null : options . PrintScaling ,
382- PrinterUriSupported = ! IsRequired ( PrinterAttribute . PrinterUriSupported ) ? null : [ GetPrinterUrl ( ) ] ,
402+ PrinterUriSupported = ! IsRequired ( PrinterAttribute . PrinterUriSupported ) ? null : [ GetPrinterUrl ( "/ipp/print" ) ] ,
383403 UriAuthenticationSupported = ! IsRequired ( PrinterAttribute . UriAuthenticationSupported ) ? null : [ UriAuthentication . None ] ,
384404 UriSecuritySupported = ! IsRequired ( PrinterAttribute . UriSecuritySupported ) ? null : [ GetUriSecuritySupported ( ) ] ,
385405 PrinterUpTime = ! IsRequired ( PrinterAttribute . PrinterUpTime ) ? null : ( int ) ( dateTimeOffsetProvider . UtcNow - _startTime ) . TotalSeconds ,
@@ -661,10 +681,10 @@ private async Task<PrintJobResponse> GetPrintJobResponseAsync(PrintJobRequest re
661681 return response ;
662682 }
663683
664- private string GetPrinterUrl ( )
684+ private string GetPrinterUrl ( string ? path = null )
665685 {
666686 var request = httpContextAccessor . HttpContext ? . Request ?? throw new Exception ( "Unable to access HttpContext" ) ;
667- return $ "ipp://{ request . Host } { request . PathBase } { request . Path } ";
687+ return $ "ipp://{ request . Host } { request . PathBase } { ( path is null ? request . Path : path ) } ";
668688 }
669689
670690 private string GetPrinterMoreInfo ( )
0 commit comments