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 
38 char *
ipp_svc_status_mesg(papi_service_t svc,papi_status_t status)39 ipp_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 
49 char *
destination_from_printer_uri(char * uri)50 destination_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 
65 void
get_printer_id(papi_attribute_t ** attributes,char ** printer,int * id)66 get_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 
97 void
get_string_list(papi_attribute_t ** attributes,char * name,char *** values)98 get_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 
113 void
add_default_attributes(papi_attribute_t *** attributes)114 add_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 
155 static void
massage_printer_attributes_group(papi_attribute_t ** group,char * printer_uri)156 massage_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 
163 static void
massage_job_attributes_group(papi_attribute_t ** group,char * printer_uri)164 massage_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  */
185 void
massage_response(papi_attribute_t ** request,papi_attribute_t ** response)186 massage_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  */
223 void
add_supported_locales(papi_attribute_t *** attributes)224 add_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 
271 void
papi_to_ipp_printer_group(papi_attribute_t *** response,papi_attribute_t ** request,int flags,papi_printer_t p)272 papi_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 
290 void
papi_to_ipp_job_group(papi_attribute_t *** response,papi_attribute_t ** request,int flags,papi_job_t j)291 papi_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