# kdeprint Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# ipprequest.cpp

    00001 /*
    00002  *  This file is part of the KDE libraries
    00003  *  Copyright (c) 2001 Michael Goffioul <kdeprint@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., 59 Temple Place - Suite 330,
    00017  *  Boston, MA 02111-1307, USA.
    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     //kdDebug(500) << "kdeprint: IPP request, lang=" << KGlobal::locale()->language() << endl;
    00158         QCString langstr = KGlobal::locale()->language().latin1();
    00159     cups_lang_t*    lang = cupsLangGet(langstr.data());
    00160     // default charset to UTF-8 (ugly hack)
    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;    // 0 is not RFC-compliant, should be at least 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     // start table
    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     // go to the first attribute of the specified group
    00347     ipp_attribute_t *attr = request_->attrs;
    00348     while (attr && attr->group_tag != group)
    00349         attr = attr->next;
    00350     // print each attribute
    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     // end table
    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         // handles specific cases: boolean, empty strings, or option that has that boolean
    00499         // keyword as value (to prevent them from conversion to real boolean)
    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     // find an remove that annoying "document-format" attribute
    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 }

This file is part of the documentation for kdeprint Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:31:01 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003