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