Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for listing cups printers #8

Merged
merged 5 commits into from
May 13, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions SharpIpp/Model/CUPSGetPrintersRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;

namespace SharpIpp.Model
{
public class CUPSGetPrintersRequest : IIppPrinterRequest
{
/// The client OPTIONALLY supplies this attribute to select the
/// first printer that is returned.
public string? FirstPrinterName { get; set; }

/// The client OPTIONALLY supplies this attribute. The Printer
/// object MUST support this attribute. It is an integer value that
/// determines the maximum number of jobs that a client will
/// receive from the Printer even if "which-jobs" or "my-jobs"
/// constrain which jobs are returned. The limit is a "stateless
/// limit" in that if the value supplied by the client is 'N', then
/// only the first 'N' jobs are returned in the Get-Jobs Response.
/// There is no mechanism to allow for the next 'M' jobs after the
/// first 'N' jobs. If the client does not supply this attribute,
/// the Printer object responds with all applicable jobs.
public int? Limit { get; set; }


///The client OPTIONALLY supplies this attribute to select which printer is returned.
public int? PrinterID { get; set; }

///The client OPTIONALLY supplies this attribute to select which printers are returned.
public string? PrinterLocation { get; set; }


///The client OPTIONALLY supplies a printer type enumeration to select which printers are returned.
public PrinterType? PrinterType { get; set; }

///The client OPTIONALLY supplies a printer type mask enumeration to select which bits are used in the "printer-type" attribute.
BlackHeart-TF marked this conversation as resolved.
Show resolved Hide resolved
public PrinterType? PrinterTypeMask { get; set; }

/// <summary>
/// The client OPTIONALLY supplies this attribute. The Printer
/// object MUST support this attribute. It is a set of Job
/// attribute names and/or attribute groups names in whose values
/// the requester is interested. This set of attributes is
/// returned for each Job object that is returned. The allowed
/// attribute group names are the same as those defined in the
/// Get-Job-Attributes operation in section 3.3.4. If the client
/// does not supply this attribute, the Printer MUST respond as if
/// the client had supplied this attribute with two values: 'job-
/// uri' and 'job-id'.
/// </summary>
public string[]? RequestedAttributes { get; set; }

public IppVersion Version { get; set; } = IppVersion.CUPS10;
public int RequestId { get; set; } = 1;
public Uri PrinterUri { get; set; } = null!;

/// <summary>
/// The "requesting-user-name" (name(MAX)) attribute SHOULD be
/// supplied by the client
/// </summary>
public string? RequestingUserName { get; set; }

public IEnumerable<IppAttribute>? AdditionalOperationAttributes { get; set; }
public IEnumerable<IppAttribute>? AdditionalJobAttributes { get; set; }
}

public enum PrinterType
Zelenov marked this conversation as resolved.
Show resolved Hide resolved
{
Printer
}
}
13 changes: 13 additions & 0 deletions SharpIpp/Model/CUPSGetPrintersResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Collections.Generic;

namespace SharpIpp.Model
{
public class CUPSGetPrintersResponse : IIppResponseMessage
{
public JobAttributes[] Jobs { get; set; } = null!;
public IppVersion Version { get; set; } = IppVersion.CUPS10;
public IppStatusCode StatusCode { get; set; }
public int RequestId { get; set; } = 1;
public List<IppSection> Sections { get; } = new List<IppSection>();
}
}
3 changes: 2 additions & 1 deletion SharpIpp/Model/IppOperation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public enum IppOperation : short
ReservedForAFutureOperation = 0x000F,
PausePrinter = 0x0010,
ResumePrinter = 0x0011,
PurgeJobs = 0x0012
PurgeJobs = 0x0012,
GetCUPSPrinters = 0x4002
}
}
3 changes: 2 additions & 1 deletion SharpIpp/Model/IppVersion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
/// </summary>
public enum IppVersion : short
{
V11 = 0x0101
V11 = 0x0101,
CUPS10 = 0x0201
}
}
2 changes: 2 additions & 0 deletions SharpIpp/Protocol/IIppProtocol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ internal interface IIppProtocol
GetJobAttributesResponse ConstructGetJobAttributesResponse(IIppResponseMessage ippResponse);
IppRequestMessage Construct(GetJobsRequest request);
GetJobsResponse ConstructGetJobsResponse(IIppResponseMessage ippResponse);
IppRequestMessage Construct(CUPSGetPrintersRequest request);
CUPSGetPrintersResponse ConstructGetCUPSPrintersResponse(IIppResponseMessage ippResponse);
IppRequestMessage Construct(GetPrinterAttributesRequest request);
GetPrinterAttributesResponse ConstructGetPrinterAttributesResponse(IIppResponseMessage ippResponse);
IppRequestMessage Construct(HoldJobRequest request);
Expand Down
60 changes: 60 additions & 0 deletions SharpIpp/Protocol/IppProtocol.GetCUPSPrinters.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System.Collections.Generic;
using System.Linq;
using SharpIpp.Model;
using SharpIpp.Protocol.Extensions;

namespace SharpIpp.Protocol
{
internal partial class IppProtocol
{
/// <summary>
/// Get-Job-Attributes Request
/// https://tools.ietf.org/html/rfc2911#section-3.3.4.1
/// </summary>
/// <param name="request"></param>
public IppRequestMessage Construct(CUPSGetPrintersRequest request) => ConstructIppRequest(request);

/// <summary>
/// Get-Job-Attributes Response
/// https://tools.ietf.org/html/rfc2911#section-3.3.4.2
/// </summary>
public CUPSGetPrintersResponse ConstructGetCUPSPrintersResponse(IIppResponseMessage ippResponse) =>
Construct<CUPSGetPrintersResponse>(ippResponse);

private static void ConfigureGetCUPSPrintersResponse(SimpleMapper mapper)
{
mapper.CreateMap<CUPSGetPrintersRequest, IppRequestMessage>((src, map) =>
{
var dst = new IppRequestMessage {IppOperation = IppOperation.GetCUPSPrinters};
mapper.Map<IIppPrinterRequest, IppRequestMessage>(src, dst);
var operation = dst.OperationAttributes;
if (src.Limit != null)
operation.Add(new IppAttribute(Tag.Integer, "requesting-user-name", src.Limit.Value));
if (src.FirstPrinterName != null)
operation.Add(new IppAttribute(Tag.Keyword, "first-printer-name", Mapper.Map<string>(src.FirstPrinterName)));
BlackHeart-TF marked this conversation as resolved.
Show resolved Hide resolved
if (src.PrinterID != null)
operation.Add(new IppAttribute(Tag.Integer, "printer-id", Mapper.Map<string>(src.PrinterID)));
if (src.PrinterLocation != null)
operation.Add(new IppAttribute(Tag.Keyword, "printer-location", Mapper.Map<string>(src.PrinterLocation)));
if (src.RequestedAttributes != null)
operation.AddRange(src.RequestedAttributes.Select(requestedAttribute =>
new IppAttribute(Tag.Keyword, "requested-attributes", requestedAttribute)));

dst.OperationAttributes.Populate(src.AdditionalOperationAttributes);
dst.JobAttributes.Populate(src.AdditionalJobAttributes);
return dst;
});
mapper.CreateMap<IppResponseMessage, CUPSGetPrintersResponse>((src, map) =>
{
var dst = new CUPSGetPrintersResponse { Jobs = map.Map<List<IppSection>, JobAttributes[]>(src.Sections)};
map.Map<IppResponseMessage, IIppResponseMessage>(src, dst);
return dst;
});
//https://tools.ietf.org/html/rfc2911#section-4.4
//mapper.CreateMap<List<IppSection>, JobAttributes[]>((src, map) =>
// src.Where(x => x.Tag == SectionTag.JobAttributesTag)
// .Select(x => map.Map<JobAttributes>(x.AllAttributes()))
// .ToArray());
}
}
}
1 change: 1 addition & 0 deletions SharpIpp/Protocol/IppProtocol.Mapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ static IppProtocol()
ConfigureGetPrinterAttributesResponse(Mapper);
ConfigureGetJobAttributesResponse(Mapper);
ConfigureGetJobsResponse(Mapper);
ConfigureGetCUPSPrintersResponse(Mapper);
ConfigurePrintUriRequest(Mapper);
ConfigureCreateJobRequest(Mapper);
ConfigureValidateJobRequest(Mapper);
Expand Down
3 changes: 2 additions & 1 deletion SharpIpp/Protocol/IppProtocol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -281,5 +281,6 @@ public void Write(IppRequestMessage requestMessage, BinaryWriter writer)
//end-of-attributes-tag https://tools.ietf.org/html/rfc8010#section-3.5.1
writer.Write((byte) SectionTag.EndOfAttributesTag);
}

}
}
}
12 changes: 12 additions & 0 deletions SharpIpp/SharpIppClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,18 @@ public async Task<GetJobsResponse> GetJobsAsync(GetJobsRequest request)
ippResponse => _ippProtocol.ConstructGetJobsResponse(ippResponse));
}

/// <summary>
/// CUPS Get-Printers Operation
/// http://www.cups.org/doc/spec-ipp.html
/// </summary>
/// <param name="request">The CUPSGetPrintersRequest object</param>
/// <returns></returns>
public async Task<CUPSGetPrintersResponse> GetCUPSPrintersAsync(CUPSGetPrintersRequest request)
{
return await SendAsync(request.PrinterUri, () => _ippProtocol.Construct(request),
ippResponse => _ippProtocol.ConstructGetCUPSPrintersResponse(ippResponse));
}

/// <summary>
/// Custom Operation, not defined in the standard
/// </summary>
Expand Down