xref: /haiku/src/add-ons/print/transports/ipp/IppContent.cpp (revision 8449c783969cae2c4d4197feb75bf4d08bba8de2)
1 // Sun, 18 Jun 2000
2 // Y.Takagi
3 
4 #if defined(__HAIKU__) || defined(HAIKU_TARGET_PLATFORM_BONE)
5 #	include <sys/socket.h>
6 #	include <netinet/in.h>
7 #else
8 #	include <net/socket.h>
9 #endif
10 
11 #include <fstream>
12 #include <list>
13 #include <cstring>
14 
15 #include "IppContent.h"
16 
17 /*----------------------------------------------------------------------*/
18 
readLength(istream & is)19 short readLength(istream &is)
20 {
21 	short len = 0;
22 	is.read((char *)&len, sizeof(short));
23 	len = ntohs(len);
24 	return len;
25 }
26 
writeLength(ostream & os,short len)27 void writeLength(ostream &os, short len)
28 {
29 	len = htons(len);
30 	os.write((char *)&len, sizeof(short));
31 }
32 
33 /*----------------------------------------------------------------------*/
34 
DATETIME()35 DATETIME::DATETIME()
36 {
37 	memset(this, 0, sizeof(DATETIME));
38 }
39 
DATETIME(const DATETIME & dt)40 DATETIME::DATETIME(const DATETIME &dt)
41 {
42 	memcpy(this, &dt.datetime, sizeof(DATETIME));
43 }
44 
operator =(const DATETIME & dt)45 DATETIME & DATETIME::operator = (const DATETIME &dt)
46 {
47 	memcpy(this, &dt.datetime, sizeof(DATETIME));
48 	return *this;
49 }
50 
operator >>(istream & is,DATETIME & attr)51 istream& operator >> (istream &is, DATETIME &attr)
52 {
53 	return is;
54 }
55 
operator <<(ostream & os,const DATETIME & attr)56 ostream& operator << (ostream &os, const DATETIME &attr)
57 {
58 	return os;
59 }
60 
61 
62 /*----------------------------------------------------------------------*/
63 
IppAttribute(IPP_TAG t)64 IppAttribute::IppAttribute(IPP_TAG t)
65 	: tag(t)
66 {
67 }
68 
length() const69 int IppAttribute::length() const
70 {
71 	return 1;
72 }
73 
input(istream & is)74 istream &IppAttribute::input(istream &is)
75 {
76 	return is;
77 }
78 
output(ostream & os) const79 ostream &IppAttribute::output(ostream &os) const
80 {
81 	os << (unsigned char)tag;
82 	return os;
83 }
84 
print(ostream & os) const85 ostream &IppAttribute::print(ostream &os) const
86 {
87 	os << "Tag: " << hex << (int)tag << '\n';
88 	return os;
89 }
90 
91 /*----------------------------------------------------------------------*/
92 
IppNamedAttribute(IPP_TAG t)93 IppNamedAttribute::IppNamedAttribute(IPP_TAG t)
94 	: IppAttribute(t)
95 {
96 }
97 
IppNamedAttribute(IPP_TAG t,const char * s)98 IppNamedAttribute::IppNamedAttribute(IPP_TAG t, const char *s)
99 	: IppAttribute(t), name(s ? s : "")
100 {
101 }
102 
length() const103 int IppNamedAttribute::length() const
104 {
105 	return IppAttribute::length() + 2 + name.length();
106 }
107 
input(istream & is)108 istream &IppNamedAttribute::input(istream &is)
109 {
110 	short len = readLength(is);
111 
112 	if (0 < len) {
113 		char *buffer = new char[len + 1];
114 		is.read(buffer, len);
115 		buffer[len] = '\0';
116 		name = buffer;
117 		delete [] buffer;
118 	}
119 
120 	return is;
121 }
122 
output(ostream & os) const123 ostream &IppNamedAttribute::output(ostream &os) const
124 {
125 	IppAttribute::output(os);
126 
127 	writeLength(os, name.length());
128 	os << name;
129 
130 	return os;
131 }
132 
print(ostream & os) const133 ostream &IppNamedAttribute::print(ostream &os) const
134 {
135 	IppAttribute::print(os);
136 	os << '\t' << "Name: " << name << '\n';
137 	return os;
138 }
139 
140 /*----------------------------------------------------------------------*/
141 
IppNoValueAttribute(IPP_TAG t)142 IppNoValueAttribute::IppNoValueAttribute(IPP_TAG t)
143 	: IppNamedAttribute(t)
144 {
145 }
146 
IppNoValueAttribute(IPP_TAG t,const char * n)147 IppNoValueAttribute::IppNoValueAttribute(IPP_TAG t, const char *n)
148 	: IppNamedAttribute(t, n)
149 {
150 }
151 
length() const152 int IppNoValueAttribute::length() const
153 {
154 	return IppAttribute::length() + 2;
155 }
156 
input(istream & is)157 istream &IppNoValueAttribute::input(istream &is)
158 {
159 	IppNamedAttribute::input(is);
160 
161 	short len = readLength(is);
162 
163 	if (0 < len) {
164 		is.seekg(len, ios::cur);
165 	}
166 
167 	return is;
168 }
169 
output(ostream & os) const170 ostream &IppNoValueAttribute::output(ostream &os) const
171 {
172 	IppAttribute::output(os);
173 
174 	writeLength(os, 0);
175 
176 	return os;
177 }
178 
print(ostream & os) const179 ostream &IppNoValueAttribute::print(ostream &os) const
180 {
181 	return IppNamedAttribute::print(os);
182 }
183 
184 /*----------------------------------------------------------------------*/
185 
IppIntegerAttribute(IPP_TAG t)186 IppIntegerAttribute::IppIntegerAttribute(IPP_TAG t)
187 	: IppNamedAttribute(t), value(0)
188 {
189 }
190 
IppIntegerAttribute(IPP_TAG t,const char * n,int v)191 IppIntegerAttribute::IppIntegerAttribute(IPP_TAG t, const char *n, int v)
192 	: IppNamedAttribute(t, n), value(v)
193 {
194 }
195 
length() const196 int IppIntegerAttribute::length() const
197 {
198 	return IppNamedAttribute::length() + 2 + 4;
199 }
200 
input(istream & is)201 istream &IppIntegerAttribute::input(istream &is)
202 {
203 	IppNamedAttribute::input(is);
204 
205 	short len = readLength(is);
206 
207 	if (0 < len && len <= 4) {
208 		is.read((char *)&value, sizeof(value));
209 		value = ntohl(value);
210 	} else {
211 		is.seekg(len, ios::cur);
212 	}
213 
214 	return is;
215 }
216 
output(ostream & os) const217 ostream &IppIntegerAttribute::output(ostream &os) const
218 {
219 	IppNamedAttribute::output(os);
220 
221 	writeLength(os, 4);
222 	unsigned long val = htonl(value);
223 	os.write((char *)&val, sizeof(val));
224 	return os;
225 }
226 
print(ostream & os) const227 ostream &IppIntegerAttribute::print(ostream &os) const
228 {
229 	IppNamedAttribute::print(os);
230 	os << '\t' << "Value: " << dec << value << '\n';
231 	return os;
232 }
233 
234 /*----------------------------------------------------------------------*/
235 
IppBooleanAttribute(IPP_TAG t)236 IppBooleanAttribute::IppBooleanAttribute(IPP_TAG t)
237 	: IppNamedAttribute(t), value(false)
238 {
239 }
240 
IppBooleanAttribute(IPP_TAG t,const char * n,bool f)241 IppBooleanAttribute::IppBooleanAttribute(IPP_TAG t, const char *n, bool f)
242 	: IppNamedAttribute(t, n), value(f)
243 {
244 }
245 
length() const246 int IppBooleanAttribute::length() const
247 {
248 	return IppNamedAttribute::length() + 2 + 1;
249 }
250 
251 
input(istream & is)252 istream &IppBooleanAttribute::input(istream &is)
253 {
254 	IppNamedAttribute::input(is);
255 
256 	short len = readLength(is);
257 
258 	if (0 < len && len <= 1) {
259 		char c;
260 		is.read((char *)&c, sizeof(c));
261 		value = c ? true : false;
262 	} else {
263 		is.seekg(len, ios::cur);
264 	}
265 
266 	return is;
267 }
268 
output(ostream & os) const269 ostream &IppBooleanAttribute::output(ostream &os) const
270 {
271 	IppNamedAttribute::output(os);
272 
273 	writeLength(os, 1);
274 	char c = (char)value;
275 	os.write((char *)&c, sizeof(c));
276 
277 	return os;
278 }
279 
print(ostream & os) const280 ostream &IppBooleanAttribute::print(ostream &os) const
281 {
282 	IppNamedAttribute::print(os);
283 	os << '\t' << "Value: " << value << '\n';
284 	return os;
285 }
286 
287 /*----------------------------------------------------------------------*/
288 
IppDatetimeAttribute(IPP_TAG t)289 IppDatetimeAttribute::IppDatetimeAttribute(IPP_TAG t)
290 	: IppNamedAttribute(t)
291 {
292 }
293 
IppDatetimeAttribute(IPP_TAG t,const char * n,const DATETIME * dt)294 IppDatetimeAttribute::IppDatetimeAttribute(IPP_TAG t, const char *n, const DATETIME *dt)
295 	: IppNamedAttribute(t, n), datetime(*dt)
296 {
297 }
298 
length() const299 int IppDatetimeAttribute::length() const
300 {
301 	return IppNamedAttribute::length() + 2 + 11;
302 }
303 
input(istream & is)304 istream &IppDatetimeAttribute::input(istream &is)
305 {
306 	IppNamedAttribute::input(is);
307 
308 	short len = readLength(is);
309 
310 	if (0 < len) {
311 		if (len == 11) {
312 			is >> datetime;
313 		} else {
314 			is.seekg(len, ios::cur);
315 		}
316 	}
317 
318 	return is;
319 }
320 
output(ostream & os) const321 ostream &IppDatetimeAttribute::output(ostream &os) const
322 {
323 	IppNamedAttribute::output(os);
324 
325 	writeLength(os, 11);
326 	os << datetime;
327 
328 	return os;
329 }
330 
print(ostream & os) const331 ostream &IppDatetimeAttribute::print(ostream &os) const
332 {
333 	IppNamedAttribute::print(os);
334 	os << '\t' << "Value(DateTime): " << datetime << '\n';
335 	return os;
336 }
337 
338 /*----------------------------------------------------------------------*/
339 
IppStringAttribute(IPP_TAG t)340 IppStringAttribute::IppStringAttribute(IPP_TAG t)
341 	: IppNamedAttribute(t)
342 {
343 }
344 
IppStringAttribute(IPP_TAG t,const char * n,const char * s)345 IppStringAttribute::IppStringAttribute(IPP_TAG t, const char *n, const char *s)
346 : IppNamedAttribute(t, n), text(s ? s : "")
347 {
348 }
349 
length() const350 int IppStringAttribute::length() const
351 {
352 	return IppNamedAttribute::length() + 2 + text.length();
353 }
354 
input(istream & is)355 istream &IppStringAttribute::input(istream &is)
356 {
357 	IppNamedAttribute::input(is);
358 
359 	short len = readLength(is);
360 
361 	if (0 < len) {
362 		char *buffer = new char[len + 1];
363 		is.read(buffer, len);
364 		buffer[len] = '\0';
365 		text = buffer;
366 		delete [] buffer;
367 	}
368 
369 	return is;
370 }
371 
output(ostream & os) const372 ostream &IppStringAttribute::output(ostream &os) const
373 {
374 	IppNamedAttribute::output(os);
375 
376 	writeLength(os, text.length());
377 	os << text;
378 
379 	return os;
380 }
381 
print(ostream & os) const382 ostream &IppStringAttribute::print(ostream &os) const
383 {
384 	IppNamedAttribute::print(os);
385 	os << '\t' << "Value: " << text << '\n';
386 	return os;
387 }
388 
389 /*----------------------------------------------------------------------*/
390 
IppDoubleStringAttribute(IPP_TAG t)391 IppDoubleStringAttribute::IppDoubleStringAttribute(IPP_TAG t)
392 	: IppNamedAttribute(t)
393 {
394 }
395 
IppDoubleStringAttribute(IPP_TAG t,const char * n,const char * s1,const char * s2)396 IppDoubleStringAttribute::IppDoubleStringAttribute(IPP_TAG t, const char *n, const char *s1, const char *s2)
397 : IppNamedAttribute(t, n), text1(s1 ? s1 : ""), text2(s2 ? s2 : "")
398 {
399 }
400 
length() const401 int IppDoubleStringAttribute::length() const
402 {
403 	return IppNamedAttribute::length() + 2 + text1.length() + 2  + text2.length();
404 }
405 
input(istream & is)406 istream &IppDoubleStringAttribute::input(istream &is)
407 {
408 	IppNamedAttribute::input(is);
409 
410 	short len = readLength(is);
411 
412 	if (0 < len) {
413 		char *buffer = new char[len + 1];
414 		is.read(buffer, len);
415 		buffer[len] = '\0';
416 		text1 = buffer;
417 		delete [] buffer;
418 	}
419 
420 	len = readLength(is);
421 
422 	if (0 < len) {
423 		char *buffer = new char[len + 1];
424 		is.read(buffer, len);
425 		buffer[len] = '\0';
426 		text2 = buffer;
427 		delete [] buffer;
428 	}
429 
430 	return is;
431 }
432 
output(ostream & os) const433 ostream &IppDoubleStringAttribute::output(ostream &os) const
434 {
435 	IppNamedAttribute::output(os);
436 
437 	writeLength(os, text1.length());
438 	os << text1;
439 
440 	writeLength(os, text2.length());
441 	os << text2;
442 
443 	return os;
444 }
445 
print(ostream & os) const446 ostream &IppDoubleStringAttribute::print(ostream &os) const
447 {
448 	IppNamedAttribute::print(os);
449 	os << '\t' << "Value1: " << text1 << '\n';
450 	os << '\t' << "Value2: " << text2 << '\n';
451 	return os;
452 }
453 
454 /*----------------------------------------------------------------------*/
455 
IppResolutionAttribute(IPP_TAG t)456 IppResolutionAttribute::IppResolutionAttribute(IPP_TAG t)
457 	: IppNamedAttribute(t), xres(0), yres(0), resolution_units((IPP_RESOLUTION_UNITS)0)
458 {
459 }
460 
IppResolutionAttribute(IPP_TAG t,const char * n,int x,int y,IPP_RESOLUTION_UNITS u)461 IppResolutionAttribute::IppResolutionAttribute(IPP_TAG t, const char *n, int x, int y, IPP_RESOLUTION_UNITS u)
462 	: IppNamedAttribute(t, n), xres(x), yres(y), resolution_units(u)
463 {
464 }
465 
length() const466 int IppResolutionAttribute::length() const
467 {
468 	return IppNamedAttribute::length() + 2 + 4 + 2 + 4 + 2 + 1;
469 }
470 
input(istream & is)471 istream &IppResolutionAttribute::input(istream &is)
472 {
473 	IppNamedAttribute::input(is);
474 
475 	short len = readLength(is);
476 
477 	if (0 < len && len <= 4) {
478 		is.read((char *)&xres, sizeof(xres));
479 		xres = ntohl(xres);
480 	} else {
481 		is.seekg(len, ios::cur);
482 	}
483 
484 	len = readLength(is);
485 
486 	if (0 < len && len <= 4) {
487 		is.read((char *)&yres, sizeof(yres));
488 		yres = ntohl(yres);
489 	} else {
490 		is.seekg(len, ios::cur);
491 	}
492 
493 	len = readLength(is);
494 
495 	if (len == 1) {
496 		char c;
497 		is.read((char *)&c, sizeof(c));
498 		resolution_units = (IPP_RESOLUTION_UNITS)c;
499 	} else {
500 		is.seekg(len, ios::cur);
501 	}
502 
503 	return is;
504 }
505 
output(ostream & os) const506 ostream &IppResolutionAttribute::output(ostream &os) const
507 {
508 	IppNamedAttribute::output(os);
509 
510 	writeLength(os, 4);
511 	unsigned long val = htonl(xres);
512 	os.write((char *)&val, sizeof(val));
513 
514 	writeLength(os, 4);
515 	val = htonl(yres);
516 	os.write((char *)&val, sizeof(val));
517 
518 	writeLength(os, 1);
519 	unsigned char c = (unsigned char)resolution_units;
520 	os.write((char *)&c, sizeof(c));
521 
522 	return os;
523 }
524 
print(ostream & os) const525 ostream &IppResolutionAttribute::print(ostream &os) const
526 {
527 	IppNamedAttribute::print(os);
528 	os << '\t' << "Value(xres): " << dec << xres << '\n';
529 	os << '\t' << "Value(yres): " << dec << yres << '\n';
530 	os << '\t' << "Value(unit): " << dec << resolution_units << '\n';
531 	return os;
532 }
533 
534 /*----------------------------------------------------------------------*/
535 
IppRangeOfIntegerAttribute(IPP_TAG t)536 IppRangeOfIntegerAttribute::IppRangeOfIntegerAttribute(IPP_TAG t)
537 	: IppNamedAttribute(t), lower(0), upper(0)
538 {
539 }
540 
IppRangeOfIntegerAttribute(IPP_TAG t,const char * n,int l,int u)541 IppRangeOfIntegerAttribute::IppRangeOfIntegerAttribute(IPP_TAG t, const char *n, int l, int u)
542 	: IppNamedAttribute(t, n), lower(l), upper(u)
543 {
544 }
545 
length() const546 int IppRangeOfIntegerAttribute::length() const
547 {
548 	return IppNamedAttribute::length() + 2 + 4 + 2 + 4;
549 }
550 
input(istream & is)551 istream &IppRangeOfIntegerAttribute::input(istream &is)
552 {
553 	IppNamedAttribute::input(is);
554 
555 	short len = readLength(is);
556 
557 	if (0 < len && len <= 4) {
558 		is.read((char *)&lower, sizeof(lower));
559 		lower = ntohl(lower);
560 	} else {
561 		is.seekg(len, ios::cur);
562 	}
563 
564 	len = readLength(is);
565 
566 	if (0 < len && len <= 4) {
567 		is.read((char *)&upper, sizeof(upper));
568 		upper = ntohl(upper);
569 	} else {
570 		is.seekg(len, ios::cur);
571 	}
572 
573 	return is;
574 }
575 
output(ostream & os) const576 ostream &IppRangeOfIntegerAttribute::output(ostream &os) const
577 {
578 	IppNamedAttribute::output(os);
579 
580 	writeLength(os, 4);
581 	unsigned long val = htonl(lower);
582 	os.write((char *)&val, sizeof(val));
583 
584 	writeLength(os, 4);
585 	val = htonl(upper);
586 	os.write((char *)&val, sizeof(val));
587 
588 	return os;
589 }
590 
print(ostream & os) const591 ostream &IppRangeOfIntegerAttribute::print(ostream &os) const
592 {
593 	IppNamedAttribute::print(os);
594 	os << '\t' << "Value(lower): " << dec << lower << '\n';
595 	os << '\t' << "Value(upper): " << dec << upper << '\n';
596 	return os;
597 }
598 
599 /*----------------------------------------------------------------------*/
600 
IppContent()601 IppContent::IppContent()
602 {
603 	version      = 0x0100;
604 	operation_id = IPP_GET_PRINTER_ATTRIBUTES;
605 	request_id   = 0x00000001;
606 
607 	is = NULL;
608 	size = -1;
609 }
610 
~IppContent()611 IppContent::~IppContent()
612 {
613 	for (list<IppAttribute *>::const_iterator it = attrs.begin(); it != attrs.end(); it++) {
614 		delete (*it);
615 	}
616 }
617 
getVersion() const618 unsigned short IppContent::getVersion() const
619 {
620 	return version;
621 }
622 
setVersion(unsigned short i)623 void IppContent::setVersion(unsigned short i)
624 {
625 	version = i;
626 }
627 
628 
getOperationId() const629 IPP_OPERATION_ID IppContent::getOperationId() const
630 {
631 	return (IPP_OPERATION_ID)operation_id;
632 }
633 
setOperationId(IPP_OPERATION_ID i)634 void IppContent::setOperationId(IPP_OPERATION_ID i)
635 {
636 	operation_id = i;
637 }
638 
getStatusCode() const639 IPP_STATUS_CODE IppContent::getStatusCode() const
640 {
641 	return (IPP_STATUS_CODE)operation_id;
642 }
643 
getRequestId() const644 unsigned long IppContent::getRequestId() const
645 {
646 	return request_id;
647 }
648 
setRequestId(unsigned long i)649 void IppContent::setRequestId(unsigned long i)
650 {
651 	request_id = i;
652 }
653 
input(istream & is)654 istream &IppContent::input(istream &is)
655 {
656 	if (!is.read((char *)&version, sizeof(version))) {
657 		return is;
658 	}
659 
660 	version = ntohs(version);
661 
662 	if (!is.read((char *)&operation_id, sizeof(operation_id))) {
663 		return is;
664 	}
665 
666 	operation_id = ntohs(operation_id);
667 
668 	if (!is.read((char *)&request_id, sizeof(request_id))) {
669 		return is;
670 	}
671 
672 	request_id = ntohl(request_id);
673 	char tag;
674 
675 	while (1) {
676 
677 		if (!is.read((char *)&tag, sizeof(tag))) {
678 			return is;
679 		}
680 
681 		if (tag <= 0x0F) {	// delimiter
682 
683 //			case IPP_OPERATION_ATTRIBUTES_TAG:
684 //			case IPP_JOB_ATTRIBUTES_TAG:
685 //			case IPP_END_OF_ATTRIBUTES_TAG:
686 //			case IPP_PRINTER_ATTRIBUTES_TAG:
687 //			case IPP_UNSUPPORTED_ATTRIBUTES_TAG:
688 
689 			attrs.push_back(new IppAttribute((IPP_TAG)tag));
690 			if (tag == IPP_END_OF_ATTRIBUTES_TAG) {
691 				break;
692 			}
693 
694 		} else if (tag <= 0x1F) {
695 
696 			IppNoValueAttribute *attr = new IppNoValueAttribute((IPP_TAG)tag);
697 			is >> *attr;
698 			attrs.push_back(attr);
699 
700 		} else if (tag <= 0x2F) {	// integer values
701 
702 			switch (tag) {
703 			case IPP_INTEGER:
704 			case IPP_ENUM:
705 				{
706 					IppIntegerAttribute *attr = new IppIntegerAttribute((IPP_TAG)tag);
707 					is >> *attr;
708 					attrs.push_back(attr);
709 				}
710 				break;
711 			case IPP_BOOLEAN:
712 				{
713 					IppBooleanAttribute *attr = new IppBooleanAttribute((IPP_TAG)tag);
714 					is >> *attr;
715 					attrs.push_back(attr);
716 				}
717 				break;
718 			default:
719 				{
720 					short len = readLength(is);
721 					is.seekg(len, ios::cur);
722 					len = readLength(is);
723 					is.seekg(len, ios::cur);
724 				}
725 				break;
726 			}
727 
728 		} else if (tag <= 0x3F) {	// octetString values
729 
730 			switch (tag) {
731 			case IPP_STRING:
732 				{
733 					IppStringAttribute *attr = new IppStringAttribute((IPP_TAG)tag);
734 					is >> *attr;
735 					attrs.push_back(attr);
736 				}
737 				break;
738 			case IPP_DATETIME:
739 				{
740 					IppDatetimeAttribute *attr = new IppDatetimeAttribute((IPP_TAG)tag);
741 					is >> *attr;
742 					attrs.push_back(attr);
743 				}
744 				break;
745 			case IPP_RESOLUTION:
746 				{
747 					IppResolutionAttribute *attr = new IppResolutionAttribute((IPP_TAG)tag);
748 					is >> *attr;
749 					attrs.push_back(attr);
750 				}
751 				break;
752 			case IPP_RANGE_OF_INTEGER:
753 				{
754 					IppRangeOfIntegerAttribute *attr = new IppRangeOfIntegerAttribute((IPP_TAG)tag);
755 					is >> *attr;
756 					attrs.push_back(attr);
757 				}
758 				break;
759 			case IPP_TEXT_WITH_LANGUAGE:
760 			case IPP_NAME_WITH_LANGUAGE:
761 				{
762 					IppDoubleStringAttribute *attr = new IppDoubleStringAttribute((IPP_TAG)tag);
763 					is >> *attr;
764 					attrs.push_back(attr);
765 				}
766 				break;
767 			default:
768 				{
769 					short len = readLength(is);
770 					is.seekg(len, ios::cur);
771 					len = readLength(is);
772 					is.seekg(len, ios::cur);
773 				}
774 				break;
775 			}
776 
777 		} else if (tag <= 0x5F) {	// character-string values
778 
779 //			case IPP_TEXT_WITHOUT_LANGUAGE:
780 //			case IPP_NAME_WITHOUT_LANGUAGE:
781 //			case IPP_KEYWORD:
782 //			case IPP_URI:
783 //			case IPP_URISCHEME:
784 //			case IPP_CHARSET:
785 //			case IPP_NATURAL_LANGUAGE:
786 //			case IPP_MIME_MEDIA_TYPE:
787 
788 			IppStringAttribute *attr = new IppStringAttribute((IPP_TAG)tag);
789 			is >> *attr;
790 			attrs.push_back(attr);
791 		}
792 	}
793 	return is;
794 }
795 
output(ostream & os) const796 ostream &IppContent::output(ostream &os) const
797 {
798 	unsigned short ns_version = htons(version);						// version-number
799 	os.write((char *)&ns_version, sizeof(ns_version));				// version-number
800 
801 	unsigned short ns_operation_id = htons(operation_id);			// operation-id
802 	os.write((char *)&ns_operation_id, sizeof(ns_operation_id));	// operation-id
803 
804 	unsigned long ns_request_id = htonl(request_id);				// request-id
805 	os.write((char *)&ns_request_id, sizeof(ns_request_id));		// request-id
806 
807 	for (list<IppAttribute *>::const_iterator it = attrs.begin(); it != attrs.end(); it++) {
808 		os << *(*it);
809 	}
810 
811 	ifstream ifs;
812 	istream *iss = is;
813 	if (iss == NULL) {
814 		if (!file_path.empty()) {
815 			ifs.open(file_path.c_str(), ios::in | ios::binary);
816 			iss = &ifs;
817 		}
818 	}
819 	if (iss && iss->good()) {
820 		if (iss->good()) {
821 			char c;
822 			while (iss->get(c)) {
823 				os.put(c);
824 			}
825 		}
826 	}
827 
828 	return os;
829 }
830 
setDelimiter(IPP_TAG tag)831 void IppContent::setDelimiter(IPP_TAG tag)
832 {
833 	attrs.push_back(new IppAttribute(tag));
834 }
835 
setInteger(const char * name,int value)836 void IppContent::setInteger(const char *name, int value)
837 {
838 	attrs.push_back(new IppIntegerAttribute(IPP_INTEGER, name, value));
839 }
840 
setBoolean(const char * name,bool value)841 void IppContent::setBoolean(const char *name, bool value)
842 {
843 	attrs.push_back(new IppBooleanAttribute(IPP_BOOLEAN, name, value));
844 }
845 
setString(const char * name,const char * value)846 void IppContent::setString(const char *name, const char *value)
847 {
848 	attrs.push_back(new IppStringAttribute(IPP_STRING, name, value));
849 }
850 
setDateTime(const char * name,const DATETIME * dt)851 void IppContent::setDateTime(const char *name, const DATETIME *dt)
852 {
853 	attrs.push_back(new IppDatetimeAttribute(IPP_DATETIME, name, dt));
854 }
855 
setResolution(const char * name,int x,int y,IPP_RESOLUTION_UNITS u)856 void IppContent::setResolution(const char *name, int x, int y, IPP_RESOLUTION_UNITS u)
857 {
858 	attrs.push_back(new IppResolutionAttribute(IPP_RESOLUTION, name, x, y, u));
859 }
860 
setRangeOfInteger(const char * name,int lower,int upper)861 void IppContent::setRangeOfInteger(const char *name, int lower, int upper)
862 {
863 	attrs.push_back(new IppRangeOfIntegerAttribute(IPP_RANGE_OF_INTEGER, name, lower, upper));
864 }
865 
setTextWithLanguage(const char * name,const char * s1,const char * s2)866 void IppContent::setTextWithLanguage(const char *name, const char *s1, const char *s2)
867 {
868 	attrs.push_back(new IppDoubleStringAttribute(IPP_TEXT_WITH_LANGUAGE, name, s1, s2));
869 }
870 
setNameWithLanguage(const char * name,const char * s1,const char * s2)871 void IppContent::setNameWithLanguage(const char *name, const char *s1, const char *s2)
872 {
873 	attrs.push_back(new IppDoubleStringAttribute(IPP_NAME_WITH_LANGUAGE, name, s1, s2));
874 }
875 
setTextWithoutLanguage(const char * name,const char * value)876 void IppContent::setTextWithoutLanguage(const char *name, const char *value)
877 {
878 	attrs.push_back(new IppStringAttribute(IPP_TEXT_WITHOUT_LANGUAGE, name, value));
879 }
880 
setNameWithoutLanguage(const char * name,const char * value)881 void IppContent::setNameWithoutLanguage(const char *name, const char *value)
882 {
883 	attrs.push_back(new IppStringAttribute(IPP_NAME_WITHOUT_LANGUAGE, name, value));
884 }
885 
setKeyword(const char * name,const char * value)886 void IppContent::setKeyword(const char *name, const char *value)
887 {
888 	attrs.push_back(new IppStringAttribute(IPP_KEYWORD, name, value));
889 }
890 
setURI(const char * name,const char * value)891 void IppContent::setURI(const char *name, const char *value)
892 {
893 	attrs.push_back(new IppStringAttribute(IPP_URI, name, value));
894 }
895 
setURIScheme(const char * name,const char * value)896 void IppContent::setURIScheme(const char *name, const char *value)
897 {
898 	attrs.push_back(new IppStringAttribute(IPP_URISCHEME, name, value));
899 }
900 
setCharset(const char * name,const char * value)901 void IppContent::setCharset(const char *name, const char *value)
902 {
903 	attrs.push_back(new IppStringAttribute(IPP_CHARSET, name, value));
904 }
905 
setNaturalLanguage(const char * name,const char * value)906 void IppContent::setNaturalLanguage(const char *name, const char *value)
907 {
908 	attrs.push_back(new IppStringAttribute(IPP_NATURAL_LANGUAGE, name, value));
909 }
910 
setMimeMediaType(const char * name,const char * value)911 void IppContent::setMimeMediaType(const char *name, const char *value)
912 {
913 	attrs.push_back(new IppStringAttribute(IPP_MIME_MEDIA_TYPE, name, value));
914 }
915 
length() const916 int IppContent::length() const
917 {
918 	int length = 8;	// sizeof(version-number + operation-id + request-id)
919 
920 	for (list<IppAttribute *>::const_iterator it = attrs.begin(); it != attrs.end(); it++) {
921 		length += (*it)->length();
922 	}
923 
924 	ifstream ifs;
925 	istream *iss = is;
926 	if (iss == NULL) {
927 		if (!file_path.empty()) {
928 			ifs.open(file_path.c_str(), ios::in | ios::binary);
929 			iss = &ifs;
930 		}
931 	}
932 	if (iss && iss->good()) {
933 		int fsize = size;
934 		if (fsize < 0) {
935 			streampos pos = iss->tellg();
936 			iss->seekg(0, ios::end);
937 			fsize = iss->tellg();
938 			iss->seekg(pos, ios::beg);
939 		}
940 		if (fsize > 0) {
941 			length += fsize;
942 		}
943 	}
944 
945 	return length;
946 }
947 
setRawData(const char * file,int n)948 void IppContent::setRawData(const char *file, int n)
949 {
950 	file_path = file;
951 	size = n;
952 }
953 
setRawData(istream & ifs,int n)954 void IppContent::setRawData(istream &ifs, int n)
955 {
956 	is = &ifs;
957 	size = n;
958 }
959 
print(ostream & os) const960 ostream &IppContent::print(ostream &os) const
961 {
962 	os << "version:      " << hex << version << '\n';
963 	os << "operation_id: " << hex << operation_id << '\n';
964 	os << "request_id:   " << hex << request_id << '\n';
965 
966 	for (list<IppAttribute *>::const_iterator it = attrs.begin(); it != attrs.end(); it++) {
967 		(*it)->print(os);
968 	}
969 
970 	return os;
971 }
972 
fail() const973 bool IppContent::fail() const
974 {
975 	return !good();
976 }
977 
good() const978 bool IppContent::good() const
979 {
980 	return /*operation_id >= IPP_SUCCESSFUL_OK_S &&*/ operation_id <= IPP_SUCCESSFUL_OK_E;
981 }
982 
operator !() const983 bool IppContent::operator !() const
984 {
985 	return fail();
986 }
987 
getStatusMessage() const988 const char *IppContent::getStatusMessage() const
989 {
990 	if (good()) {
991 		switch (operation_id) {
992 		case IPP_SUCCESSFUL_OK:
993 			return "successful-ok";
994 		case IPP_SUCCESSFUL_OK_IGNORED_OR_SUBSTITUTED_ATTRIBUTES:
995 			return "successful-ok-ignored-or-substituted-attributes";
996 		case IPP_SUCCESSFUL_OK_CONFLICTING_ATTRIBUTES:
997 			return "successful-ok-conflicting-attributes";
998 		default:
999 			return "successful-ok-???";
1000 		}
1001 	} else if (IPP_CLIENT_ERROR_S <= operation_id && operation_id <= IPP_CLIENT_ERROR_E) {
1002 		switch (operation_id) {
1003 		case IPP_CLIENT_ERROR_BAD_REQUEST:
1004 			return "client-error-bad-request";
1005 		case IPP_CLIENT_ERROR_FORBIDDEN:
1006 			return "client-error-forbidden";
1007 		case IPP_CLIENT_ERROR_NOT_AUTHENTICATED:
1008 			return "client-error-not-authenticated";
1009 		case IPP_CLIENT_ERROR_NOT_AUTHORIZED:
1010 			return "client-error-not-authorized";
1011 		case IPP_CLIENT_ERROR_NOT_POSSIBLE:
1012 			return "client-error-not-possible";
1013 		case IPP_CLIENT_ERROR_TIMEOUT:
1014 			return "client-error-timeout";
1015 		case IPP_CLIENT_ERROR_NOT_FOUND:
1016 			return "client-error-not-found";
1017 		case IPP_CLIENT_ERROR_GONE:
1018 			return "client-error-gone";
1019 		case IPP_CLIENT_ERROR_REQUEST_ENTITY_TOO_LARGE:
1020 			return "client-error-request-entity-too-large";
1021 		case IPP_CLIENT_ERROR_REQUEST_VALUE_TOO_LONG:
1022 			return "client-error-request-value-too-long";
1023 		case IPP_CLIENT_ERROR_DOCUMENT_FORMAT_NOT_SUPPORTED:
1024 			return "client-error-document-format-not-supported";
1025 		case IPP_CLIENT_ERROR_ATTRIBUTES_OR_VALUES_NOT_SUPPORTED:
1026 			return "client-error-attributes-or-values-not-supported";
1027 		case IPP_CLIENT_ERROR_URI_SCHEME_NOT_SUPPORTED:
1028 			return "client-error-uri-scheme-not-supported";
1029 		case IPP_CLIENT_ERROR_CHARSET_NOT_SUPPORTED:
1030 			return "client-error-charset-not-supported";
1031 		case IPP_CLIENT_ERROR_CONFLICTING_ATTRIBUTES:
1032 			return "client-error-conflicting-attributes";
1033 		default:
1034 			return "client-error-???";
1035 		}
1036 	} else if (IPP_SERVER_ERROR_S <= operation_id && operation_id <= IPP_SERVER_ERROR_E) {
1037 		switch (operation_id) {
1038 		case IPP_SERVER_ERROR_INTERNAL_ERROR:
1039 			return "server-error-internal-error";
1040 		case IPP_SERVER_ERROR_OPERATION_NOT_SUPPORTED:
1041 			return "server-error-operation-not-supported";
1042 		case IPP_SERVER_ERROR_SERVICE_UNAVAILABLE:
1043 			return "server-error-service-unavailable";
1044 		case IPP_SERVER_ERROR_VERSION_NOT_SUPPORTED:
1045 			return "server-error-version-not-supported";
1046 		case IPP_SERVER_ERROR_DEVICE_ERROR:
1047 			return "server-error-device-error";
1048 		case IPP_SERVER_ERROR_TEMPORARY_ERROR:
1049 			return "server-error-temporary-error";
1050 		case IPP_SERVER_ERROR_NOT_ACCEPTING_JOBS:
1051 			return "server-error-not-accepting-jobs";
1052 		case IPP_SERVER_ERROR_BUSY:
1053 			return "server-error-busy";
1054 		case IPP_SERVER_ERROR_JOB_CANCELED:
1055 			return "server-error-job-canceled";
1056 		default:
1057 			return "server-error-???";
1058 		}
1059 	} else {
1060 		return "unknown error.";
1061 	}
1062 }
1063