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