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