xref: /haiku/src/add-ons/print/transports/ipp/IppTransport.cpp (revision 21258e2674226d6aa732321b6f8494841895af5f)
1 // Sun, 18 Jun 2000
2 // Y.Takagi
3 
4 #include <Alert.h>
5 #include <DataIO.h>
6 #include <Directory.h>
7 #include <Message.h>
8 #include <Url.h>
9 
10 #include <pwd.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <strings.h>
14 #include <unistd.h>
15 
16 #include "IppContent.h"
17 #include "IppURLConnection.h"
18 #include "IppSetupDlg.h"
19 #include "IppTransport.h"
20 #include "IppDefs.h"
21 #include "DbgMsg.h"
22 
23 #if (!__MWERKS__)
24 using namespace std;
25 #else
26 #define std
27 #endif
28 
29 IppTransport::IppTransport(BMessage *msg)
30 	: BDataIO()
31 {
32 	__url[0]  = '\0';
33 	__user[0] = '\0';
34 	__file[0] = '\0';
35 	__jobid   = 0;
36 	__error   = false;
37 
38 	DUMP_BMESSAGE(msg);
39 
40 	const char *spool_path = msg->FindString(SPOOL_PATH);
41 	if (spool_path && *spool_path) {
42 		BDirectory dir(spool_path);
43 		DUMP_BDIRECTORY(&dir);
44 
45 		dir.ReadAttr(IPP_URL, B_STRING_TYPE, 0, __url, sizeof(__url));
46 		if (__url[0] == '\0') {
47 			IppSetupDlg *dlg = new IppSetupDlg(&dir);
48 			if (dlg->Go() == B_ERROR) {
49 				__error = true;
50 				return;
51 			}
52 		}
53 
54 		dir.ReadAttr(IPP_URL,    B_STRING_TYPE, 0, __url,    sizeof(__url));
55 		dir.ReadAttr(IPP_JOB_ID, B_INT32_TYPE,  0, &__jobid, sizeof(__jobid));
56 		__jobid++;
57 		if (__jobid > 255) {
58 			__jobid = 1;
59 		}
60 		dir.WriteAttr(IPP_JOB_ID, B_INT32_TYPE, 0, &__jobid, sizeof(__jobid));
61 
62 		struct passwd *pwd = getpwuid(geteuid());
63 		if (pwd != NULL && pwd->pw_name != NULL && pwd->pw_name[0])
64 			strcpy(__user, pwd->pw_name);
65 		else
66 			strcpy(__user, "baron");
67 
68 		sprintf(__file, "%s/%s@ipp.%" B_PRId32, spool_path, __user, __jobid);
69 
70 		__fs.open(__file, ios::in | ios::out | ios::binary | ios::trunc);
71 		if (__fs.good()) {
72 			DBGMSG(("spool_file: %s\n", __file));
73 			return;
74 		}
75 	}
76 	__error = true;
77 }
78 
79 IppTransport::~IppTransport()
80 {
81 	string error_msg;
82 
83 	if (!__error && __fs.good()) {
84 		DBGMSG(("create IppContent\n"));
85 		IppContent *request = new IppContent;
86 		request->setOperationId(IPP_PRINT_JOB);
87 		request->setDelimiter(IPP_OPERATION_ATTRIBUTES_TAG);
88 		request->setCharset("attributes-charset", "utf-8");
89 		request->setNaturalLanguage("attributes-natural-language", "en-us");
90 		request->setURI("printer-uri", __url);
91 		request->setMimeMediaType("document-format", "application/octet-stream");
92 		request->setNameWithoutLanguage("requesting-user-name", __user);
93 //		request->setNameWithoutLanguage("job-name", __file);	// optional
94 		request->setDelimiter(IPP_END_OF_ATTRIBUTES_TAG);
95 
96 		long fssize = __fs.tellg();
97 		__fs.seekg(0, ios::beg);
98 		request->setRawData(__fs, fssize);
99 
100 		BUrl url(__url);
101 		IppURLConnection conn(url);
102 		conn.setIppRequest(request);
103 		conn.setRequestProperty("Connection", "close");
104 
105 		DBGMSG(("do connect\n"));
106 
107 		HTTP_RESPONSECODE response_code = conn.getResponseCode();
108 		if (response_code == HTTP_OK) {
109 			const char *content_type = conn.getContentType();
110 			if (content_type == NULL || strncasecmp(content_type, "application/ipp", 15) == 0) {
111 				const IppContent *ipp_response = conn.getIppResponse();
112 				if (ipp_response->fail()) {
113 					__error = true;
114 					error_msg = ipp_response->getStatusMessage();
115 				}
116 			} else {
117 				__error = true;
118 				error_msg = "cannot get a IPP response.";
119 			}
120 		} else if (response_code != HTTP_UNKNOWN) {
121 			__error = true;
122 			error_msg = conn.getResponseMessage();
123 		} else {
124 			__error = true;
125 			error_msg = "cannot connect to the IPP server.";
126 		}
127 	}
128 
129 	unlink(__file);
130 
131 	if (__error) {
132 		BAlert *alert = new BAlert("", error_msg.c_str(), "OK");
133 		alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
134 		alert->Go();
135 	}
136 }
137 
138 ssize_t IppTransport::Read(void *, size_t)
139 {
140 	return 0;
141 }
142 
143 ssize_t IppTransport::Write(const void *buffer, size_t size)
144 {
145 //	DBGMSG(("write: %d\n", size));
146 
147 	if (!__fs.write((const char *)buffer, size)) {
148 		__error = true;
149 		return 0;
150 	}
151 //	return __fs.pcount();
152 	return size;
153 }
154