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