00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
#include "ipprequest.h"
00021
#include "cupsinfos.h"
00022
00023
#include <stdlib.h>
00024
#include <cups/language.h>
00025
#include <kdebug.h>
00026
#include <kglobal.h>
00027
#include <klocale.h>
00028
#include <qdatetime.h>
00029
#include <qregexp.h>
00030
#include <cups/cups.h>
00031
00032
#ifdef HAVE_CONFIG_H
00033
#include <config.h>
00034
#endif
00035
00036
#ifdef HAVE_CUPS_NO_PWD_CACHE
00037
#include <qcstring.h>
00038
static QCString cups_authstring =
"";
00039
#endif
00040
00041
void dumpRequest(ipp_t *req,
bool answer =
false,
const QString& s = QString::null)
00042 {
00043 kdDebug(500) <<
"==========" << endl;
00044
if (s.isEmpty())
00045 kdDebug(500) << (answer ?
"Answer" :
"Request") << endl;
00046
else
00047 kdDebug(500) << s << endl;
00048 kdDebug(500) <<
"==========" << endl;
00049
if (!req)
00050 {
00051 kdDebug(500) <<
"Null request" << endl;
00052
return;
00053 }
00054 kdDebug(500) <<
"State = 0x" <<
QString::number(req->state, 16) << endl;
00055 kdDebug(500) <<
"ID = 0x" <<
QString::number(req->request.status.request_id, 16) << endl;
00056
if (answer)
00057 {
00058 kdDebug(500) <<
"Status = 0x" <<
QString::number(req->request.status.status_code, 16) << endl;
00059 kdDebug(500) <<
"Status message = " << ippErrorString(req->request.status.status_code) << endl;
00060 }
00061
else
00062 kdDebug(500) <<
"Operation = 0x" <<
QString::number(req->request.op.operation_id, 16) << endl;
00063 kdDebug(500) <<
"Version = " << (
int)(req->request.status.version[0]) <<
"." << (
int)(req->request.status.version[1]) << endl;
00064 kdDebug(500) << endl;
00065
00066 ipp_attribute_t *attr = req->attrs;
00067
while (attr)
00068 {
00069
QString s =
QString::fromLatin1(
"%1 (0x%2) = ").arg(attr->name).arg(attr->value_tag, 0, 16);
00070
for (
int i=0;i<attr->num_values;i++)
00071 {
00072
switch (attr->value_tag)
00073 {
00074
case IPP_TAG_INTEGER:
00075
case IPP_TAG_ENUM:
00076 s += (
"0x"+
QString::number(attr->values[i].integer, 16));
00077
break;
00078
case IPP_TAG_BOOLEAN:
00079 s += (attr->values[i].boolean ?
"true" :
"false");
00080
break;
00081
case IPP_TAG_STRING:
00082
case IPP_TAG_TEXT:
00083
case IPP_TAG_NAME:
00084
case IPP_TAG_KEYWORD:
00085
case IPP_TAG_URI:
00086
case IPP_TAG_MIMETYPE:
00087
case IPP_TAG_NAMELANG:
00088
case IPP_TAG_TEXTLANG:
00089
case IPP_TAG_CHARSET:
00090
case IPP_TAG_LANGUAGE:
00091 s += attr->values[i].string.text;
00092
break;
00093
default:
00094
break;
00095 }
00096
if (i != (attr->num_values-1))
00097 s +=
", ";
00098 }
00099 kdDebug(500) << s << endl;
00100 attr = attr->next;
00101 }
00102 }
00103
00104
QString errorString(
int status)
00105 {
00106
QString str;
00107
switch (status)
00108 {
00109
case IPP_FORBIDDEN:
00110 str = i18n(
"You don't have access to the requested resource.");
00111
break;
00112
case IPP_NOT_AUTHORIZED:
00113 str = i18n(
"You are not authorized to access the requested resource.");
00114
break;
00115
case IPP_NOT_POSSIBLE:
00116 str = i18n(
"The requested operation cannot be completed.");
00117
break;
00118
case IPP_SERVICE_UNAVAILABLE:
00119 str = i18n(
"The requested service is currently unavailable.");
00120
break;
00121
case IPP_NOT_ACCEPTING:
00122 str = i18n(
"The target printer is not accepting print jobs.");
00123
break;
00124
default:
00125 str =
QString::fromLocal8Bit(ippErrorString((ipp_status_t)status));
00126
break;
00127 }
00128
return str;
00129 }
00130
00131
00132
00133 IppRequest::IppRequest()
00134 {
00135 request_ = 0;
00136 port_ = -1;
00137 host_ = QString::null;
00138 dump_ = 0;
00139 init();
00140 }
00141
00142 IppRequest::~IppRequest()
00143 {
00144 ippDelete(request_);
00145 }
00146
00147
void IppRequest::init()
00148 {
00149 connect_ =
true;
00150
00151
if (request_)
00152 {
00153 ippDelete(request_);
00154 request_ = 0;
00155 }
00156 request_ = ippNew();
00157
00158
QCString langstr = KGlobal::locale()->language().latin1();
00159 cups_lang_t* lang = cupsLangGet(langstr.data());
00160
00161 lang->encoding = CUPS_UTF8;
00162 ippAddString(request_, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
"attributes-charset", NULL, cupsLangEncoding(lang));
00163 ippAddString(request_, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
"attributes-natural-language", NULL, lang->language);
00164 cupsLangFree(lang);
00165 }
00166
00167
void IppRequest::addString_p(
int group,
int type,
const QString& name,
const QString& value)
00168 {
00169
if (!name.isEmpty())
00170 ippAddString(request_,(ipp_tag_t)group,(ipp_tag_t)type,name.latin1(),NULL,(value.isEmpty() ?
"" : value.local8Bit().data()));
00171 }
00172
00173
void IppRequest::addStringList_p(
int group,
int type,
const QString& name,
const QStringList& values)
00174 {
00175
if (!name.isEmpty())
00176 {
00177 ipp_attribute_t *attr = ippAddStrings(request_,(ipp_tag_t)group,(ipp_tag_t)type,name.latin1(),(
int)(values.count()),NULL,NULL);
00178
int i(0);
00179
for (QStringList::ConstIterator it=values.begin(); it != values.end(); ++it, i++)
00180 attr->values[i].string.text = strdup((*it).local8Bit());
00181 }
00182 }
00183
00184
void IppRequest::addInteger_p(
int group,
int type,
const QString& name,
int value)
00185 {
00186
if (!name.isEmpty()) ippAddInteger(request_,(ipp_tag_t)group,(ipp_tag_t)type,name.latin1(),value);
00187 }
00188
00189
void IppRequest::addIntegerList_p(
int group,
int type,
const QString& name,
const QValueList<int>& values)
00190 {
00191
if (!name.isEmpty())
00192 {
00193 ipp_attribute_t *attr = ippAddIntegers(request_,(ipp_tag_t)group,(ipp_tag_t)type,name.latin1(),(
int)(values.
count()),NULL);
00194
int i(0);
00195
for (
QValueList<int>::ConstIterator it=values.
begin(); it != values.
end(); ++it, i++)
00196 attr->values[i].integer = *it;
00197 }
00198 }
00199
00200
void IppRequest::addBoolean(
int group,
const QString& name,
bool value)
00201 {
00202
if (!name.isEmpty()) ippAddBoolean(request_,(ipp_tag_t)group,name.latin1(),(
char)value);
00203 }
00204
00205
void IppRequest::addBoolean(
int group,
const QString& name,
const QValueList<bool>& values)
00206 {
00207
if (!name.isEmpty())
00208 {
00209 ipp_attribute_t *attr = ippAddBooleans(request_,(ipp_tag_t)group,name.latin1(),(
int)(values.
count()),NULL);
00210
int i(0);
00211
for (
QValueList<bool>::ConstIterator it=values.
begin(); it != values.
end(); ++it, i++)
00212 attr->values[i].boolean = (
char)(*it);
00213 }
00214 }
00215
00216
void IppRequest::setOperation(
int op)
00217 {
00218 request_->request.op.operation_id = (ipp_op_t)op;
00219 request_->request.op.request_id = 1;
00220 }
00221
00222
int IppRequest::status()
00223 {
00224
return (request_ ? request_->request.status.status_code : (connect_ ? cupsLastError() : -2));
00225 }
00226
00227
QString IppRequest::statusMessage()
00228 {
00229
QString msg;
00230
switch (status())
00231 {
00232
case -2:
00233 msg = i18n(
"Connection to CUPS server failed. Check that the CUPS server is correctly installed and running.");
00234
break;
00235
case -1:
00236 msg = i18n(
"The IPP request failed for an unknown reason.");
00237
break;
00238
default:
00239 msg = errorString(status());
00240
break;
00241 }
00242
return msg;
00243 }
00244
00245
bool IppRequest::integerValue_p(
const QString& name,
int& value,
int type)
00246 {
00247
if (!request_ || name.isEmpty())
return false;
00248 ipp_attribute_t *attr = ippFindAttribute(request_, name.latin1(), (ipp_tag_t)type);
00249
if (attr)
00250 {
00251 value = attr->values[0].integer;
00252
return true;
00253 }
00254
else return false;
00255 }
00256
00257
bool IppRequest::stringValue_p(
const QString& name,
QString& value,
int type)
00258 {
00259
if (!request_ || name.isEmpty())
return false;
00260 ipp_attribute_t *attr = ippFindAttribute(request_, name.latin1(), (ipp_tag_t)type);
00261
if (attr)
00262 {
00263 value =
QString::fromLocal8Bit(attr->values[0].string.text);
00264
return true;
00265 }
00266
else return false;
00267 }
00268
00269
bool IppRequest::stringListValue_p(
const QString& name,
QStringList& values,
int type)
00270 {
00271
if (!request_ || name.isEmpty())
return false;
00272 ipp_attribute_t *attr = ippFindAttribute(request_, name.latin1(), (ipp_tag_t)type);
00273 values.clear();
00274
if (attr)
00275 {
00276
for (
int i=0;i<attr->num_values;i++)
00277 values.append(QString::fromLocal8Bit(attr->values[i].string.text));
00278
return true;
00279 }
00280
else return false;
00281 }
00282
00283
bool IppRequest::boolean(
const QString& name,
bool& value)
00284 {
00285
if (!request_ || name.isEmpty())
return false;
00286 ipp_attribute_t *attr = ippFindAttribute(request_, name.latin1(), IPP_TAG_BOOLEAN);
00287
if (attr)
00288 {
00289 value = (
bool)attr->values[0].boolean;
00290
return true;
00291 }
00292
else return false;
00293 }
00294
00295
bool IppRequest::doFileRequest(
const QString& res,
const QString& filename)
00296 {
00297
QString myHost = host_;
00298
int myPort = port_;
00299
if (myHost.
isEmpty()) myHost = CupsInfos::self()->host();
00300
if (myPort <= 0) myPort = CupsInfos::self()->port();
00301 http_t *HTTP = httpConnect(myHost.
latin1(),myPort);
00302
00303 connect_ = (HTTP != NULL);
00304
00305
if (HTTP == NULL)
00306 {
00307 ippDelete(request_);
00308 request_ = 0;
00309
return false;
00310 }
00311
00312
#ifdef HAVE_CUPS_NO_PWD_CACHE
00313
strncpy( HTTP->authstring, cups_authstring.data(), HTTP_MAX_VALUE );
00314
#endif
00315
00316
if (dump_ > 0)
00317 {
00318 dumpRequest(request_,
false,
"Request to "+myHost+
":"+QString::number(myPort));
00319 }
00320
00321 request_ = cupsDoFileRequest(HTTP, request_, (res.
isEmpty() ?
"/" : res.
latin1()), (filename.
isEmpty() ? NULL : filename.
latin1()));
00322
#ifdef HAVE_CUPS_NO_PWD_CACHE
00323
cups_authstring = HTTP->authstring;
00324
#endif
00325
httpClose(HTTP);
00326
00327
if (dump_ > 1)
00328 {
00329 dumpRequest(request_,
true);
00330 }
00331
00332
if (!request_ || request_->state == IPP_ERROR || (request_->request.status.status_code & 0x0F00))
00333
return false;
00334
00335
00336
return true;
00337 }
00338
00339
bool IppRequest::htmlReport(
int group,
QTextStream& output)
00340 {
00341
if (!request_)
return false;
00342
00343 output <<
"<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">" << endl;
00344 output <<
"<tr><th bgcolor=\"dark blue\"><font color=\"white\">" << i18n(
"Attribute") <<
"</font></th>" << endl;
00345 output <<
"<th bgcolor=\"dark blue\"><font color=\"white\">" << i18n(
"Values") <<
"</font></th></tr>" << endl;
00346
00347 ipp_attribute_t *attr = request_->attrs;
00348
while (attr && attr->group_tag != group)
00349 attr = attr->next;
00350
00351 ipp_uchar_t *d;
00352
QCString dateStr;
00353
QDateTime dt;
00354
bool bg(
false);
00355
while (attr && attr->group_tag == group)
00356 {
00357 output <<
" <tr bgcolor=\"" << (bg ?
"#ffffd9" :
"#ffffff") <<
"\">\n <td><b>" << attr->name <<
"</b></td>\n <td>" << endl;
00358 bg = !bg;
00359
for (
int i=0; i<attr->num_values; i++)
00360 {
00361
switch (attr->value_tag)
00362 {
00363
case IPP_TAG_INTEGER:
00364
if (attr->name && strstr(attr->name,
"time"))
00365 {
00366 dt.
setTime_t((
unsigned int)(attr->values[i].integer));
00367 output << dt.
toString();
00368 }
00369
else
00370 output << attr->values[i].integer;
00371
break;
00372
case IPP_TAG_ENUM:
00373 output <<
"0x" << hex << attr->values[i].integer << dec;
00374
break;
00375
case IPP_TAG_BOOLEAN:
00376 output << (attr->values[i].boolean ? i18n(
"True") : i18n("False"));
00377
break;
00378
case IPP_TAG_STRING:
00379
case IPP_TAG_TEXTLANG:
00380
case IPP_TAG_NAMELANG:
00381
case IPP_TAG_TEXT:
00382
case IPP_TAG_NAME:
00383
case IPP_TAG_KEYWORD:
00384
case IPP_TAG_URI:
00385
case IPP_TAG_CHARSET:
00386
case IPP_TAG_LANGUAGE:
00387
case IPP_TAG_MIMETYPE:
00388 output << attr->values[i].string.text;
00389
break;
00390
case IPP_TAG_RESOLUTION:
00391 output <<
"( " << attr->values[i].resolution.xres
00392 <<
", " << attr->values[i].resolution.yres <<
" )";
00393
break;
00394
case IPP_TAG_RANGE:
00395 output <<
"[ " << (attr->values[i].range.lower > 0 ? attr->values[i].range.lower : 1)
00396 <<
", " << (attr->values[i].range.upper > 0 ? attr->values[i].range.upper : 65535) <<
" ]";
00397
break;
00398
case IPP_TAG_DATE:
00399 d = attr->values[i].date;
00400 dateStr.
sprintf(
"%.4d-%.2d-%.2d, %.2d:%.2d:%.2d %c%.2d%.2d",
00401 d[0]*256+d[1], d[2], d[3],
00402 d[4], d[5], d[6],
00403 d[8], d[9], d[10]);
00404 output << dateStr;
00405
break;
00406
default:
00407
continue;
00408 }
00409
if (i < attr->num_values-1)
00410 output <<
"<br>";
00411 }
00412 output <<
"</td>\n </tr>" << endl;
00413 attr = attr->next;
00414 }
00415
00416 output <<
"</table>" << endl;
00417
00418
return true;
00419 }
00420
00421
QMap<QString,QString> IppRequest::toMap(
int group)
00422 {
00423
QMap<QString,QString> opts;
00424
if (request_)
00425 {
00426 ipp_attribute_t *attr = first();
00427
while (attr)
00428 {
00429
if (group != -1 && attr->group_tag != group)
00430 {
00431 attr = attr->next;
00432
continue;
00433 }
00434
QString value;
00435
for (
int i=0; i<attr->num_values; i++)
00436 {
00437
switch (attr->value_tag)
00438 {
00439
case IPP_TAG_INTEGER:
00440
case IPP_TAG_ENUM:
00441 value.append(QString::number(attr->values[i].integer)).append(
",");
00442
break;
00443
case IPP_TAG_BOOLEAN:
00444 value.append((attr->values[i].boolean ?
"true" :
"false")).append(
",");
00445
break;
00446
case IPP_TAG_RANGE:
00447
if (attr->values[i].range.lower > 0)
00448 value.append(QString::number(attr->values[i].range.lower));
00449
if (attr->values[i].range.lower != attr->values[i].range.upper)
00450 {
00451 value.append(
"-");
00452
if (attr->values[i].range.upper > 0)
00453 value.append(QString::number(attr->values[i].range.upper));
00454 }
00455 value.append(
",");
00456
break;
00457
case IPP_TAG_STRING:
00458
case IPP_TAG_TEXT:
00459
case IPP_TAG_NAME:
00460
case IPP_TAG_KEYWORD:
00461
case IPP_TAG_URI:
00462
case IPP_TAG_MIMETYPE:
00463
case IPP_TAG_NAMELANG:
00464
case IPP_TAG_TEXTLANG:
00465
case IPP_TAG_CHARSET:
00466
case IPP_TAG_LANGUAGE:
00467 value.append(QString::fromLocal8Bit(attr->values[i].string.text)).append(
",");
00468
break;
00469
default:
00470
break;
00471 }
00472 }
00473
if (!value.isEmpty())
00474 value.truncate(value.length()-1);
00475 opts[
QString::fromLocal8Bit(attr->name)] = value;
00476 attr = attr->next;
00477 }
00478 }
00479
return opts;
00480 }
00481
00482
void IppRequest::setMap(
const QMap<QString,QString>& opts)
00483 {
00484
if (!request_)
00485
return;
00486
00487
QRegExp re(
"^\"|\"$");
00488 cups_option_t *options = NULL;
00489
int n = 0;
00490
for (
QMap<QString,QString>::ConstIterator it=opts.
begin(); it!=opts.
end(); ++it)
00491 {
00492
if (it.key().startsWith(
"kde-") || it.key().startsWith(
"app-"))
00493
continue;
00494
QString value = it.data().stripWhiteSpace(), lovalue;
00495 value.replace(re,
"");
00496 lovalue = value.lower();
00497
00498
00499
00500
if (value ==
"true" || value ==
"false")
00501 addBoolean(IPP_TAG_JOB, it.key(), (value ==
"true"));
00502
else if (value.isEmpty() || lovalue ==
"off" || lovalue ==
"on"
00503 || lovalue ==
"yes" || lovalue ==
"no"
00504 || lovalue ==
"true" || lovalue ==
"false")
00505 addName(IPP_TAG_JOB, it.key(), value);
00506
else
00507 n = cupsAddOption(it.key().local8Bit(), value.local8Bit(), n, &options);
00508 }
00509
if (n > 0)
00510 cupsEncodeOptions(request_, n, options);
00511 cupsFreeOptions(n, options);
00512
00513
00514 ipp_attribute_t *attr = request_->attrs;
00515
while (attr)
00516 {
00517
if (attr->next && strcmp(attr->next->name,
"document-format") == 0)
00518 {
00519 ipp_attribute_t *attr2 = attr->next;
00520 attr->next = attr2->next;
00521 _ipp_free_attr(attr2);
00522
break;
00523 }
00524 attr = attr->next;
00525 }
00526 }