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