ipprequest.cpp
00001 /* 00002 * This file is part of the KDE libraries 00003 * Copyright (c) 2001 Michael Goffioul <tdeprint@swing.be> 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Library General Public 00007 * License version 2 as published by the Free Software Foundation. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Library General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Library General Public License 00015 * along with this library; see the file COPYING.LIB. If not, write to 00016 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 * Boston, MA 02110-1301, USA. 00018 **/ 00019 00020 #include "ipprequest.h" 00021 #include "cupsinfos.h" 00022 00023 #include <stdlib.h> 00024 #include <string> 00025 #include <cups/language.h> 00026 #include <kdebug.h> 00027 #include <tdeglobal.h> 00028 #include <tdelocale.h> 00029 #include <tqdatetime.h> 00030 #include <tqregexp.h> 00031 #include <cups/cups.h> 00032 00033 #ifdef HAVE_CONFIG_H 00034 #include <config.h> 00035 #endif 00036 00037 #ifdef HAVE_CUPS_NO_PWD_CACHE 00038 #include <tqcstring.h> 00039 static TQCString cups_authstring = ""; 00040 #endif 00041 00042 void dumpRequest(ipp_t *req, bool answer = false, const TQString& s = TQString::null) 00043 { 00044 kdDebug(500) << "==========" << endl; 00045 if (s.isEmpty()) 00046 kdDebug(500) << (answer ? "Answer" : "Request") << endl; 00047 else 00048 kdDebug(500) << s << endl; 00049 kdDebug(500) << "==========" << endl; 00050 if (!req) 00051 { 00052 kdDebug(500) << "Null request" << endl; 00053 return; 00054 } 00055 #ifdef HAVE_CUPS_1_6 00056 kdDebug(500) << "State = 0x" << TQString::number(ippGetState(req), 16) << endl; 00057 kdDebug(500) << "ID = 0x" << TQString::number(ippGetRequestId(req), 16) << endl; 00058 if (answer) 00059 { 00060 kdDebug(500) << "Status = 0x" << TQString::number(ippGetStatusCode(req), 16) << endl; 00061 kdDebug(500) << "Status message = " << ippErrorString(ippGetStatusCode(req)) << endl; 00062 } 00063 else 00064 kdDebug(500) << "Operation = 0x" << TQString::number(ippGetOperation(req), 16) << endl; 00065 int minorVersion; 00066 int majorVersion = ippGetVersion(req, &minorVersion); 00067 kdDebug(500) << "Version = " << (int)(majorVersion) << "." << (int)(minorVersion) << endl; 00068 kdDebug(500) << endl; 00069 00070 ipp_attribute_t *attr = ippFirstAttribute(req); 00071 while (attr) 00072 { 00073 TQString s = TQString::fromLatin1("%1 (0x%2) = ").arg(ippGetName(attr)).arg(ippGetValueTag(attr), 0, 16); 00074 for (int i=0;i<ippGetCount(attr);i++) 00075 { 00076 switch (ippGetValueTag(attr)) 00077 { 00078 case IPP_TAG_INTEGER: 00079 case IPP_TAG_ENUM: 00080 s += ("0x"+TQString::number(ippGetInteger(attr, i), 16)); 00081 break; 00082 case IPP_TAG_BOOLEAN: 00083 s += (ippGetBoolean(attr, i) ? "true" : "false"); 00084 break; 00085 case IPP_TAG_STRING: 00086 case IPP_TAG_TEXT: 00087 case IPP_TAG_NAME: 00088 case IPP_TAG_KEYWORD: 00089 case IPP_TAG_URI: 00090 case IPP_TAG_MIMETYPE: 00091 case IPP_TAG_NAMELANG: 00092 case IPP_TAG_TEXTLANG: 00093 case IPP_TAG_CHARSET: 00094 case IPP_TAG_LANGUAGE: 00095 s += ippGetString(attr, i, NULL); 00096 break; 00097 default: 00098 break; 00099 } 00100 if (i != (ippGetCount(attr)-1)) 00101 s += ", "; 00102 } 00103 kdDebug(500) << s << endl; 00104 attr = ippNextAttribute(req); 00105 } 00106 #else // HAVE_CUPS_1_6 00107 kdDebug(500) << "State = 0x" << TQString::number(req->state, 16) << endl; 00108 kdDebug(500) << "ID = 0x" << TQString::number(req->request.status.request_id, 16) << endl; 00109 if (answer) 00110 { 00111 kdDebug(500) << "Status = 0x" << TQString::number(req->request.status.status_code, 16) << endl; 00112 kdDebug(500) << "Status message = " << ippErrorString(req->request.status.status_code) << endl; 00113 } 00114 else 00115 kdDebug(500) << "Operation = 0x" << TQString::number(req->request.op.operation_id, 16) << endl; 00116 kdDebug(500) << "Version = " << (int)(req->request.status.version[0]) << "." << (int)(req->request.status.version[1]) << endl; 00117 kdDebug(500) << endl; 00118 00119 ipp_attribute_t *attr = req->attrs; 00120 while (attr) 00121 { 00122 TQString s = TQString::fromLatin1("%1 (0x%2) = ").arg(attr->name).arg(attr->value_tag, 0, 16); 00123 for (int i=0;i<attr->num_values;i++) 00124 { 00125 switch (attr->value_tag) 00126 { 00127 case IPP_TAG_INTEGER: 00128 case IPP_TAG_ENUM: 00129 s += ("0x"+TQString::number(attr->values[i].integer, 16)); 00130 break; 00131 case IPP_TAG_BOOLEAN: 00132 s += (attr->values[i].boolean ? "true" : "false"); 00133 break; 00134 case IPP_TAG_STRING: 00135 case IPP_TAG_TEXT: 00136 case IPP_TAG_NAME: 00137 case IPP_TAG_KEYWORD: 00138 case IPP_TAG_URI: 00139 case IPP_TAG_MIMETYPE: 00140 case IPP_TAG_NAMELANG: 00141 case IPP_TAG_TEXTLANG: 00142 case IPP_TAG_CHARSET: 00143 case IPP_TAG_LANGUAGE: 00144 s += attr->values[i].string.text; 00145 break; 00146 default: 00147 break; 00148 } 00149 if (i != (attr->num_values-1)) 00150 s += ", "; 00151 } 00152 kdDebug(500) << s << endl; 00153 attr = attr->next; 00154 } 00155 #endif // HAVE_CUPS_1_6 00156 } 00157 00158 TQString errorString(int status) 00159 { 00160 TQString str; 00161 switch (status) 00162 { 00163 case IPP_FORBIDDEN: 00164 str = i18n("You don't have access to the requested resource."); 00165 break; 00166 case IPP_NOT_AUTHORIZED: 00167 str = i18n("You are not authorized to access the requested resource."); 00168 break; 00169 case IPP_NOT_POSSIBLE: 00170 str = i18n("The requested operation cannot be completed."); 00171 break; 00172 case IPP_SERVICE_UNAVAILABLE: 00173 str = i18n("The requested service is currently unavailable."); 00174 break; 00175 case IPP_NOT_ACCEPTING: 00176 str = i18n("The target printer is not accepting print jobs."); 00177 break; 00178 default: 00179 str = TQString::fromLocal8Bit(ippErrorString((ipp_status_t)status)); 00180 break; 00181 } 00182 return str; 00183 } 00184 00185 //************************************************************************************* 00186 00187 IppRequest::IppRequest() 00188 { 00189 request_ = 0; 00190 port_ = -1; 00191 host_ = TQString(); 00192 dump_ = 0; 00193 init(); 00194 } 00195 00196 IppRequest::~IppRequest() 00197 { 00198 ippDelete(request_); 00199 } 00200 00201 void IppRequest::init() 00202 { 00203 connect_ = true; 00204 00205 if (request_) 00206 { 00207 ippDelete(request_); 00208 request_ = 0; 00209 } 00210 request_ = ippNew(); 00211 //kdDebug(500) << "tdeprint: IPP request, lang=" << TDEGlobal::locale()->language() << endl; 00212 TQCString langstr = TDEGlobal::locale()->language().latin1(); 00213 cups_lang_t* lang = cupsLangGet(langstr.data()); 00214 // default charset to UTF-8 (ugly hack) 00215 lang->encoding = CUPS_UTF8; 00216 ippAddString(request_, IPP_TAG_OPERATION, IPP_TAG_CHARSET, "attributes-charset", NULL, cupsLangEncoding(lang)); 00217 ippAddString(request_, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, lang->language); 00218 cupsLangFree(lang); 00219 } 00220 00221 void IppRequest::addString_p(int group, int type, const TQString& name, const TQString& value) 00222 { 00223 if (!name.isEmpty()) 00224 ippAddString(request_,(ipp_tag_t)group,(ipp_tag_t)type,name.latin1(),NULL,(value.isEmpty() ? "" : value.local8Bit().data())); 00225 } 00226 00227 void IppRequest::addStringList_p(int group, int type, const TQString& name, const TQStringList& values) 00228 { 00229 if (!name.isEmpty()) 00230 { 00231 //> Values buffer and references offset prepare 00232 const char *vlsRefs[values.count()]; 00233 std::string vlsBuf; 00234 for(unsigned i_vl = 0; i_vl < values.count(); i_vl++) 00235 { 00236 vlsRefs[i_vl] = (const char*)vlsBuf.size(); 00237 vlsBuf += values[i_vl].local8Bit(); 00238 vlsBuf += (char)0; 00239 } 00240 //> References update to pointers 00241 for(unsigned i_vl = 0; i_vl < values.count(); i_vl++) 00242 vlsRefs[i_vl] = vlsBuf.data()+(intptr_t)vlsRefs[i_vl]; 00243 ippAddStrings(request_,(ipp_tag_t)group,(ipp_tag_t)type,name.latin1(),(int)(values.count()),NULL,(const char**)&vlsRefs); 00244 } 00245 } 00246 00247 void IppRequest::addInteger_p(int group, int type, const TQString& name, int value) 00248 { 00249 if (!name.isEmpty()) ippAddInteger(request_,(ipp_tag_t)group,(ipp_tag_t)type,name.latin1(),value); 00250 } 00251 00252 void IppRequest::addIntegerList_p(int group, int type, const TQString& name, const TQValueList<int>& values) 00253 { 00254 if (!name.isEmpty()) 00255 { 00256 ipp_attribute_t *attr = ippAddIntegers(request_,(ipp_tag_t)group,(ipp_tag_t)type,name.latin1(),(int)(values.count()),NULL); 00257 int i(0); 00258 for (TQValueList<int>::ConstIterator it=values.begin(); it != values.end(); ++it, i++) 00259 #ifdef HAVE_CUPS_1_6 00260 ippSetInteger(request_, &attr, i, *it); 00261 #else // HAVE_CUPS_1_6 00262 attr->values[i].integer = *it; 00263 #endif // HAVE_CUPS_1_6 00264 } 00265 } 00266 00267 void IppRequest::addBoolean(int group, const TQString& name, bool value) 00268 { 00269 if (!name.isEmpty()) ippAddBoolean(request_,(ipp_tag_t)group,name.latin1(),(char)value); 00270 } 00271 00272 void IppRequest::addBoolean(int group, const TQString& name, const TQValueList<bool>& values) 00273 { 00274 if (!name.isEmpty()) 00275 { 00276 ipp_attribute_t *attr = ippAddBooleans(request_,(ipp_tag_t)group,name.latin1(),(int)(values.count()),NULL); 00277 int i(0); 00278 for (TQValueList<bool>::ConstIterator it=values.begin(); it != values.end(); ++it, i++) 00279 #ifdef HAVE_CUPS_1_6 00280 ippSetBoolean(request_, &attr, i, (char)(*it)); 00281 #else // HAVE_CUPS_1_6 00282 attr->values[i].boolean = (char)(*it); 00283 #endif // HAVE_CUPS_1_6 00284 } 00285 } 00286 00287 void IppRequest::setOperation(int op) 00288 { 00289 #ifdef HAVE_CUPS_1_6 00290 ippSetOperation(request_, (ipp_op_t)op); 00291 ippSetRequestId(request_, 1); // 0 is not RFC-compliant, should be at least 1 00292 #else // HAVE_CUPS_1_6 00293 request_->request.op.operation_id = (ipp_op_t)op; 00294 request_->request.op.request_id = 1; // 0 is not RFC-compliant, should be at least 1 00295 #endif // HAVE_CUPS_1_6 00296 } 00297 00298 int IppRequest::status() 00299 { 00300 #ifdef HAVE_CUPS_1_6 00301 return (request_ ? ippGetStatusCode(request_) : (connect_ ? cupsLastError() : -2)); 00302 #else // HAVE_CUPS_1_6 00303 return (request_ ? request_->request.status.status_code : (connect_ ? cupsLastError() : -2)); 00304 #endif // HAVE_CUPS_1_6 00305 } 00306 00307 TQString IppRequest::statusMessage() 00308 { 00309 TQString msg; 00310 switch (status()) 00311 { 00312 case -2: 00313 msg = i18n("Connection to CUPS server failed. Check that the CUPS server is correctly installed and running."); 00314 break; 00315 case -1: 00316 msg = i18n("The IPP request failed for an unknown reason."); 00317 break; 00318 default: 00319 msg = errorString(status()); 00320 break; 00321 } 00322 return msg; 00323 } 00324 00325 bool IppRequest::integerValue_p(const TQString& name, int& value, int type) 00326 { 00327 if (!request_ || name.isEmpty()) return false; 00328 ipp_attribute_t *attr = ippFindAttribute(request_, name.latin1(), (ipp_tag_t)type); 00329 if (attr) 00330 { 00331 #ifdef HAVE_CUPS_1_6 00332 value = ippGetInteger(attr, 0); 00333 #else // HAVE_CUPS_1_6 00334 value = attr->values[0].integer; 00335 #endif // HAVE_CUPS_1_6 00336 return true; 00337 } 00338 else return false; 00339 } 00340 00341 bool IppRequest::stringValue_p(const TQString& name, TQString& value, int type) 00342 { 00343 if (!request_ || name.isEmpty()) return false; 00344 ipp_attribute_t *attr = ippFindAttribute(request_, name.latin1(), (ipp_tag_t)type); 00345 if (attr) 00346 { 00347 #ifdef HAVE_CUPS_1_6 00348 value = TQString::fromLocal8Bit(ippGetString(attr, 0, NULL)); 00349 #else // HAVE_CUPS_1_6 00350 value = TQString::fromLocal8Bit(attr->values[0].string.text); 00351 #endif // HAVE_CUPS_1_6 00352 return true; 00353 } 00354 else return false; 00355 } 00356 00357 bool IppRequest::stringListValue_p(const TQString& name, TQStringList& values, int type) 00358 { 00359 if (!request_ || name.isEmpty()) return false; 00360 ipp_attribute_t *attr = ippFindAttribute(request_, name.latin1(), (ipp_tag_t)type); 00361 values.clear(); 00362 if (attr) 00363 { 00364 #ifdef HAVE_CUPS_1_6 00365 for (int i=0;i<ippGetCount(attr);i++) 00366 values.append(TQString::fromLocal8Bit(ippGetString(attr, i, NULL))); 00367 #else // HAVE_CUPS_1_6 00368 for (int i=0;i<attr->num_values;i++) 00369 values.append(TQString::fromLocal8Bit(attr->values[i].string.text)); 00370 #endif // HAVE_CUPS_1_6 00371 return true; 00372 } 00373 else return false; 00374 } 00375 00376 bool IppRequest::boolean(const TQString& name, bool& value) 00377 { 00378 if (!request_ || name.isEmpty()) return false; 00379 ipp_attribute_t *attr = ippFindAttribute(request_, name.latin1(), IPP_TAG_BOOLEAN); 00380 if (attr) 00381 { 00382 #ifdef HAVE_CUPS_1_6 00383 value = (bool)ippGetBoolean(attr, 0); 00384 #else // HAVE_CUPS_1_6 00385 value = (bool)attr->values[0].boolean; 00386 #endif // HAVE_CUPS_1_6 00387 return true; 00388 } 00389 else return false; 00390 } 00391 00392 bool IppRequest::doFileRequest(const TQString& res, const TQString& filename) 00393 { 00394 TQString myHost = host_; 00395 int myPort = port_; 00396 if (myHost.isEmpty()) myHost = CupsInfos::self()->host(); 00397 if (myPort <= 0) myPort = CupsInfos::self()->port(); 00398 http_t *HTTP = httpConnect(myHost.latin1(),myPort); 00399 00400 connect_ = (HTTP != NULL); 00401 00402 if (HTTP == NULL) 00403 { 00404 ippDelete(request_); 00405 request_ = 0; 00406 return false; 00407 } 00408 00409 #ifdef HAVE_CUPS_NO_PWD_CACHE 00410 #if CUPS_VERSION_MAJOR < 1 || (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR < 2) 00411 strncpy( HTTP->authstring, cups_authstring.data(), HTTP_MAX_VALUE ); 00412 #else 00413 httpSetAuthString( HTTP, NULL, cups_authstring.data() ); 00414 #endif 00415 #endif 00416 00417 if (dump_ > 0) 00418 { 00419 dumpRequest(request_, false, "Request to "+myHost+":"+TQString::number(myPort)); 00420 } 00421 00422 request_ = cupsDoFileRequest(HTTP, request_, (res.isEmpty() ? "/" : res.latin1()), (filename.isEmpty() ? NULL : filename.latin1())); 00423 #ifdef HAVE_CUPS_NO_PWD_CACHE 00424 #if CUPS_VERSION_MAJOR < 1 || (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR < 2) 00425 cups_authstring = HTTP->authstring; 00426 #else 00427 cups_authstring = httpGetAuthString( HTTP ); 00428 #endif 00429 #endif 00430 httpClose(HTTP); 00431 00432 if (dump_ > 1) 00433 { 00434 dumpRequest(request_, true); 00435 } 00436 00437 /* No printers found */ 00438 #ifdef HAVE_CUPS_1_6 00439 if ( request_ && ippGetStatusCode(request_) == 0x406 ) 00440 #else // HAVE_CUPS_1_6 00441 if ( request_ && request_->request.status.status_code == 0x406 ) 00442 #endif // HAVE_CUPS_1_6 00443 return true; 00444 00445 #ifdef HAVE_CUPS_1_6 00446 if (!request_ || ippGetState(request_) == IPP_ERROR || (ippGetStatusCode(request_) & 0x0F00)) 00447 #else // HAVE_CUPS_1_6 00448 if (!request_ || request_->state == IPP_ERROR || (request_->request.status.status_code & 0x0F00)) 00449 #endif // HAVE_CUPS_1_6 00450 return false; 00451 00452 00453 return true; 00454 } 00455 00456 bool IppRequest::htmlReport(int group, TQTextStream& output) 00457 { 00458 if (!request_) return false; 00459 // start table 00460 output << "<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">" << endl; 00461 output << "<tr><th bgcolor=\"dark blue\"><font color=\"white\">" << i18n("Attribute") << "</font></th>" << endl; 00462 output << "<th bgcolor=\"dark blue\"><font color=\"white\">" << i18n("Values") << "</font></th></tr>" << endl; 00463 // go to the first attribute of the specified group 00464 #ifdef HAVE_CUPS_1_6 00465 ipp_attribute_t *attr = ippFirstAttribute(request_); 00466 while (attr && ippGetGroupTag(attr) != group) 00467 attr = ippNextAttribute(request_); 00468 #else // HAVE_CUPS_1_6 00469 ipp_attribute_t *attr = request_->attrs; 00470 while (attr && attr->group_tag != group) 00471 attr = attr->next; 00472 #endif // HAVE_CUPS_1_6 00473 // print each attribute 00474 const ipp_uchar_t *d; 00475 TQCString dateStr; 00476 TQDateTime dt; 00477 bool bg(false); 00478 #ifdef HAVE_CUPS_1_6 00479 while (attr && ippGetGroupTag(attr) == group) 00480 { 00481 output << " <tr bgcolor=\"" << (bg ? "#ffffd9" : "#ffffff") << "\">\n <td><b>" << ippGetName(attr) << "</b></td>\n <td>" << endl; 00482 bg = !bg; 00483 for (int i=0; i<ippGetCount(attr); i++) 00484 { 00485 switch (ippGetValueTag(attr)) 00486 { 00487 case IPP_TAG_INTEGER: 00488 if (ippGetName(attr) && strstr(ippGetName(attr), "time")) 00489 { 00490 dt.setTime_t((unsigned int)(ippGetInteger(attr, i))); 00491 output << dt.toString(); 00492 } 00493 else 00494 output << ippGetInteger(attr, i); 00495 break; 00496 case IPP_TAG_ENUM: 00497 output << "0x" << hex << ippGetInteger(attr, i) << dec; 00498 break; 00499 case IPP_TAG_BOOLEAN: 00500 output << (ippGetBoolean(attr, i) ? i18n("True") : i18n("False")); 00501 break; 00502 case IPP_TAG_STRING: 00503 case IPP_TAG_TEXTLANG: 00504 case IPP_TAG_NAMELANG: 00505 case IPP_TAG_TEXT: 00506 case IPP_TAG_NAME: 00507 case IPP_TAG_KEYWORD: 00508 case IPP_TAG_URI: 00509 case IPP_TAG_CHARSET: 00510 case IPP_TAG_LANGUAGE: 00511 case IPP_TAG_MIMETYPE: 00512 output << ippGetString(attr, i, NULL); 00513 break; 00514 case IPP_TAG_RESOLUTION: 00515 int xres; 00516 int yres; 00517 ipp_res_t units; 00518 xres = ippGetResolution(attr, i, &yres, &units); 00519 output << "( " << xres 00520 << ", " << yres << " )"; 00521 break; 00522 case IPP_TAG_RANGE: 00523 int lowervalue; 00524 int uppervalue; 00525 lowervalue = ippGetRange(attr, i, &uppervalue); 00526 output << "[ " << (lowervalue > 0 ? lowervalue : 1) 00527 << ", " << (uppervalue > 0 ? uppervalue : 65535) << " ]"; 00528 break; 00529 case IPP_TAG_DATE: 00530 d = ippGetDate(attr, i); 00531 dateStr.sprintf("%.4d-%.2d-%.2d, %.2d:%.2d:%.2d %c%.2d%.2d", 00532 d[0]*256+d[1], d[2], d[3], 00533 d[4], d[5], d[6], 00534 d[8], d[9], d[10]); 00535 output << dateStr; 00536 break; 00537 default: 00538 continue; 00539 } 00540 if (i < ippGetCount(attr)-1) 00541 output << "<br>"; 00542 } 00543 output << "</td>\n </tr>" << endl; 00544 attr = ippNextAttribute(request_); 00545 #else // HAVE_CUPS_1_6 00546 while (attr && attr->group_tag == group) 00547 { 00548 output << " <tr bgcolor=\"" << (bg ? "#ffffd9" : "#ffffff") << "\">\n <td><b>" << attr->name << "</b></td>\n <td>" << endl; 00549 bg = !bg; 00550 for (int i=0; i<attr->num_values; i++) 00551 { 00552 switch (attr->value_tag) 00553 { 00554 case IPP_TAG_INTEGER: 00555 if (attr->name && strstr(attr->name, "time")) 00556 { 00557 dt.setTime_t((unsigned int)(attr->values[i].integer)); 00558 output << dt.toString(); 00559 } 00560 else 00561 output << attr->values[i].integer; 00562 break; 00563 case IPP_TAG_ENUM: 00564 output << "0x" << hex << attr->values[i].integer << dec; 00565 break; 00566 case IPP_TAG_BOOLEAN: 00567 output << (attr->values[i].boolean ? i18n("True") : i18n("False")); 00568 break; 00569 case IPP_TAG_STRING: 00570 case IPP_TAG_TEXTLANG: 00571 case IPP_TAG_NAMELANG: 00572 case IPP_TAG_TEXT: 00573 case IPP_TAG_NAME: 00574 case IPP_TAG_KEYWORD: 00575 case IPP_TAG_URI: 00576 case IPP_TAG_CHARSET: 00577 case IPP_TAG_LANGUAGE: 00578 case IPP_TAG_MIMETYPE: 00579 output << attr->values[i].string.text; 00580 break; 00581 case IPP_TAG_RESOLUTION: 00582 output << "( " << attr->values[i].resolution.xres 00583 << ", " << attr->values[i].resolution.yres << " )"; 00584 break; 00585 case IPP_TAG_RANGE: 00586 output << "[ " << (attr->values[i].range.lower > 0 ? attr->values[i].range.lower : 1) 00587 << ", " << (attr->values[i].range.upper > 0 ? attr->values[i].range.upper : 65535) << " ]"; 00588 break; 00589 case IPP_TAG_DATE: 00590 d = attr->values[i].date; 00591 dateStr.sprintf("%.4d-%.2d-%.2d, %.2d:%.2d:%.2d %c%.2d%.2d", 00592 d[0]*256+d[1], d[2], d[3], 00593 d[4], d[5], d[6], 00594 d[8], d[9], d[10]); 00595 output << dateStr; 00596 break; 00597 default: 00598 continue; 00599 } 00600 if (i < attr->num_values-1) 00601 output << "<br>"; 00602 } 00603 output << "</td>\n </tr>" << endl; 00604 attr = attr->next; 00605 #endif // HAVE_CUPS_1_6 00606 } 00607 // end table 00608 output << "</table>" << endl; 00609 00610 return true; 00611 } 00612 00613 TQMap<TQString,TQString> IppRequest::toMap(int group) 00614 { 00615 TQMap<TQString,TQString> opts; 00616 if (request_) 00617 { 00618 ipp_attribute_t *attr = first(); 00619 while (attr) 00620 { 00621 #ifdef HAVE_CUPS_1_6 00622 if (group != -1 && ippGetGroupTag(attr) != group) 00623 { 00624 attr = ippNextAttribute(request_); 00625 continue; 00626 } 00627 TQString value; 00628 for (int i=0; i<ippGetCount(attr); i++) 00629 { 00630 switch (ippGetValueTag(attr)) 00631 { 00632 case IPP_TAG_INTEGER: 00633 case IPP_TAG_ENUM: 00634 value.append(TQString::number(ippGetInteger(attr, i))).append(","); 00635 break; 00636 case IPP_TAG_BOOLEAN: 00637 value.append((ippGetBoolean(attr, i) ? "true" : "false")).append(","); 00638 break; 00639 case IPP_TAG_RANGE: 00640 int lowervalue; 00641 int uppervalue; 00642 lowervalue = ippGetRange(attr, i, &uppervalue); 00643 if (lowervalue > 0) 00644 value.append(TQString::number(lowervalue)); 00645 if (lowervalue != uppervalue) 00646 { 00647 value.append("-"); 00648 if (uppervalue > 0) 00649 value.append(TQString::number(uppervalue)); 00650 } 00651 value.append(","); 00652 break; 00653 case IPP_TAG_STRING: 00654 case IPP_TAG_TEXT: 00655 case IPP_TAG_NAME: 00656 case IPP_TAG_KEYWORD: 00657 case IPP_TAG_URI: 00658 case IPP_TAG_MIMETYPE: 00659 case IPP_TAG_NAMELANG: 00660 case IPP_TAG_TEXTLANG: 00661 case IPP_TAG_CHARSET: 00662 case IPP_TAG_LANGUAGE: 00663 value.append(TQString::fromLocal8Bit(ippGetString(attr, i, NULL))).append(","); 00664 break; 00665 default: 00666 break; 00667 } 00668 } 00669 if (!value.isEmpty()) 00670 value.truncate(value.length()-1); 00671 opts[TQString::fromLocal8Bit(ippGetName(attr))] = value; 00672 attr = ippNextAttribute(request_); 00673 #else // HAVE_CUPS_1_6 00674 if (group != -1 && attr->group_tag != group) 00675 { 00676 attr = attr->next; 00677 continue; 00678 } 00679 TQString value; 00680 for (int i=0; i<attr->num_values; i++) 00681 { 00682 switch (attr->value_tag) 00683 { 00684 case IPP_TAG_INTEGER: 00685 case IPP_TAG_ENUM: 00686 value.append(TQString::number(attr->values[i].integer)).append(","); 00687 break; 00688 case IPP_TAG_BOOLEAN: 00689 value.append((attr->values[i].boolean ? "true" : "false")).append(","); 00690 break; 00691 case IPP_TAG_RANGE: 00692 if (attr->values[i].range.lower > 0) 00693 value.append(TQString::number(attr->values[i].range.lower)); 00694 if (attr->values[i].range.lower != attr->values[i].range.upper) 00695 { 00696 value.append("-"); 00697 if (attr->values[i].range.upper > 0) 00698 value.append(TQString::number(attr->values[i].range.upper)); 00699 } 00700 value.append(","); 00701 break; 00702 case IPP_TAG_STRING: 00703 case IPP_TAG_TEXT: 00704 case IPP_TAG_NAME: 00705 case IPP_TAG_KEYWORD: 00706 case IPP_TAG_URI: 00707 case IPP_TAG_MIMETYPE: 00708 case IPP_TAG_NAMELANG: 00709 case IPP_TAG_TEXTLANG: 00710 case IPP_TAG_CHARSET: 00711 case IPP_TAG_LANGUAGE: 00712 value.append(TQString::fromLocal8Bit(attr->values[i].string.text)).append(","); 00713 break; 00714 default: 00715 break; 00716 } 00717 } 00718 if (!value.isEmpty()) 00719 value.truncate(value.length()-1); 00720 opts[TQString::fromLocal8Bit(attr->name)] = value; 00721 attr = attr->next; 00722 #endif // HAVE_CUPS_1_6 00723 } 00724 } 00725 return opts; 00726 } 00727 00728 void IppRequest::setMap(const TQMap<TQString,TQString>& opts) 00729 { 00730 if (!request_) 00731 return; 00732 00733 TQRegExp re("^\"|\"$"); 00734 cups_option_t *options = NULL; 00735 int n = 0; 00736 for (TQMap<TQString,TQString>::ConstIterator it=opts.begin(); it!=opts.end(); ++it) 00737 { 00738 if (it.key().startsWith("kde-") || it.key().startsWith("app-")) 00739 continue; 00740 TQString value = it.data().stripWhiteSpace(), lovalue; 00741 value.replace(re, ""); 00742 lovalue = value.lower(); 00743 00744 // handles specific cases: boolean, empty strings, or option that has that boolean 00745 // keyword as value (to prevent them from conversion to real boolean) 00746 if (value == "true" || value == "false") 00747 addBoolean(IPP_TAG_JOB, it.key(), (value == "true")); 00748 else if (value.isEmpty() || lovalue == "off" || lovalue == "on" 00749 || lovalue == "yes" || lovalue == "no" 00750 || lovalue == "true" || lovalue == "false") 00751 addName(IPP_TAG_JOB, it.key(), value); 00752 else 00753 n = cupsAddOption(it.key().local8Bit(), value.local8Bit(), n, &options); 00754 } 00755 if (n > 0) 00756 cupsEncodeOptions(request_, n, options); 00757 cupsFreeOptions(n, options); 00758 00759 // find an remove that annoying "document-format" attribute 00760 #if CUPS_VERSION_MAJOR > 1 || (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR >= 2) 00761 ipp_attribute_t *attr = ippFindAttribute(request_, "document-format", IPP_TAG_NAME); 00762 ippDeleteAttribute(request_, attr); 00763 #else 00764 // (can't use IppDeleteAttribute as older cups doesn't have that) 00765 ipp_attribute_t *attr = request_->attrs; 00766 while (attr) 00767 { 00768 if (attr->next && strcmp(attr->next->name, "document-format") == 0) 00769 { 00770 ipp_attribute_t *attr2 = attr->next; 00771 attr->next = attr2->next; 00772 _ipp_free_attr(attr2); 00773 break; 00774 } 00775 attr = attr->next; 00776 } 00777 #endif 00778 } 00779 00780 #ifdef HAVE_CUPS_1_6 00781 ipp_attribute_t* IppRequest::first() 00782 { return (request_ ? ippFirstAttribute(request_) : NULL); } 00783 #else // HAVE_CUPS_1_6 00784 ipp_attribute_t* IppRequest::first() 00785 { return (request_ ? request_->attrs : NULL); } 00786 #endif // HAVE_CUPS_1_6