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__)
23using namespace std;
24#else
25#define std
26#endif
27
28IppTransport::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
78IppTransport::~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
137ssize_t IppTransport::Read(void *, size_t)
138{
139	return 0;
140}
141
142ssize_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