src/wsdlparser/WsdlInvoker.cpp

00001 /* 
00002  * wsdlpull - A C++ parser  for WSDL  (Web services description language)
00003  * Copyright (C) 2005-2007 Vivek Krishna
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 as published by the Free Software Foundation; either
00008  * version 2 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Library General Public
00016  * License along with this library; if not, write to the Free
00017  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018  */
00019 
00020 #ifdef HAVE_CONFIG_H
00021 #include <config.h>
00022 #endif
00023 
00024 #ifdef  WITH_CURL
00025 #include <curl/curl.h>
00026 #endif 
00027 #include "wsdlparser/WsdlInvoker.h"
00028 
00029 extern "C" {
00030   size_t storeResults(void * buf,size_t sz,size_t nmemb,void* userdata);
00031 }
00032 static char* results_ = 0;
00033 
00034 namespace WsdlPull {
00035 
00036 WsdlInvoker::WsdlInvoker()
00037   :wParser_(0),
00038    ourParser_(0),
00039    xmlStream_(0),
00040    soap_(0),
00041    soapheaders_(false),
00042    hPartId_(-1),
00043    soapstr_(0),
00044    status_(false),
00045    serializeMode_(false),
00046    verbose_(false),
00047    dontPost_(false),
00048    oHeaders_(0),
00049    op_(0),
00050    n_(0),
00051    iHeaders_(0),
00052    messageType_(WsdlPull::Input)
00053 {
00054 }
00055 
00056 WsdlInvoker::WsdlInvoker(const std::string & url)
00057   :wParser_(0),
00058    ourParser_(0),
00059    xmlStream_(0),
00060    soap_(0),
00061    soapheaders_(false),
00062    hPartId_(-1),
00063    status_(false),
00064    serializeMode_(false),
00065    verbose_(false),
00066    dontPost_(false),
00067    op_(0),
00068    n_(0),
00069    iHeaders_(0),
00070    messageType_(WsdlPull::Input)
00071 {
00072   parseWsdl(url);
00073 }
00074 
00075 WsdlInvoker::WsdlInvoker(const std::string & url, const std::string & schemaPath)
00076    :wParser_(0),
00077    ourParser_(0),
00078    xmlStream_(0),
00079    soap_(0),
00080    soapheaders_(false),
00081    hPartId_(-1),
00082    status_(false),
00083    serializeMode_(false),
00084    verbose_(false),
00085    dontPost_(false),
00086    op_(0),
00087    n_(0),
00088    iHeaders_(0),
00089    messageType_(WsdlPull::Input)
00090 {
00091       parseWsdl(url, schemaPath);
00092 }
00093 
00094 
00095 void
00096 WsdlInvoker::parseWsdl(const std::string & url, const std::string & schemaPath)
00097 {
00098   try{
00099     wParser_ = new WsdlParser(url,logger_, schemaPath);
00100     ourParser_= wParser_;
00101     if (wParser_){
00102       //parse the web service
00103       while (wParser_->getNextElement () != WsdlParser::END);
00104       if (wParser_->status()){
00105       
00106         status_=true;
00107         init(wParser_);
00108       }
00109     }
00110   }
00111     catch (WsdlException we)
00112       {
00113        logger_<<"An exception  occurred at "<<we.line   
00114              <<":"<<we.col<<std::endl;
00115         logger_<<we.description<<std::endl;
00116         status_ =false;
00117       }
00118     catch (SchemaParserException spe)
00119       {
00120        logger_<<"An exception occurred at "<<spe.line
00121              <<":"<<spe.col<<std::endl;
00122         logger_<<spe.description<<std::endl;
00123         status_ =false;
00124       }
00125     catch (XmlPullParserException xpe)
00126       {
00127        logger_<<"An exception occurred at "<<xpe.line
00128              <<":"<<xpe.col<<std::endl;
00129        logger_<<xpe.description<<std::endl;
00130        status_= false;
00131       }
00132 }
00133 
00134 bool
00135 WsdlInvoker::init(WsdlParser* parser)
00136 {
00137   try{
00138     wParser_ = parser;
00139     status_ = wParser_->status();
00140     if (status_){
00141       
00142       PortType::cPortTypeIterator p1,p2;
00143       wParser_->getPortTypes(p1,p2);
00144       int i=0;
00145       Soap* soap=static_cast<Soap*> (wParser_->getExtensibilityHandler(Soap::soapBindingUri));
00146       while(p1!=p2){
00147     
00148         Operation::cOpIterator op1,op2;
00149         (*p1)->getOperations(op1,op2);
00150         const Binding *bn = (*p1)->binding(Soap::soapBindingUri);
00151         if (!bn){
00152           p1++;
00153           continue;
00154         }
00155         int soap_binding_elem =soap->getElementName (bn->getBindingInfo ());
00156         //check if the port type has a soap binding
00157         if (soap_binding_elem == 0){
00158           p1++;
00159           continue;
00160         }
00161 
00162         while(op1!=op2){
00163         
00164           opMap_[(*op1)->getName()]=*op1;
00165           op1++; 
00166           i++;
00167         }
00168         p1++;
00169       }
00170     }
00171   }
00172   catch (WsdlException we)
00173     {
00174       logger_<<"A WSDL exception occurred at"<<we.line
00175              <<":"<<we.col<<std::endl;
00176       logger_<<we.description<<std::endl;
00177       status_ =false;
00178     }
00179   catch (SchemaParserException spe)
00180     {
00181       logger_<<"A Schema Parser exception occurred at "<<spe.line
00182              <<":"<<spe.col<<std::endl;
00183       logger_<<spe.description<<std::endl;
00184       status_ =false;
00185     }
00186   catch (XmlPullParserException xpe)
00187     {
00188       logger_<<"An Xml Parsing exception occurred at row:col "<<xpe.line
00189              <<":"<<xpe.col<<std::endl;
00190       logger_<<xpe.description<<std::endl;
00191       status_ =false;
00192     }
00193   return status_;
00194 }
00195  
00196 int
00197 WsdlInvoker::getOperations(std::vector<std::string> & operations)
00198 {
00199   int i = 0;
00200   for(
00201   std::map<std::string,const Operation*>::iterator it =
00202     opMap_.begin();
00203   it != opMap_.end();
00204   it++,i++){
00205 
00206     operations.push_back(it->first);
00207   }
00208   return i;
00209 }
00210 
00211 std::string
00212 WsdlInvoker::getDocumentation()
00213 {
00214    return *(wParser_->getDocumentation());
00215 }
00216    
00217 std::string
00218 WsdlInvoker::getOpDocumentation(const std::string & n)
00219 {
00220   
00221   std::map<std::string,const Operation*>::iterator it =
00222     opMap_.find(n);
00223   
00224   if (it != opMap_.end()){
00225     
00226     return  it->second->getDocumentation();
00227   }
00228   return "";
00229 }
00230 
00231 bool
00232 WsdlInvoker::setOperation(const std::string & opname,
00233                           WsdlPull::MessageType mType)
00234 {
00235   reset();
00236   messageType_ = mType;
00237    std::map<std::string,const Operation*>::iterator it =
00238     opMap_.find(opname);
00239 
00240   if (it != opMap_.end()){
00241     
00242     op_ = it->second;
00243 
00244     getOperationDetails(op_);
00245     
00246     if (soapheaders_){
00247       serializeHeader();
00248     }
00249     serialize();
00250     n_ = iHeaders_;
00251     return status_;
00252   }
00253   else{
00254     return false;
00255   }
00256 }
00257 
00258 std::string
00259 WsdlInvoker::getServiceEndPoint(const std::string & opname) 
00260 {
00261 
00262   reset();
00263   location_="";
00264   std::map<std::string,const Operation*>::iterator it =
00265     opMap_.find(opname);
00266 
00267   if (it != opMap_.end()){
00268     
00269     const Operation* op = it->second;
00270 
00271     getOperationDetails(op);
00272     reset();
00273   }
00274   return location_;
00275 }
00276 
00277 void
00278 WsdlInvoker::getOperationDetails(const Operation* op) 
00279 {
00280   const Binding * bnSoap = op->portType()->binding(Soap::soapBindingUri);
00281   soap_ = static_cast<Soap*> (wParser_->getExtensibilityHandler(Soap::soapBindingUri));    
00282 
00283   ///get various soap properties
00284   soap_->getServiceLocation (bnSoap->getServiceExtId (),location_);
00285   style_ = soap_->getStyle();
00286 
00287   if (location_.empty()){
00288 
00289     logger_<<"No service location specified"<<std::endl;
00290     status_ = false;
00291     return;
00292   }
00293   //get the soap:operation's SOAPAction and style
00294   const int *bindings = 0;
00295   int opIndex  = op->portType()->getOperationIndex(op->getName());
00296   bnSoap->getOpBinding (opIndex, bindings);
00297   int soapOpBindingId = bindings[0];
00298   //operation's style over rides 
00299   soap_->getSoapOperationInfo (soapOpBindingId, action_, style_);
00300 
00301   //get the soap:body namespace and use attributes
00302   int nBindings=bnSoap->getInputBinding(opIndex,bindings);
00303   //get the body and header
00304   for (int x=0;x<nBindings;x++){
00305     if (soap_->isSoapBody(bindings[x])){
00306 
00307       soap_->getSoapBodyInfo(bindings[x],nsp_,use_,encodingStyle_);
00308     }
00309     if (soap_->isSoapHeader(bindings[x]))
00310       soapheaders_ = true;
00311 
00312   }
00313     
00314   if (nsp_.empty()){
00315 
00316     nsp_ = wParser_->getNamespace();
00317   }
00318 }
00319 
00320 void
00321 WsdlInvoker::serializeHeader()
00322 {
00323   //create input  holders for the soap header,use the same list
00324   //but just remember where the header's params end
00325   std::string name;
00326   
00327   int hPartId;
00328   const Message* hMessage;//message corresponding to soap header
00329 
00330   const Binding * bnSoap = op_->portType()->binding(Soap::soapBindingUri);
00331   const int *bindings = 0;
00332   int opIndex  = op_->portType()->getOperationIndex(op_->getName());
00333   int nBindings=bnSoap->getInputBinding(opIndex,bindings);
00334   //get the body and header
00335   for (int x=0;x<nBindings;x++){
00336     
00337     if (soap_->isSoapHeader(bindings[x])){
00338       
00339       soap_->getSoapHeaderInfo(bindings[x],hnsp_,hPartId,hMessage);  
00340 
00341   
00342       Schema::Type pType =Schema::XSD_INVALID;
00343       if (hMessage->getPartRefType(hPartId)==Part::Elem){
00344         
00345         name = hMessage->getMessagePart(hPartId)->element()->getName();
00346         pType = (Schema::Type)hMessage->getMessagePart(hPartId)->element()->getType();
00347       }
00348       else {
00349         
00350         name = hMessage->getPartName(hPartId);
00351         pType = (Schema::Type)hMessage->getMessagePart(hPartId)->type();
00352       }
00353       std::vector<std::string> parents;
00354       parents.push_back(name);
00355       serializeType(pType,
00356                     name,
00357                     wParser_->getSchemaParser(hMessage->getPartContentSchemaId(hPartId)),
00358                     1,1,parents,hnsp_,true);
00359     }
00360   }
00361   iHeaders_ = elems_.size();
00362 
00363 }
00364 
00365 //this method extracts the  atomic types needed for the web service
00366 //it recursively calls serializeType for all the input or output types expected
00367 //This method works in 2 modes.In the serializeMode_ == false it creates holders
00368 //for the parameter values.In serializeMode_ == true it uses the inputs from the holders 
00369 //to generate the SOAP XML message
00370 void
00371 WsdlInvoker::serialize()
00372 {
00373   const Message * m = op_->getMessage(messageType_);
00374   if (!m)
00375     return;
00376   
00377   for (int i = 0 ;i<m->getNumParts();i++){
00378       
00379     Part::PartRefType prt = m->getPartRefType(i);
00380     const Part * p = m->getMessagePart(i);
00381     const SchemaParser * sParser = wParser_->getSchemaParser(p->schemaId());
00382     const std::string nsp = sParser->getNamespace();
00383     
00384     std::vector<std::string> parents;
00385     if (prt == Part::Elem){
00386       
00387       const Element * e = p->element();
00388       serializeType((Schema::Type)e->getType(),e->getName(),sParser,1,1,parents,nsp,true);
00389     }
00390     else{
00391       
00392       serializeType((Schema::Type)p->type(),p->name(),sParser,1,1,parents,nsp,true);
00393     }
00394   }
00395 }
00396 
00397 void
00398 WsdlInvoker::serializeType(Schema::Type typeId,
00399                            const std::string &tag,
00400                            const SchemaParser * sParser,
00401                            int minimum,
00402                            int maximum,
00403                            std::vector<std::string> parents,
00404                            const std::string nsp,
00405                            bool isRoot)
00406 {
00407   std::string t = tag;
00408   if (t == "*")
00409     t = "item";
00410 
00411 
00412   //for( std::vector<std::string>::iterator it=parents.begin();it!=parents.end();it++) std::cout<<*it; 
00413 
00414   const XSDType * pType = sParser->getType(typeId);
00415   if ( pType== 0 ||
00416        pType->isSimple() ||
00417        pType->getContentModel() == Schema::Simple){
00418     
00419     if (serializeMode_ == false){
00420       
00421       parents.push_back(tag);
00422       Parameter p(typeId,t,minimum,maximum,sParser,parents);
00423       elems_.push_back(p);
00424 
00425 #ifdef LOGGING
00426 
00427       std::cout<<"Adding input type "<<tag<<XmlUtils::dbsp
00428                <<sParser->getTypeName(typeId)<<XmlUtils::dbsp;
00429       std::cout<<sParser->getNamespace()<<std::endl;
00430 #endif
00431     }
00432     else{
00433       //generate the xml
00434       serializeParam(n_++,t,sParser,nsp,isRoot);
00435     }
00436   }
00437   else{
00438 
00439     if (serializeMode_){
00440       
00441       if (style_ == Soap::DOC ){
00442     
00443 
00444           if (sParser->getElementQualified()) {
00445             
00446             xmlStream_->startTag("",t);
00447             if (isRoot)
00448               xmlStream_->attribute("","xmlns",nsp);
00449           }
00450           else {
00451         
00452             if (isRoot) {
00453               xmlStream_->setPrefix(getPrefix(nsp),nsp);  
00454               xmlStream_->startTag(nsp,t);
00455             } 
00456             else {
00457               xmlStream_->startTag("",t);
00458             }
00459           }
00460         }
00461       
00462       else{
00463 
00464         xmlStream_->startTag("",t);
00465 
00466         //fix for sending SOAP arrays.add the soap arrayType attribute
00467         //works only for 1-D arrays
00468         const ComplexType* ct = static_cast<const ComplexType*>(pType);
00469         if(isSoapArray(ct,sParser)){
00470 
00471           std::string arrayName = ct->getName();
00472           arrayName = "ns:"+arrayName+"[1]";
00473           xmlStream_->attribute(Soap::soapEncUri,"arrayType",arrayName);
00474         }
00475       }
00476     }
00477     else {
00478       
00479       //complex types with multiple occurences
00480 
00481 
00482       //      parents.push_back(tag);
00483       //      Parameter p(typeId,t,minimum,maximum,sParser,parents);
00484       //      elems_.push_back(p);       TODO
00485       
00486     }
00487     
00488     
00489     const ComplexType * ct =
00490       static_cast<const ComplexType*>(pType);
00491     
00492     //complex types handling
00493     if (ct->getNumAttributes() > 0) {
00494       
00495       for (int i = 0; i < ct->getNumAttributes(); i++) {
00496           
00497         const Attribute*at = ct->getAttribute(i);
00498         /*
00499          * Check for the correctness of each attribute
00500          */
00501         if (at->isRequired()){
00502         
00503           if (serializeMode_ == false){
00504 
00505             std::vector<std::string> attparents(parents);
00506             attparents.push_back(tag);
00507             attparents.push_back("#" + at->getName() + "#");
00508             Parameter p((Schema::Type)at->getType(),at->getName(),elems_.size(),0,sParser,
00509                         attparents);
00510             elems_.push_back(p);
00511           }
00512           else{
00513             //generate the xml
00514             
00515             xmlStream_->attribute(sParser->getNamespace(),at->getName(),elems_[n_++].data_[0]);
00516           }
00517         }
00518         else
00519           continue;
00520       }
00521     }
00522   
00523     if (ct->getContentModel() == Schema::Simple) {
00524 
00525       if (serializeMode_ == false){
00526       
00527         parents.push_back(tag);
00528         Parameter p((Schema::Type)ct->getContentType(),tag,minimum,maximum,sParser,parents);
00529         elems_.push_back(p);
00530       }
00531       else{
00532         //generate the xml
00533         serializeParam(n_++,t,sParser,nsp,isRoot);
00534       }
00535     }
00536     else{
00537           
00538       ContentModel* cm=ct->getContents();
00539       if(cm){
00540 
00541         parents.push_back(tag);
00542         serializeContentModel(cm,sParser,parents);
00543       }
00544     }
00545 
00546     if (serializeMode_){
00547 
00548 
00549 
00550 
00551 
00552       if (style_ == Soap::DOC ){
00553     
00554         if (sParser->getElementQualified()) {
00555             
00556           xmlStream_->endTag("",t);
00557         }
00558         else {
00559           
00560           if (isRoot) {
00561             
00562             xmlStream_->endTag(nsp,t);
00563           } 
00564           else {
00565               xmlStream_->endTag("",t);
00566           }
00567         }
00568       }
00569       else{
00570         
00571         xmlStream_->endTag("",t);
00572 
00573 
00574       }
00575     }
00576   }
00577 }
00578 
00579 void
00580 WsdlInvoker::serializeContentModel(ContentModel *cm,
00581                                    const SchemaParser *sParser,
00582                                    std::vector<std::string> parents)
00583 {
00584   
00585   ContentModel::ContentsIterator cit_b=cm->begin();
00586   ContentModel::ContentsIterator cit_e=cm->end();
00587   ContentModel::ContentsIterator ci=cit_b;
00588 
00589         
00590   switch (cm->getCompositor())
00591     {
00592     case Schema::All:
00593     case Schema::Sequence:
00594     case Schema::Choice:
00595       {
00596         // a simple logic to start with
00597         // not taking care of all,choice ,sequence as of now
00598         
00599         for (ci=cit_b;ci!=cit_e;ci++){
00600           
00601           if(ci->second==ContentModel::Particle &&
00602              ci->first.e->getMax() > 0){
00603 
00604 
00605             const SchemaParser* s1Parser = sParser;
00606             bool isRoot = false;
00607             std::string nsp;
00608             Schema::Type t=(Schema::Type)ci->first.e->getType();
00609             
00610             if (!ci->first.e->getTypeNamespace().empty() &&
00611                 sParser->isImported(ci->first.e->getTypeNamespace()) &&
00612                 sParser->getNamespace() != ci->first.e->getTypeNamespace()) {
00613         
00614               //here the type of the element is defined in another imported schemaparser
00615               //so try to get the pointer.
00616               if ( !sParser->isBasicType(t)){ 
00617                   t = (Schema::Type)sParser->getType(t)->getTypeId();
00618                   sParser = sParser->getImportedSchemaParser(ci->first.e->getTypeNamespace());
00619               }
00620               if(ci->first.e->getNamespace() != s1Parser->getNamespace()){
00621                 nsp = ci->first.e->getNamespace();
00622                 isRoot = true ;// the element is from another namespace so need to qualify it
00623               }
00624                 
00625             }
00626            
00627             serializeType(t,
00628                           ci->first.e->getName(),
00629                           sParser,
00630                           ci->first.e->getMin(),
00631                           ci->first.e->getMax(),
00632                           parents,
00633                           nsp,isRoot);
00634             sParser = s1Parser;
00635           }
00636           else if (ci->second==ContentModel::Container) {
00637             
00638             //nested xsd:sequence inside choice..nested content models
00639             serializeContentModel(ci->first.c,
00640                                   sParser,
00641                                   parents);
00642               
00643           }
00644           else if (ci->second==ContentModel::ParticleGroup){
00645             
00646             //xsd:group inside 
00647             serializeContentModel(ci->first.g->getContents(),
00648                                   sParser,
00649                                   parents);
00650           }
00651         }
00652         break;
00653       }
00654     }
00655 }
00656 
00657 
00658 void
00659 WsdlInvoker::serializeParam(int n,const std::string & tag,
00660                             const SchemaParser * sParser,
00661                             const std::string nsp,
00662                             bool isRoot)
00663 {
00664 
00665   std::string t=tag;
00666   if (tag=="*")
00667     t="item";
00668     
00669   for (int i = 0 ;i<elems_[n].n_;i++){
00670 
00671     if (style_ == Soap::DOC){
00672 
00673       if (!isRoot)
00674         xmlStream_->startTag("",t);
00675       
00676       else {
00677         
00678         if (!nsp.empty())
00679           xmlStream_->setPrefix(getPrefix(nsp),nsp);
00680 
00681         xmlStream_->startTag(nsp,t);
00682 
00683       }
00684     }
00685     else{
00686       
00687         xmlStream_->startTag("",t);
00688         
00689         //xsi::type is needed for many SOAP servers
00690         if (sParser->isBasicType(elems_[n].type_) && 
00691             use_ == Soap::ENCODED){
00692           
00693           xmlStream_->attribute(Schema::SchemaInstaceUri,
00694                                 "type",
00695                                 "xsd:"+sParser->getTypeName(elems_[n].type_));
00696         }
00697     }
00698     
00699     xmlStream_->text(elems_[n].data_[i]);
00700     if (style_ == Soap::DOC && isRoot)
00701       xmlStream_->endTag(nsp,t);
00702     else
00703       xmlStream_->endTag("",t);
00704     
00705     
00706   }
00707 }
00708 
00709 
00710 bool
00711 WsdlInvoker::setInputValue(const int param,void** values,unsigned int occurs)
00712 {
00713 
00714   if (occurs < elems_[param].min_ ||
00715       occurs > elems_[param].max_)
00716     return false;
00717 
00718   SchemaValidator *sv = new SchemaValidator (elems_[param].sParser_);
00719   for (unsigned int i = 0 ;i < occurs ;i++){
00720       
00721     TypeContainer * tc = sv->validate(values[i],
00722                                       elems_[param].type_);
00723     if (!tc->isValueValid()){
00724         
00725       return false;
00726     }
00727     std::ostringstream oss;
00728     tc->print(oss);
00729     elems_[param].data_.push_back(oss.str());
00730     delete tc;
00731   }
00732   delete sv;
00733   
00734   elems_[param].n_ = occurs;
00735   return true;
00736 }
00737 
00738 bool
00739 WsdlInvoker::setInputValue(const int param,std::vector<std::string> values)
00740 {
00741 
00742 
00743   if (values.size() < elems_[param].min_ ||
00744       values.size() > elems_[param].max_)
00745     return false;
00746 
00747   SchemaValidator *sv = new SchemaValidator (elems_[param].sParser_);
00748   
00749   for (size_t i = 0 ;i < values.size() ;i++){
00750       
00751     TypeContainer * tc = sv->validate(values[i],
00752                                       elems_[param].type_);
00753     if (!tc->isValueValid()){
00754         
00755       return false;
00756     }
00757     elems_[param].data_.push_back(values[i]);
00758     delete tc;
00759   }
00760   delete sv;
00761   
00762   elems_[param].n_ = values.size();
00763   return true;
00764 }
00765 
00766 bool
00767 WsdlInvoker::setInputValue(const int param,std::string val)
00768 {
00769 
00770   const SchemaParser* sParser = elems_[param].sParser_;
00771   SchemaValidator *sv = new SchemaValidator (sParser);
00772   Schema::Type t = elems_[param].type_;
00773   const XSDType * pType = sParser->getType(t);
00774   if (pType && !pType->isSimple()){
00775 
00776     if (pType->getContentModel() != Schema::Simple)
00777       return false;
00778 
00779     const ComplexType * ct = static_cast<const ComplexType*>(pType);
00780     t = (Schema::Type)ct->getContentType();
00781   }
00782   
00783   TypeContainer * tc = sv->validate(val,t);
00784   if (!(tc && tc->isValueValid())){
00785         
00786     return false;
00787   }
00788   if (elems_[param].data_.size() == 0)
00789     elems_[param].data_.push_back(val);
00790   else
00791     elems_[param].data_[0]=val;
00792 
00793   delete tc;
00794     
00795   delete sv;
00796   
00797   elems_[param].n_ = 1;
00798   return true;
00799 }
00800 
00801 
00802 
00803 bool
00804 WsdlInvoker::setInputValue(const int param,void* val)
00805 {
00806 
00807   const SchemaParser*  sParser = elems_[param].sParser_;
00808   SchemaValidator *sv = new SchemaValidator (sParser);
00809   Schema::Type t = elems_[param].type_;
00810   const XSDType * pType = sParser->getType(t);
00811   if (pType && !pType->isSimple()){
00812 
00813     if (pType->getContentModel() != Schema::Simple)
00814       return false;
00815 
00816     const ComplexType * ct = static_cast<const ComplexType*>(pType);
00817     t = (Schema::Type)ct->getContentType();
00818   }
00819 
00820   TypeContainer * tc = sv->validate(val,t);
00821   if (!(tc && tc->isValueValid())){
00822         
00823     return false;
00824   }
00825   std::ostringstream oss;
00826   tc->print(oss);
00827   if (elems_[param].data_.size() == 0)
00828     elems_[param].data_.push_back(oss.str());
00829   else
00830     elems_[param].data_[0]=oss.str();
00831   delete tc;
00832   delete sv;
00833   elems_[param].n_ = 1;
00834   return true;
00835 }
00836 
00837 bool
00838 WsdlInvoker::setValue(const std::string & param,void* val)
00839 {
00840   for (size_t s = 0;s<elems_.size();s++){
00841     
00842     if (elems_[s].tag_ == param)
00843       return setInputValue(s,val);
00844   }
00845   return false;
00846 }
00847 
00848 bool
00849 WsdlInvoker::setValue(const std::string & param,void** values,unsigned int occur)
00850 {
00851 
00852   for (size_t s = 0;s<elems_.size();s++){
00853     
00854     if (elems_[s].tag_ == param)
00855       return setInputValue(s,values,occur);
00856   }
00857   return false;
00858 }
00859  
00860 bool
00861 WsdlInvoker::setValue(const std::string & param,std::string val)
00862 {
00863   for (size_t s = 0;s<elems_.size();s++){
00864     
00865     if (elems_[s].tag_ == param)
00866       return setInputValue(s,val);
00867   }
00868   return false;
00869 }
00870 
00871 bool
00872 WsdlInvoker::setValue(const std::string & param,std::vector<std::string> values)
00873 {
00874   for (size_t s = 0;s<elems_.size();s++){
00875     
00876     if (elems_[s].tag_ == param)
00877       return setInputValue(s,values);
00878   }
00879   return false;
00880 }
00881 
00882 
00883 std::string
00884 WsdlInvoker::getSoapMessage(){
00885 
00886   dontPost_ = true;
00887   invoke();
00888   return soapstr_->str();
00889 }
00890 
00891 
00892 
00893 bool
00894 WsdlInvoker::invoke(long timeout)
00895 {
00896 
00897 try{
00898     
00899   if (xmlStream_){
00900     
00901     delete xmlStream_;
00902   }
00903   if (soapstr_){
00904     
00905     delete soapstr_;
00906   }
00907   if (results_){
00908     delete results_;
00909     results_ = 0;
00910   }
00911 
00912 
00913   for (size_t x = 0;x<outputs_.size();x++)
00914     delete outputs_[x].second;
00915 
00916   outputs_.clear();
00917 
00918   soapstr_ = new std::ostringstream();
00919   xmlStream_ = new XmlSerializer(*soapstr_);
00920 
00921   serializeMode_ = true;
00922 
00923   xmlStream_->startDocument("UTF-8",false);
00924   xmlStream_->setPrefix("SOAP-ENV",Soap::soapEnvUri);
00925   xmlStream_->setPrefix("SOAP-ENC",Soap::soapEncUri);
00926   xmlStream_->setPrefix("xsd",Schema::SchemaUri);
00927   xmlStream_->setPrefix("xsi",Schema::SchemaInstaceUri);
00928   xmlStream_->setPrefix(getPrefix(nsp_),nsp_);
00929   xmlStream_->startTag(Soap::soapEnvUri,"Envelope");
00930   
00931   if (style_ == Soap::RPC) {
00932     
00933     xmlStream_->attribute(Soap::soapEnvUri,
00934                           "encodingStyle",
00935                           Soap::soapEncUri);
00936   }
00937 
00938   n_ = 0;
00939   if (soapheaders_){
00940     xmlStream_->startTag(Soap::soapEnvUri,"Header");
00941     serializeHeader();
00942     xmlStream_->endTag(Soap::soapEnvUri,"Header");
00943   }
00944 
00945   xmlStream_->startTag(Soap::soapEnvUri,"Body");
00946   if (style_ == Soap::RPC){
00947     
00948     xmlStream_->startTag(nsp_,op_->getName());
00949   }
00950 
00951   serialize();
00952   if (style_ == Soap::RPC){
00953     xmlStream_->endTag(nsp_,op_->getName());
00954   }
00955 
00956   xmlStream_->endTag(Soap::soapEnvUri,"Body");
00957   xmlStream_->endTag(Soap::soapEnvUri,"Envelope");
00958   xmlStream_->flush();
00959   
00960 
00961 
00962   //test
00963   //status_ = true;
00964   //processResults();
00965   //return status_;
00966   //test
00967   if (dontPost_)
00968     return true;
00969 
00970   post(timeout);
00971   if (results_){
00972     processResults();
00973     if (status_)
00974       return true;
00975   }
00976   else{
00977     
00978     logger_<<"Couldnt connect to "<<location_;
00979   }
00980     
00981   return false;
00982 
00983 }
00984 catch (WsdlException we)
00985   {
00986     logger_<<"A WSDL exception occurred at"<<we.line
00987            <<":"<<we.col<<std::endl;
00988     logger_<<we.description<<std::endl;
00989     return false;
00990   }
00991 catch (SchemaParserException spe)
00992   {
00993     logger_<<"A Schema Parser exception occurred at "<<spe.line
00994            <<":"<<spe.col<<std::endl;
00995     logger_<<spe.description<<std::endl;
00996     return false;
00997   }
00998 catch (XmlPullParserException xpe)
00999   {
01000     logger_<<"An Xml Parsing exception occurred at row:col "<<xpe.line
01001            <<":"<<xpe.col<<std::endl;
01002     logger_<<xpe.description<<std::endl;
01003     return false;
01004   }
01005 }
01006 
01007 int
01008 WsdlInvoker::getNextInput(std::string & param ,Schema::Type & type,int & minimum,int & maximum)
01009 {
01010   std::vector<std::string> parents;
01011   return getNextInput(param, type, minimum, maximum, parents);
01012 }
01013 
01014 int
01015 WsdlInvoker::getNextInput(std::string & param ,Schema::Type & type,int & minimum,int & maximum,
01016                           std::vector<std::string> & parents)
01017 {
01018   if (n_ < elems_.size()){
01019     
01020     param = elems_[n_].tag_;
01021     type = elems_[n_].type_;
01022     minimum = elems_[n_].min_;
01023     parents = elems_[n_].parents_;
01024     maximum = elems_[n_].max_;
01025     return n_++;
01026   }
01027   else{
01028     return -1;
01029   }
01030 }
01031 
01032 int
01033 WsdlInvoker::getNextHeaderInput(std::string & param ,Schema::Type & type,
01034                                 int & minimum,int & maximum)
01035 {
01036 
01037   std::vector<std::string> parents;
01038   return getNextHeaderInput(param,type,minimum,maximum,parents);
01039 }
01040 
01041 int
01042 WsdlInvoker::getNextHeaderInput(std::string & param ,Schema::Type & type,
01043                                 int & minimum,int & maximum,
01044                                 std::vector<std::string> & parents)
01045 {
01046   static int h = 0;
01047   if (h<iHeaders_){
01048     param = elems_[h].tag_;
01049     type = elems_[h].type_;
01050     minimum = elems_[h].min_;
01051     maximum = elems_[h].max_;
01052     parents = elems_[h].parents_;
01053     return h++;
01054   }
01055   else{
01056     h = 0;
01057     return -1;
01058   }
01059 }
01060 
01061 void
01062 WsdlInvoker::processResults()
01063 {
01064   try{
01065 
01066     const Message* m = op_->getMessage(WsdlPull::Output);
01067     std::istringstream respstr(results_);
01068     //    std::ifstream respstr("r.xml");//test
01069     XmlPullParser* xpp = new XmlPullParser(respstr);
01070     xpp->setFeature (FEATURE_PROCESS_NAMESPACES, true);
01071     xpp->require (XmlPullParser::START_DOCUMENT, "", "");
01072 
01073     while (xpp->getEventType () != XmlPullParser::END_DOCUMENT) {
01074 
01075       if (xpp->getEventType () == XmlPullParser::END_DOCUMENT)
01076         break;
01077       
01078       if (xpp->getEventType () == XmlPullParser::END_TAG &&
01079           xpp->getName() == "Envelope" &&
01080           xpp->getNamespace() ==  Soap::soapEnvUri)
01081         break;
01082         
01083       if (xpp->getEventType () != XmlPullParser::START_TAG){
01084         xpp->nextToken ();
01085         continue;
01086       }
01087       
01088       xpp->nextTag ();
01089       Qname elemName (xpp->getName ());
01090       elemName.setNamespace(xpp->getNamespace());
01091       
01092       if (elemName.getNamespace() == Soap::soapEnvUri){
01093         
01094         if (elemName.getLocalName() == "Fault"){
01095           processFault(xpp);
01096           status_ = false;
01097           return;
01098         } 
01099         else if (elemName.getLocalName() == "Header"){
01100 
01101           processHeader(xpp);
01102         }
01103         if (elemName.getLocalName() == "Body"){
01104 
01105           xpp->nextTag();
01106           processBody(m,xpp);
01107         }
01108         continue; //ignore soap:Body and soap:Envelope tags
01109       }
01110     }
01111     delete xpp;
01112     n_ = oHeaders_;
01113   }
01114   catch (WsdlException we)
01115     {
01116       logger_<<"A WSDL exception occurred while parsing the response at line "<<we.line
01117              <<":"<<we.col<<std::endl;
01118       logger_<<we.description<<std::endl;
01119       status_ =false;
01120     }
01121   catch (SchemaParserException spe)
01122     {
01123       logger_<<"A Schema Parser exception occurred while parsing the response at line "<<spe.line
01124              <<":"<<spe.col<<std::endl;
01125       logger_<<spe.description<<std::endl;
01126       status_ =false;
01127     }
01128   catch (XmlPullParserException xpe)
01129     {
01130       logger_<<"An Xml Parsing exception occurred while parsing the response at line "<<xpe.line
01131              <<":"<<xpe.col<<std::endl;
01132       logger_<<xpe.description<<std::endl;
01133       status_ =false;
01134     }
01135   return;
01136 }
01137 
01138 WsdlInvoker::~WsdlInvoker()
01139 {
01140   reset();
01141   if (ourParser_){  
01142       delete ourParser_;
01143   }
01144   if (xmlStream_){
01145     
01146     delete xmlStream_;
01147   }
01148   if (soapstr_){
01149     
01150     delete soapstr_;
01151   }
01152 }
01153 
01154 void
01155 WsdlInvoker::reset()
01156 {
01157   n_ =  iHeaders_ = oHeaders_ = 0;
01158   elems_.clear();
01159 
01160   for (size_t x = 0;x<outputs_.size();x++)
01161     delete outputs_[x].second;
01162 
01163   outputs_.clear();
01164   serializeMode_ = false;
01165 }
01166 
01167 bool 
01168 WsdlInvoker::getNextOutput(std::string & name,TypeContainer * & tc)
01169 {
01170   if (status_ && n_ < outputs_.size()){
01171     
01172     name = outputs_[n_].first;
01173     tc = outputs_[n_].second;
01174     n_++;
01175     return true;
01176   }
01177   n_ = oHeaders_;
01178   return false;
01179 }
01180 
01181 
01182 TypeContainer*
01183 WsdlInvoker::getOutput(const std::string  & name)
01184 {
01185   for (unsigned int i = 0 ;status_ && i <outputs_.size();i++){
01186 
01187     if ( name == outputs_[i].first)
01188       return outputs_[i].second;
01189   }
01190   return 0;
01191 }
01192 
01193 bool
01194 WsdlInvoker::getNextHeaderOutput(std::string & name,TypeContainer*& tc)
01195 {
01196   static int j = 0;
01197   if(j<oHeaders_){
01198     name = outputs_[j].first;
01199     tc = outputs_[j].second;
01200     j++;
01201     return true;
01202   }
01203   else{
01204     j = 0;
01205     return false;
01206   }
01207 }
01208 
01209 void * 
01210 WsdlInvoker::getValue(const std::string  & name ,Schema::Type & t)
01211 {
01212   for (unsigned int i = 0 ;status_ && i <outputs_.size();i++){
01213 
01214     if (outputs_[i].second!=0){
01215       outputs_[i].second->rewind();
01216       void * tmp= outputs_[i].second->getValue(name,t);
01217       if (tmp)
01218         return tmp;
01219     }
01220   }
01221   return 0;
01222 }
01223 
01224 
01225 
01226 void
01227 WsdlInvoker::post(long timeout, std::string username, std::string passwd)
01228 {
01229   const std::string  postData = soapstr_->str();
01230   if(verbose_){
01231     
01232     std::ofstream ofs("request.log",std::ios::app);
01233     ofs<<postData;
01234     ofs<<std::endl;
01235     ofs.flush();
01236   }
01237     
01238 #ifdef WITH_CURL
01239   CURL * ctx=0;
01240   CURLcode res;
01241   curl_global_init( CURL_GLOBAL_ALL ) ;
01242   ctx=curl_easy_init();
01243   int bufsize = 0;
01244   if (!ctx)
01245     return ;
01246   curl_easy_setopt( ctx , CURLOPT_URL,  location_.c_str()) ;
01247 
01248   curl_easy_setopt( ctx , CURLOPT_NOPROGRESS , 1 ) ;
01249   if(timeout){
01250     curl_easy_setopt( ctx ,CURLOPT_TIMEOUT, timeout);
01251   }
01252 
01253   if (verbose_) {
01254     curl_easy_setopt( ctx , CURLOPT_VERBOSE,1);
01255     curl_easy_setopt( ctx , CURLOPT_NOPROGRESS , 0 ) ;
01256   }
01257 
01258   curl_easy_setopt( ctx , CURLOPT_POST , 1 );
01259   curl_easy_setopt( ctx , CURLOPT_POSTFIELDS , postData.c_str()) ;
01260   curl_slist* responseHeaders = NULL ;
01261   std::string tmp="SOAPAction: ";
01262   tmp.push_back('"');
01263   tmp+=action_;
01264   tmp.push_back('"');
01265   responseHeaders = curl_slist_append( responseHeaders , tmp.c_str());
01266   responseHeaders = curl_slist_append( responseHeaders ,"Content-Type: text/xml; charset=UTF-8");
01267   responseHeaders = curl_slist_append( responseHeaders ,"Accept: text/xml;");
01268   curl_easy_setopt( ctx , CURLOPT_HTTPHEADER , responseHeaders ) ;
01269   tmp = "wsdlpull";
01270 #ifdef HAVE_CONFIG_H
01271   tmp=tmp+"/"+VERSION;
01272 #endif
01273   curl_easy_setopt( ctx,CURLOPT_USERAGENT,tmp.c_str());
01274   curl_easy_setopt( ctx,CURLOPT_POSTFIELDSIZE,postData.length());
01275   
01276   if (XmlUtils::getProxy()){
01277     curl_easy_setopt(ctx,CURLOPT_PROXY,XmlUtils::getProxyHost().c_str());
01278     tmp=XmlUtils::getProxyUser()+":"+XmlUtils::getProxyPass();
01279     curl_easy_setopt(ctx,CURLOPT_PROXYUSERPWD,tmp.c_str());
01280   }
01281   curl_easy_setopt( ctx ,CURLOPT_WRITEDATA ,&bufsize) ;
01282   curl_easy_setopt( ctx ,CURLOPT_WRITEFUNCTION,storeResults) ;
01283   
01284   // std::logger_ << "- - - BEGIN: response - - -" << std::endl ;
01285   res=curl_easy_perform(ctx);
01286   //  std::logger_ << "- - - END: response - - -" << std::endl ;
01287 
01288   curl_slist_free_all( responseHeaders ) ;
01289   curl_easy_cleanup( ctx ) ;
01290   curl_global_cleanup() ;
01291   
01292 
01293 #elif _WIN32
01294   XmlUtils::winPost(location_,username,passwd,postData,action_,results_);
01295 #endif
01296 
01297   if(verbose_ && results_){
01298     
01299     std::ofstream ofs("response.log",std::ios::app);
01300     ofs<<results_;
01301     ofs<<std::endl;
01302     ofs.flush();
01303   }
01304 
01305 }
01306 
01307 void
01308 WsdlInvoker::printTypeNames(bool f)
01309 {
01310   TypeContainer::printTypeNames_ = false;
01311 }
01312 
01313 
01314 void
01315 WsdlInvoker::processFault(XmlPullParser* xpp)
01316 {
01317 
01318   while (!(xpp->getEventType () == XmlPullParser::END_TAG &&
01319            xpp->getName() == "Fault")) {
01320     
01321     if (xpp->getEventType() == XmlPullParser::START_TAG &&
01322         xpp->getName() == "faultcode"){
01323       
01324       xpp->next();
01325       logger_<<"SOAP Fault Code: "<<xpp->getText()<<std::endl;
01326     }
01327     
01328     if (xpp->getEventType() == XmlPullParser::START_TAG &&
01329         xpp->getName() == "faultstring"){
01330       
01331       xpp->next();
01332       logger_<<"SOAP Fault String: "<<xpp->getText()<<std::endl;
01333     }
01334     if (xpp->getEventType() == XmlPullParser::START_TAG &&
01335         xpp->getName() == "faultactor"){
01336       
01337       xpp->next();
01338       logger_<<"SOAP Fault Actor: "<<xpp->getText()<<std::endl;
01339     }
01340     xpp->next();
01341   }
01342 }
01343 
01344 void 
01345 WsdlInvoker::processBody(const Message* m,
01346                          XmlPullParser* xpp)
01347 {
01348   
01349   if (xpp->getName() == "Fault") {
01350     
01351     processFault(xpp);
01352     status_ = false;
01353     return;
01354   }
01355 
01356   if (style_ == Soap::RPC && use_==Soap::ENCODED){
01357           
01358     if (xpp->getName () == op_->getName()+"Response") {
01359 
01360       //operation's name followed by 'Response' must be the containing element
01361       xpp->nextTag ();
01362       
01363       do {
01364       
01365         
01366         //first look for xsi:type
01367         Qname typ(xpp->getAttributeValue(Schema::SchemaInstaceUri, "type"));
01368         typ.setNamespace(xpp->getNamespace(typ.getPrefix()));
01369         const SchemaParser * sParser = 0;
01370         int typeId = 0;
01371           
01372         if (!(typ.getNamespace() == Soap::soapEncUri &&
01373               typ.getLocalName() == "Array"))//for soap array just use the part's type info
01374           sParser= wParser_->getSchemaParser(typ.getNamespace());
01375           
01376         if (sParser){
01377             
01378           typeId = (const_cast<SchemaParser*>(sParser))->getTypeId(typ);
01379         }
01380         else{
01381 
01382           //if xsi:type doesnt give a clue then see if the part name matches
01383           const Part * p = m->getMessagePart(xpp->getName ());
01384           if (p){
01385             
01386             sParser = wParser_->getSchemaParser(p->schemaId());
01387             typeId = p->type();
01388           }else {
01389 
01390 
01391           }
01392         }
01393         if (sParser && typeId !=0){  
01394             
01395           SchemaValidator * sv= new SchemaValidator(sParser);     
01396           std::string tag = xpp->getName();
01397           TypeContainer * t = sv->validate (xpp, typeId);
01398           outputs_.push_back(std::pair<std::string,TypeContainer*>(tag,t));
01399           xpp->nextTag();
01400           delete sv;
01401         }
01402         else{
01403 
01404           status_ = false;
01405           logger_<<"Unknown element "<<xpp->getName()<<std::endl;
01406           return;
01407         }
01408       } while (!(xpp->getName() == op_->getName()+"Response" &&
01409                  xpp->getEventType() == XmlPullParser::END_TAG));
01410     }
01411   }
01412   else{
01413     
01414     while (!(xpp->getName() == "Body" && 
01415              xpp->getNamespace() == Soap::soapEnvUri &&
01416              xpp->getEventType() == XmlPullParser::END_TAG)) {
01417              
01418       Qname elemName (xpp->getName ());
01419       elemName.setNamespace(xpp->getNamespace());
01420 
01421       //doc/literal has ref type element in the part
01422       const SchemaParser * sParser =
01423         wParser_->getSchemaParser(elemName.getNamespace());
01424       if (!sParser){
01425           
01426         status_ = false;
01427         logger_<<"Unknown element "<<elemName<<std::endl;
01428         return;
01429       }
01430       SchemaValidator * sv= new SchemaValidator(sParser);         
01431           
01432       const Element * e = sParser->getElement (elemName);
01433       if(e){
01434         int typeId = e->getType () ;
01435         TypeContainer * t = sv->validate (xpp, typeId);
01436         std::pair<std::string,TypeContainer*> pr(elemName.getLocalName(),t);
01437         outputs_.push_back(pr);
01438       }
01439       else{
01440         status_ = false;
01441         std::cerr<<"Unkown element "<<elemName.getLocalName()<<std::endl;
01442         return;
01443       }
01444       delete sv;
01445       xpp->nextTag();
01446     }
01447   }
01448   status_ = true;
01449 }
01450 
01451 void
01452 WsdlInvoker::processHeader(XmlPullParser *xpp)
01453 {
01454   Qname elem;
01455   const SchemaParser * sParser = 0;
01456   int type = Schema::XSD_INVALID;
01457   xpp->nextTag ();
01458   std::string tag = xpp->getName();
01459 
01460   while (!(xpp->getEventType() == XmlPullParser::END_TAG &&
01461            xpp->getName() == "Header")){
01462 
01463 
01464     //first look for xsi:type
01465     if (xpp->getAttributeValue(Schema::SchemaInstaceUri, "type") != "" ) {
01466       
01467       elem = Qname(xpp->getAttributeValue(Schema::SchemaInstaceUri, "type"));
01468       elem.setNamespace(xpp->getNamespace(elem.getPrefix()));
01469       sParser= wParser_->getSchemaParser(elem.getNamespace());
01470       type = (const_cast<SchemaParser*>(sParser))->getTypeId(elem);  
01471     }
01472     else {
01473 
01474       elem = Qname(xpp->getName());
01475       elem.setNamespace(xpp->getNamespace());      
01476       sParser=wParser_->getSchemaParser(elem.getNamespace());
01477       const Element * e = sParser->getElement (elem);
01478       if(e){
01479              type = e->getType ();
01480       }
01481     }
01482     SchemaValidator * sv= new SchemaValidator(sParser);   
01483     TypeContainer * t = sv->validate (xpp, type);
01484     outputs_.push_back(std::pair<std::string,TypeContainer*>(tag,t));
01485     oHeaders_++; 
01486     xpp->nextTag();
01487     delete sv;
01488   }
01489   xpp->nextTag();   
01490 }
01491 
01492 bool
01493 WsdlInvoker::isSoapArray (const ComplexType * ct,
01494                           const SchemaParser * sParser)
01495 {
01496   const XSDType * baseType=sParser->getType(ct->getBaseTypeId());
01497   if (baseType) {
01498     if(baseType->getNamespace()==Soap::soapEncUri &&
01499        baseType->getName()=="Array")
01500       return true;
01501   }
01502   return false;
01503 }
01504 
01505 void
01506 WsdlInvoker::setCredentials(const std::string & user, const std::string & pass)
01507 {
01508   username_ = user;
01509   password_ = pass;
01510   XmlUtils::setProxyUser(user);
01511   XmlUtils::setProxyPass(pass);
01512   XmlUtils::setProxy(true);
01513 }
01514 
01515 void
01516 WsdlInvoker::setProxy(const std::string & host,int  port)
01517 {
01518   host_ = host;
01519   port_ = port;
01520   std::ostringstream oss;
01521   oss<<host<<":"<<port;
01522   XmlUtils::setProxyHost(oss.str());
01523   XmlUtils::setProxy(true);
01524 }
01525 
01526 std::string
01527 WsdlInvoker::getPrefix(const std::string & nsp)
01528 {
01529   
01530   unsigned int i = 0;
01531   char prefix='1';
01532   while (i<prefixes_.size()) {
01533     if (prefixes_[i] == nsp)
01534       break;
01535     i++;
01536   }
01537 
01538   std::string tmp("ns");
01539   tmp.append(1,prefix+i);
01540   if (i == prefixes_.size())
01541     prefixes_.push_back(nsp);
01542   
01543   return tmp;
01544 
01545 }
01546 
01547 }
01548 
01549 size_t
01550 storeResults(void * buf,size_t sz,size_t nmemb,void* userdata)
01551 {
01552   int *bufsize= (int*)userdata;
01553   if (results_ == 0){
01554     
01555     results_ = (char*)malloc(sizeof(char) * sz * nmemb);
01556   }
01557   else{
01558     results_ = (char*) realloc(results_,sizeof(char) * sz * nmemb+ (*bufsize));
01559   }
01560   memcpy (results_+(*bufsize),buf,sz*nmemb);
01561   *bufsize+=sz*nmemb;
01562   return sz*nmemb;
01563 }

Generated on Sat May 3 16:29:00 2008 for wsdlpull by  doxygen 1.4.6