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 /* $Id: service.c 171 2006-05-20 06:00:32Z njacobs $ */
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 /*LINTLIBRARY*/
33 
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <stdarg.h>
37 #include <string.h>
38 #include <alloca.h>
39 #include <libintl.h>
40 #include <papi_impl.h>
41 
42 #include <config-site.h>
43 
44 http_encryption_t
45 http_encryption_type(papi_encryption_t encryption)
46 {
47 	switch (encryption) {
48 	case PAPI_ENCRYPT_IF_REQUESTED:
49 		return (HTTP_ENCRYPT_IF_REQUESTED);
50 	case PAPI_ENCRYPT_REQUIRED:
51 		return (HTTP_ENCRYPT_REQUIRED);
52 	case PAPI_ENCRYPT_ALWAYS:
53 		return (HTTP_ENCRYPT_ALWAYS);
54 	case PAPI_ENCRYPT_NEVER:
55 		return (HTTP_ENCRYPT_NEVER);
56 	default:
57 		; /* this should log an error */
58 	}
59 
60 	return (HTTP_ENCRYPT_NEVER);	/* should never get here */
61 }
62 
63 papi_status_t
64 service_connect(service_t *svc, char *service_name)
65 {
66 	papi_status_t result = PAPI_OK;
67 	int port = 631;
68 
69 	if (svc == NULL)
70 		return (PAPI_BAD_ARGUMENT);
71 
72 	if (svc->connection != NULL)	/* alread connected ? */
73 		return (PAPI_OK);
74 
75 	if (svc->uri == NULL)
76 		uri_from_string(service_name, &svc->uri);
77 
78 	if ((service_name != NULL) && (svc->uri == NULL)) {
79 		/*
80 		 * a name was supplied and it's not in URI form, we will
81 		 * try to use a "default" IPP service under the assumption
82 		 * that this is most likely a short-form printer name from
83 		 * from a papiPrinter*() or papiJob*() call and not from a
84 		 * papiServiceCreate() call.
85 		 */
86 		if ((service_name = getenv("PAPI_SERVICE_URI")) == NULL) {
87 			char *cups;
88 
89 			if ((cups = getenv("CUPS_SERVER")) != NULL) {
90 				char buf[BUFSIZ];
91 
92 				snprintf(buf, sizeof (buf),
93 					"ipp://%s/printers/", cups);
94 				service_name = strdup(buf);
95 			}
96 		}
97 		if (service_name == NULL)
98 			service_name = DEFAULT_IPP_SERVICE_URI;
99 
100 		uri_from_string(service_name, &svc->uri);
101 	}
102 
103 	if (svc->uri == NULL)
104 		return (PAPI_NOT_POSSIBLE);
105 
106 	if (svc->uri->port != NULL)
107 		port = strtol(svc->uri->port, NULL, 10);
108 
109 	svc->connection = httpConnectEncrypt(svc->uri->host, port,
110 					http_encryption_type(svc->encryption));
111 	if (svc->connection == NULL) {
112 		if (svc->uri != NULL) {
113 			uri_free(svc->uri);
114 			svc->uri = NULL;
115 		}
116 		result = PAPI_SERVICE_UNAVAILABLE;
117 	} else if (service_name != NULL)
118 		svc->name = strdup(service_name);
119 
120 	return (result);
121 }
122 
123 papi_status_t
124 papiServiceCreate(papi_service_t *handle, char *service_name,
125 		char *user_name, char *password,
126 		int (*authCB)(papi_service_t svc, void *app_data),
127 		papi_encryption_t encryption, void *app_data)
128 {
129 	papi_status_t result = PAPI_NOT_POSSIBLE;
130 	service_t *svc = NULL;
131 	char *encoding = getenv("HTTP_TRANSFER_ENCODING");
132 
133 	if (handle == NULL)
134 		return (PAPI_BAD_ARGUMENT);
135 
136 	if ((*handle = svc = calloc(1, sizeof (*svc))) == NULL)
137 		return (PAPI_TEMPORARY_ERROR);
138 
139 	if (user_name != NULL)
140 		svc->user = strdup(user_name);
141 
142 	if (password != NULL)
143 		svc->password = strdup(password);
144 
145 	svc->encryption = encryption;
146 
147 	if (authCB != NULL)
148 		svc->authCB = authCB;
149 
150 	if (app_data != NULL)
151 		svc->app_data = app_data;
152 
153 	if ((encoding != NULL) && (strcasecmp(encoding, "content-length") == 0))
154 		svc->transfer_encoding = TRANSFER_ENCODING_LENGTH;
155 	else
156 		svc->transfer_encoding = TRANSFER_ENCODING_CHUNKED;
157 
158 	if (service_name != NULL) {
159 		result = service_connect(svc, service_name);
160 	} else
161 		result = PAPI_OK;
162 
163 	return (result);
164 }
165 
166 void
167 papiServiceDestroy(papi_service_t handle)
168 {
169 	if (handle != NULL) {
170 		service_t *svc = handle;
171 
172 		if (svc->attributes != NULL)
173 			papiAttributeListFree(svc->attributes);
174 		if (svc->name != NULL)
175 			free(svc->name);
176 		if (svc->user != NULL)
177 			free(svc->user);
178 		if (svc->password != NULL)
179 			free(svc->password);
180 		if (svc->uri != NULL)
181 			uri_free(svc->uri);
182 		if (svc->post != NULL)
183 			free(svc->post);
184 		if (svc->connection != NULL)
185 			httpClose(svc->connection);
186 
187 		free(handle);
188 	}
189 }
190 
191 papi_status_t
192 papiServiceSetUserName(papi_service_t handle, char *user_name)
193 {
194 	papi_status_t result = PAPI_OK;
195 
196 	if (handle != NULL) {
197 		service_t *svc = handle;
198 
199 		if (svc->user != NULL)
200 			free(svc->user);
201 		svc->user = NULL;
202 		if (user_name != NULL)
203 			svc->user = strdup(user_name);
204 	} else
205 		result = PAPI_BAD_ARGUMENT;
206 
207 	return (result);
208 }
209 
210 papi_status_t
211 papiServiceSetPassword(papi_service_t handle, char *password)
212 {
213 	papi_status_t result = PAPI_OK;
214 
215 	if (handle != NULL) {
216 		service_t *svc = handle;
217 
218 		if (svc->password != NULL)
219 			free(svc->password);
220 		svc->password = NULL;
221 		if (password != NULL)
222 			svc->password = strdup(password);
223 	} else
224 		result = PAPI_BAD_ARGUMENT;
225 
226 	return (result);
227 }
228 
229 papi_status_t
230 papiServiceSetEncryption(papi_service_t handle,
231 			papi_encryption_t encryption)
232 {
233 	papi_status_t result = PAPI_OK;
234 
235 	if (handle != NULL) {
236 		service_t *svc = handle;
237 
238 		svc->encryption = encryption;
239 		httpEncryption(svc->connection,
240 				(http_encryption_t)svc->encryption);
241 	} else
242 		result = PAPI_BAD_ARGUMENT;
243 
244 	return (result);
245 }
246 
247 papi_status_t
248 papiServiceSetAuthCB(papi_service_t handle,
249 			int (*authCB)(papi_service_t svc, void *app_data))
250 {
251 	papi_status_t result = PAPI_OK;
252 
253 	if (handle != NULL) {
254 		service_t *svc = handle;
255 
256 		svc->authCB = authCB;
257 	} else
258 		result = PAPI_BAD_ARGUMENT;
259 
260 	return (result);
261 }
262 
263 
264 papi_status_t
265 papiServiceSetAppData(papi_service_t handle, void *app_data)
266 {
267 	papi_status_t result = PAPI_OK;
268 
269 	if (handle != NULL) {
270 		service_t *svc = handle;
271 
272 		svc->app_data = (void *)app_data;
273 	} else
274 		result = PAPI_BAD_ARGUMENT;
275 
276 	return (result);
277 }
278 
279 char *
280 papiServiceGetServiceName(papi_service_t handle)
281 {
282 	char *result = NULL;
283 
284 	if (handle != NULL) {
285 		service_t *svc = handle;
286 
287 		result = svc->name;
288 	}
289 
290 	return (result);
291 }
292 
293 char *
294 papiServiceGetUserName(papi_service_t handle)
295 {
296 	char *result = NULL;
297 
298 	if (handle != NULL) {
299 		service_t *svc = handle;
300 
301 		result = svc->user;
302 	}
303 
304 	return (result);
305 }
306 
307 char *
308 papiServiceGetPassword(papi_service_t handle)
309 {
310 	char *result = NULL;
311 
312 	if (handle != NULL) {
313 		service_t *svc = handle;
314 
315 		result = svc->password;
316 	}
317 
318 	return (result);
319 }
320 
321 papi_encryption_t
322 papiServiceGetEncryption(papi_service_t handle)
323 {
324 	papi_encryption_t result = PAPI_ENCRYPT_NEVER;
325 
326 	if (handle != NULL) {
327 		service_t *svc = handle;
328 
329 		result = svc->encryption;
330 	}
331 
332 	return (result);
333 }
334 
335 void *
336 papiServiceGetAppData(papi_service_t handle)
337 {
338 	void *result = NULL;
339 
340 	if (handle != NULL) {
341 		service_t *svc = handle;
342 
343 		result = svc->app_data;
344 	}
345 
346 	return (result);
347 }
348 
349 papi_attribute_t **
350 papiServiceGetAttributeList(papi_service_t handle)
351 {
352 	papi_attribute_t **result = NULL;
353 	service_t *svc = handle;
354 
355 	if (handle != NULL)
356 		result = svc->attributes;
357 
358 	return (result);
359 }
360 
361 char *
362 papiServiceGetStatusMessage(papi_service_t handle)
363 {
364 	char *result = NULL;
365 	service_t *svc = handle;
366 
367 	papiAttributeListGetString(svc->attributes, NULL,
368 					"detailed-status-message", &result);
369 
370 	return (result);
371 }
372 
373 void
374 detailed_error(service_t *svc, char *fmt, ...)
375 {
376 	if ((svc != NULL) && (fmt != NULL)) {
377 		va_list ap;
378 		size_t size;
379 		char *message = alloca(BUFSIZ);
380 
381 		va_start(ap, fmt);
382 		/*
383 		 * fill in the message.  If the buffer is too small, allocate
384 		 * one that is large enough and fill it in.
385 		 */
386 		if ((size = vsnprintf(message, BUFSIZ, fmt, ap)) >= BUFSIZ)
387 			if ((message = alloca(size)) != NULL)
388 				vsnprintf(message, size, fmt, ap);
389 		va_end(ap);
390 
391 		papiAttributeListAddString(&svc->attributes, PAPI_ATTR_APPEND,
392 					"detailed-status-message", message);
393 	}
394 }
395