1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 *
26 */
27
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <ctype.h>
32#include <errno.h>
33#include <sys/types.h>
34#include <unistd.h>
35#include <papi.h>
36#include <ipp-listener.h>
37
38char *
39ipp_svc_status_mesg(papi_service_t svc, papi_status_t status)
40{
41	char *mesg =  papiServiceGetStatusMessage(svc);
42
43	if (mesg == NULL)
44		mesg = papiStatusString(status);
45
46	return (mesg);
47}
48
49char *
50destination_from_printer_uri(char *uri)
51{
52	char *result = NULL;
53
54	if (uri != NULL)
55		result = strrchr(uri, '/');
56
57	if (result == NULL)
58		result = uri;
59	else
60		result++;
61
62	return (result);
63}
64
65void
66get_printer_id(papi_attribute_t **attributes, char **printer, int *id)
67{
68	papi_status_t result;
69	char *job = NULL;
70	char *fodder;
71	int junk;
72
73	if (printer == NULL)
74		printer = &fodder;
75	if (id == NULL)
76		id = &junk;
77
78	*printer = NULL;
79	*id = -1;
80
81	result = papiAttributeListGetString(attributes, NULL, "job-uri", &job);
82	if (result != PAPI_OK) {
83		result = papiAttributeListGetString(attributes, NULL,
84		    "printer-uri", printer);
85		if (result == PAPI_OK)
86			papiAttributeListGetInteger(attributes, NULL,
87			    "job-id", id);
88	} else {
89		*printer = job;
90		if ((job = strrchr(*printer, '/')) != NULL) {
91			*job = '\0';
92			*id = atoi(++job);
93		}
94	}
95}
96
97void
98get_string_list(papi_attribute_t **attributes, char *name, char ***values)
99{
100	papi_status_t result;
101
102	void *iterator = NULL;
103	char *value = NULL;
104
105	for (result = papiAttributeListGetString(attributes, &iterator,
106	    name, &value);
107	    result == PAPI_OK;
108	    result = papiAttributeListGetString(attributes, &iterator,
109	    NULL, &value))
110		list_append(values, value);
111}
112
113void
114add_default_attributes(papi_attribute_t ***attributes)
115{
116
117	(void) papiAttributeListAddString(attributes, PAPI_ATTR_APPEND,
118	    "ipp-versions-supported", "1.0");
119	(void) papiAttributeListAddString(attributes, PAPI_ATTR_APPEND,
120	    "ipp-versions-supported", "1.1");
121	(void) papiAttributeListAddBoolean(attributes, PAPI_ATTR_EXCL,
122	    "multiple-document-jobs-supported", 0);
123	/*
124	 * Should be able to ask the web server if it supports SSL or TLS, but
125	 * for now, we pick only "none"
126	 */
127	(void) papiAttributeListAddString(attributes, PAPI_ATTR_EXCL,
128	    "uri-security-supported", "none");
129
130	/*
131	 * For now, we only "none".  As we support more authentication methods,
132	 * we will need to add the associated uri for each.  Valid values would
133	 * be:
134	 *	"none", "requesting-user-name", "basic", "digest", "certificate"
135	 * See RFC2911 page 127 for more information.
136	 */
137	(void) papiAttributeListAddString(attributes, PAPI_ATTR_EXCL,
138	    "uri-authentication-supported", "requesting-user-name");
139	(void) papiAttributeListAddString(attributes, PAPI_ATTR_EXCL,
140	    "uri-security-supported", "none");
141	/* printer-uri-supported is added in the service based attributes */
142
143	(void) papiAttributeListAddInteger(attributes, PAPI_ATTR_EXCL,
144	    "multiple-operation-time-out", 60);
145
146	/* I18N related */
147	(void) papiAttributeListAddString(attributes, PAPI_ATTR_EXCL,
148	    "charset-configured", "utf-8");
149	(void) papiAttributeListAddString(attributes, PAPI_ATTR_EXCL,
150	    "charset-supported", "utf-8");
151	(void) papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE,
152	    "natural-language-configured", "en-us");
153}
154
155static void
156massage_printer_attributes_group(papi_attribute_t **group, char *printer_uri)
157{
158	if (papiAttributeListFind(group, "printer-uri-supported") != NULL)
159		papiAttributeListAddString(&group, PAPI_ATTR_REPLACE,
160		    "printer-uri-supported", printer_uri);
161}
162
163static void
164massage_job_attributes_group(papi_attribute_t **group, char *printer_uri)
165{
166	if (papiAttributeListFind(group, "job-printer-uri") != NULL)
167		papiAttributeListAddString(&group, PAPI_ATTR_REPLACE,
168		    "job-printer-uri", printer_uri);
169
170	if (papiAttributeListFind(group, "job-printer-uri") != NULL) {
171		char buf[BUFSIZ];
172		int32_t id = -1;
173
174		papiAttributeListGetInteger(group, NULL, "job-id", &id);
175		snprintf(buf, sizeof (buf), "%s/%d", printer_uri, id);
176		papiAttributeListAddString(&group, PAPI_ATTR_REPLACE,
177		    "job-uri", buf);
178	}
179}
180
181/*
182 * This function will replace the job/printer URIs with the requested
183 * uri because the print service may return a URI that isn't IPP based.
184 */
185void
186massage_response(papi_attribute_t **request, papi_attribute_t **response)
187{
188	papi_status_t status;
189	papi_attribute_t **group = NULL;
190	void *iter = NULL;
191	char *host = "localhost";
192	char *path = "/printers/";
193	int port = 631;
194	char buf[BUFSIZ];
195
196	(void) papiAttributeListGetString(request, NULL, "uri-host", &host);
197	(void) papiAttributeListGetString(request, NULL, "uri-path", &path);
198	(void) papiAttributeListGetInteger(request, NULL, "uri-port", &port);
199
200	if (port == 631)
201		snprintf(buf, sizeof (buf), "ipp://%s%s", host, path);
202	else
203		snprintf(buf, sizeof (buf), "http://%s:%d%s", host, port, path);
204
205	for (status = papiAttributeListGetCollection(response, &iter,
206	    "printer-attributes-group", &group);
207	    status == PAPI_OK;
208	    status = papiAttributeListGetCollection(NULL, &iter, NULL, &group))
209		massage_printer_attributes_group(group, buf);
210
211	iter = NULL;
212	for (status = papiAttributeListGetCollection(response, &iter,
213	    "job-attributes-group", &group);
214	    status == PAPI_OK;
215	    status = papiAttributeListGetCollection(NULL, &iter, NULL, &group))
216		massage_job_attributes_group(group, buf);
217}
218
219/*
220 * This walks through the locale tab and returns the installed
221 * locales.  There must be a better way.
222 */
223void
224add_supported_locales(papi_attribute_t ***attributes)
225{
226	FILE *fp;
227
228	papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE,
229	    "generated-natural-language-supported", "en-us");
230
231	if ((fp = fopen("/usr/lib/locale/lcttab", "r")) != NULL) {
232		char buf[1024];
233
234		while (fgets(buf, sizeof (buf), fp) != NULL) {
235			char *name, *file;
236			int i, passed = 1;
237
238			name = strtok(buf, " \t\n");
239			if (name == NULL)
240				continue;
241
242			for (i = 0; ((passed == 1) && (name[i] != '\0')); i++) {
243				if (isalpha(name[i]) != 0)
244					name[i] = tolower(name[i]);
245				else if ((name[i] == '_') || (name[i] == '-'))
246					name[i] = '-';
247				else
248					passed = 0;
249			}
250
251			if ((passed == 1) &&
252			    ((file = strtok(NULL, " \t\n")) != NULL)) {
253					char path[1024];
254
255				snprintf(path, sizeof (path),
256				    "/usr/lib/locale/%s", file);
257
258				if (access(path, F_OK) != 0)
259					continue;
260
261				papiAttributeListAddString(attributes,
262				    PAPI_ATTR_APPEND,
263				    "generated-natural-language-supported",
264				    name);
265			}
266		}
267		(void) fclose(fp);
268	}
269}
270
271void
272papi_to_ipp_printer_group(papi_attribute_t ***response,
273    papi_attribute_t **request, int flags, papi_printer_t p)
274{
275	papi_attribute_t **ipp_group = NULL;
276
277	copy_attributes(&ipp_group, papiPrinterGetAttributeList(p));
278
279	/* Windows clients appear to have a problem with very large values */
280	papiAttributeListDelete(&ipp_group, "lpsched-printer-ppd-contents");
281
282	add_default_attributes(&ipp_group);
283	ipp_operations_supported(&ipp_group, request);
284
285	(void) papiAttributeListAddCollection(response, flags,
286	    "printer-attributes-group", ipp_group);
287	papiAttributeListFree(ipp_group);
288}
289
290void
291papi_to_ipp_job_group(papi_attribute_t ***response,
292    papi_attribute_t **request, int flags, papi_job_t j)
293{
294	papi_attribute_t **ipp_group = NULL;
295
296	copy_attributes(&ipp_group, papiJobGetAttributeList(j));
297
298	(void) papiAttributeListAddCollection(response, flags,
299	    "job-attributes-group", ipp_group);
300	papiAttributeListFree(ipp_group);
301}
302