1 /*
2  * wsdlpull - A C++ parser  for WSDL  (Web services description language)
3  * Copyright (C) 2005-2007 Vivek Krishna
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 #ifdef  WITH_CURL
24 #include <curl/curl.h>
25 #endif
26 
27 #include <iostream>
28 using namespace std;
29 
30 #include "wsdlparser/WsdlInvoker.h"
31 
32 
33 
34 #ifdef WITH_CURL
35 size_t storeResults(void * buf, size_t sz, size_t nmemb, void* userdata);
36 #endif
37 
38 namespace WsdlPull {
39 
WsdlInvoker()40 WsdlInvoker::WsdlInvoker()
41   :wParser_(0),
42    ourParser_(0),
43    xmlStream_(0),
44    soap_(0),
45    soapheaders_(false),
46    hPartId_(-1),
47    soapstr_(0),
48    status_(false),
49    serializeMode_(false),
50    verbose_(false),
51    dontPost_(false),
52    oHeaders_(0),
53    op_(0),
54    n_(0),
55    iHeaders_(0),
56    messageType_(WsdlPull::Input),
57    bAuth(false),
58    ctx(0),
59    m_buildXmlTree( false),
60    m_xmlTreeProduced( false)
61 {
62 }
63 
WsdlInvoker(std::istream & input,const std::string & schemaPath)64 WsdlInvoker::WsdlInvoker(std::istream &input, const std::string &schemaPath)
65   :wParser_(0),
66    ourParser_(0),
67    xmlStream_(0),
68    soap_(0),
69    soapheaders_(false),
70    hPartId_(-1),
71    soapstr_(0),
72    status_(false),
73    serializeMode_(false),
74    verbose_(false),
75    dontPost_(false),
76    op_(0),
77    n_(0),
78    iHeaders_(0),
79    messageType_(WsdlPull::Input),
80    bAuth(false),
81    ctx(0),
82    m_buildXmlTree( false),
83    m_xmlTreeProduced( false)
84 {
85   try{
86     wParser_ = new WsdlParser(input,logger_, schemaPath);
87     ourParser_= wParser_;
88     if (wParser_){
89       //parse the web service
90       while (wParser_->getNextElement () != WsdlParser::END);
91       if (wParser_->status()){
92 
93         status_=true;
94         init(wParser_);
95       }
96     }
97   }
98   catch (WsdlException we)
99   {
100     logger_<<"An exception  occurred at "<<we.line
101     <<":"<<we.col<<std::endl;
102     logger_<<we.description<<std::endl;
103     status_ =false;
104   }
105   catch (SchemaParserException spe)
106   {
107     logger_<<"An exception occurred at "<<spe.line
108     <<":"<<spe.col<<std::endl;
109     logger_<<spe.description<<std::endl;
110     status_ =false;
111   }
112   catch (XmlPullParserException xpe)
113   {
114     logger_<<"An exception occurred at "<<xpe.line
115     <<":"<<xpe.col<<std::endl;
116     logger_<<xpe.description<<std::endl;
117     status_= false;
118   }
119 }
120 
WsdlInvoker(const std::string & url,const std::string & schemaPath)121 WsdlInvoker::WsdlInvoker(const std::string & url, const std::string & schemaPath)
122    :wParser_(0),
123     ourParser_(0),
124     xmlStream_(0),
125     soap_(0),
126     soapheaders_(false),
127     hPartId_(-1),
128     soapstr_(0),
129     status_(false),
130     serializeMode_(false),
131     verbose_(false),
132     dontPost_(false),
133     op_(0),
134     n_(0),
135     iHeaders_(0),
136     messageType_(WsdlPull::Input),
137     bAuth(false),
138     ctx(0),
139     m_buildXmlTree( false),
140     m_xmlTreeProduced( false)
141 {
142   parseWsdl(url, schemaPath);
143 }
144 
145 
146 void
parseWsdl(const std::string & url,const std::string & schemaPath)147 WsdlInvoker::parseWsdl(const std::string & url, const std::string & schemaPath)
148 {
149   try{
150     wParser_ = new WsdlParser(url,logger_, schemaPath);
151     ourParser_= wParser_;
152     if (wParser_){
153       //parse the web service
154       while (wParser_->getNextElement () != WsdlParser::END);
155       if (wParser_->status()){
156 
157 	status_=true;
158 	init(wParser_);
159       }
160     }
161   }
162     catch (WsdlException we)
163       {
164        logger_<<"An exception  occurred at "<<we.line
165   	     <<":"<<we.col<<std::endl;
166         logger_<<we.description<<std::endl;
167         status_ =false;
168       }
169     catch (SchemaParserException spe)
170       {
171        logger_<<"An exception occurred at "<<spe.line
172   	     <<":"<<spe.col<<std::endl;
173         logger_<<spe.description<<std::endl;
174         status_ =false;
175       }
176     catch (XmlPullParserException xpe)
177       {
178        logger_<<"An exception occurred at "<<xpe.line
179   	     <<":"<<xpe.col<<std::endl;
180        logger_<<xpe.description<<std::endl;
181        status_= false;
182       }
183 }
184 
185 bool
init(WsdlParser * parser)186 WsdlInvoker::init(WsdlParser* parser)
187 {
188   try{
189     wParser_ = parser;
190     status_ = wParser_->status();
191 
192     if (status_){
193 
194       PortType::cPortTypeIterator p1,p2;
195       wParser_->getPortTypes(p1,p2);
196       int i=0;
197 
198       while(p1!=p2){
199 
200 	Operation::cOpIterator op1,op2;
201 	(*p1)->getOperations(op1,op2);
202 	bool bn = (*p1)->binding(Soap::soapBindingUri11) || (*p1)->binding(Soap::soapBindingUri12) ;
203 	//if neither SOAP1.1 or SOAP1.2 bindings are available for a port type skip it
204 	///eventually we should add a test to check for all supported bindings in the invoker
205 	if (!bn){
206 	  p1++;
207 	  continue;
208 	}
209 
210 	while(op1!=op2){
211 
212 	  opMap_[(*op1)->getName()]=*op1;
213 	  op1++;
214 	  i++;
215 	}
216 	p1++;
217       }
218     }
219   }
220   catch (WsdlException we)
221     {
222       logger_<<"A WSDL exception occurred at"<<we.line
223 	     <<":"<<we.col<<std::endl;
224       logger_<<we.description<<std::endl;
225       status_ =false;
226     }
227   catch (SchemaParserException spe)
228     {
229       logger_<<"A Schema Parser exception occurred at "<<spe.line
230 	     <<":"<<spe.col<<std::endl;
231       logger_<<spe.description<<std::endl;
232       status_ =false;
233     }
234   catch (XmlPullParserException xpe)
235     {
236       logger_<<"An Xml Parsing exception occurred at row:col "<<xpe.line
237 	     <<":"<<xpe.col<<std::endl;
238       logger_<<xpe.description<<std::endl;
239       status_ =false;
240     }
241   return status_;
242 }
243 
244 int
getOperations(std::vector<std::string> & operations)245 WsdlInvoker::getOperations(std::vector<std::string> & operations)
246 {
247   int i = 0;
248   for(
249   std::map<std::string,const Operation*>::iterator it =
250     opMap_.begin();
251   it != opMap_.end();
252   it++,i++){
253 
254     operations.push_back(it->first);
255   }
256   return i;
257 }
258 
259 std::string
getDocumentation()260 WsdlInvoker::getDocumentation()
261 {
262   std::stringstream result;
263   result << wParser_->getDocumentation();
264   return result.str();
265 }
266 
267 std::string
getOpDocumentation(const std::string & n)268 WsdlInvoker::getOpDocumentation(const std::string & n)
269 {
270 
271   std::map<std::string,const Operation*>::iterator it =
272     opMap_.find(n);
273 
274   if (it != opMap_.end()){
275 
276     return  it->second->getDocumentation();
277   }
278   return "";
279 }
280 
281 bool
setOperation(const std::string & opname,WsdlPull::MessageType mType)282 WsdlInvoker::setOperation(const std::string & opname,
283 			  WsdlPull::MessageType mType)
284 {
285   reset();
286   messageType_ = mType;
287    std::map<std::string,const Operation*>::iterator it =
288     opMap_.find(opname);
289 
290   if (it != opMap_.end()){
291 
292     op_ = it->second;
293 
294     getOperationDetails(op_);
295     if (!status_)
296       return false;
297 
298     if (soapheaders_){
299       serializeHeader();
300     }
301     serialize();
302     n_ = iHeaders_;
303     return status_;
304   }
305   else{
306     return false;
307   }
308 }
309 
310 std::string
getServiceEndPoint(const std::string & opname)311 WsdlInvoker::getServiceEndPoint(const std::string & opname)
312 {
313 
314   reset();
315   location_="";
316   std::map<std::string,const Operation*>::iterator it =
317     opMap_.find(opname);
318 
319   if (it != opMap_.end()){
320 
321     const Operation* op = it->second;
322 
323     getOperationDetails(op);
324     reset();
325   }
326   return location_;
327 }
328 
329 void
getOperationDetails(const Operation * op)330 WsdlInvoker::getOperationDetails(const Operation* op)
331 {
332 
333   const Binding * bnSoap = 0;
334   bnSoap = op->portType()->binding(Soap::soapBindingUri11);
335   if (bnSoap) {
336 
337     soap_ = static_cast<Soap*> (wParser_->getExtensibilityHandler(Soap::soapBindingUri11));
338   }else {
339 
340     bnSoap = op->portType()->binding(Soap::soapBindingUri12);
341     soap_ = static_cast<Soap*> (wParser_->getExtensibilityHandler(Soap::soapBindingUri12));
342 
343   }
344 
345   ///get various soap properties
346   soap_->getServiceLocation (bnSoap->getServiceExtId (),location_);
347   style_ = soap_->getStyle();
348 
349   if (location_.empty()){
350 
351     logger_<<"No service location specified for SOAP binding "<<bnSoap->getName()<<std::endl;
352     status_ = false;
353     return;
354   }
355   //get the soap:operation's SOAPAction and style
356   const int *bindings = 0;
357   int opIndex  = bnSoap->getOperationIndex(op->getName());
358   bnSoap->getOpBinding (opIndex, bindings);
359   int soapOpBindingId = bindings[0];
360   //operation's style over rides
361   soap_->getSoapOperationInfo (soapOpBindingId, action_, style_);
362 
363   //get the soap:body namespace and use attributes
364   int nBindings=bnSoap->getInputBinding(opIndex,bindings);
365   //get the body and header
366   for (int x=0;x<nBindings;x++){
367     if (soap_->isSoapBody(bindings[x])){
368 
369       soap_->getSoapBodyInfo(bindings[x],nsp_,use_,encodingStyle_);
370     }
371     if (soap_->isSoapHeader(bindings[x]))
372       soapheaders_ = true;
373 
374   }
375 
376   if (nsp_.empty()){
377 
378     nsp_ = wParser_->getNamespace();
379   }
380 }
381 
382 void
serializeHeader()383 WsdlInvoker::serializeHeader()
384 {
385   //create input  holders for the soap header,use the same list
386   //but just remember where the header's params end
387   std::string name;
388 
389   int hPartId;
390   const Message* hMessage;//message corresponding to soap header
391 
392   const Binding * bnSoap = op_->portType()->binding(soap_->getNamespace());
393   const int *bindings = 0;
394   int opIndex  = op_->portType()->getOperationIndex(op_->getName());
395   int nBindings=bnSoap->getInputBinding(opIndex,bindings);
396   //get the body and header
397   for (int x=0;x<nBindings;x++){
398 
399     if (soap_->isSoapHeader(bindings[x])){
400 
401       soap_->getSoapHeaderInfo(bindings[x],hnsp_,hPartId,hMessage);
402 
403 
404       Schema::Type pType =Schema::XSD_INVALID;
405       if (hMessage->getPartRefType(hPartId)==Part::Elem){
406 
407 	name = hMessage->getMessagePart(hPartId)->element()->getName();
408 	pType = (Schema::Type)hMessage->getMessagePart(hPartId)->element()->getType();
409       }
410       else {
411 
412 	name = hMessage->getPartName(hPartId);
413 	pType = (Schema::Type)hMessage->getMessagePart(hPartId)->type();
414       }
415       std::vector<std::string> parents;
416       parents.push_back(name);
417       serializeType(pType,
418 		    name,
419 		    wParser_->getSchemaParser(hMessage->getPartContentSchemaId(hPartId)),
420 		    1,1,parents,hnsp_,true);
421     }
422   }
423   iHeaders_ = elems_.size();
424 
425 }
426 
427 //this method extracts the  atomic types needed for the web service
428 //it recursively calls serializeType for all the input or output types expected
429 //This method works in 2 modes.In the serializeMode_ == false it creates holders
430 //for the parameter values.In serializeMode_ == true it uses the inputs from the holders
431 //to generate the SOAP XML message
432 void
serialize()433 WsdlInvoker::serialize()
434 {
435   const Message * m = op_->getMessage(messageType_);
436   if (!m)
437     return;
438 
439   for (int i = 0 ;i<m->getNumParts();i++){
440 
441     Part::PartRefType prt = m->getPartRefType(i);
442     const Part * p = m->getMessagePart(i);
443     const SchemaParser * sParser = wParser_->getSchemaParser(p->schemaId());
444     const std::string nsp = sParser->getNamespace();
445 
446     std::vector<std::string> parents;
447     if (prt == Part::Elem){
448 
449       const Element * e = p->element();
450       if (e->getTypeNamespace() != sParser->getNamespace()) {
451 	sParser = wParser_->getSchemaParser(e->getTypeNamespace());
452       }
453       //the above can happen when the actual type/element is defined in someother namespace via imports
454       serializeType((Schema::Type)e->getType(),e->getName(),sParser,1,1,parents,e->getTypeNamespace(),true);
455     }
456     else{
457 
458       serializeType((Schema::Type)p->type(),p->name(),sParser,1,1,parents,nsp,true);
459     }
460   }
461 }
462 
463 void
serializeType(Schema::Type typeId,const std::string & tag,const SchemaParser * sParser,int minimum,int maximum,std::vector<std::string> parents,const std::string nsp,bool isRoot)464 WsdlInvoker::serializeType(Schema::Type typeId,
465 			   const std::string &tag,
466 			   const SchemaParser * sParser,
467                            int minimum,
468                            int maximum,
469 			   std::vector<std::string> parents,
470 			   const std::string nsp,
471 			   bool isRoot)
472 {
473   std::string t = tag;
474   if (t == "*")
475     t = "item";
476 
477 
478   //for( std::vector<std::string>::iterator it=parents.begin();it!=parents.end();it++) std::cout<<*it;
479 
480   const XSDType * pType = sParser->getType(typeId);
481 
482   for (size_t z=0;z<avoidrecurse_.size();z++){
483     //if there is a recursive type reference return to avoid infinite loop
484     if (avoidrecurse_[z] == pType)
485       return;
486 
487   }
488   avoidrecurse_.push_back(pType);
489 
490   if ( pType== 0 ||
491        pType->isSimple() ||
492        pType->getContentModel() == Schema::Simple){
493     //simple types
494     if (serializeMode_ == false){
495 
496       parents.push_back(tag);
497       Parameter p(typeId,t,minimum,maximum,sParser,parents);
498       elems_.push_back(p);
499 
500 #ifdef LOGGING
501 
502       std::cout<<"Adding input type "<<tag<<XmlUtils::dbsp
503                <<sParser->getTypeName(typeId)<<XmlUtils::dbsp;
504       std::cout<<sParser->getNamespace()<<std::endl;
505 #endif
506     }
507     else{
508       //generate the xml
509       serializeParam(n_++,t,sParser,nsp,isRoot);
510     }
511   }
512   else{
513 
514     if (serializeMode_){
515 
516       if (style_ == Soap::DOC ){
517 
518 
519 	if (sParser->getElementQualified()) {
520 
521 	  xmlStream_->startTag("",t);
522 	  if (isRoot)
523 	    xmlStream_->attribute("","xmlns",nsp);
524 	}
525 	else {
526 
527 	    if (isRoot) {
528 	      xmlStream_->setPrefix(getPrefix(nsp),nsp);
529 	      xmlStream_->startTag(nsp,t);
530 	    }
531 	    else {
532 	      xmlStream_->startTag("",t);
533 	    }
534 	}
535       }
536       else{
537 
538 	xmlStream_->startTag("",t);
539 
540 	//fix for sending SOAP arrays.add the soap arrayType attribute
541 	//works only for 1-D arrays
542 	const ComplexType* ct = static_cast<const ComplexType*>(pType);
543 	if(isSoapArray(ct,sParser)){
544 
545 	  std::string arrayName = ct->getName();
546 	  arrayName = "ns:"+arrayName+"[1]";
547 	  xmlStream_->attribute(soap_->getEncodingUri(),"arrayType",arrayName);
548 	}
549       }
550     }
551     else {
552 
553       //complex types with multiple occurences
554 
555 
556       //      parents.push_back(tag);
557       //      Parameter p(typeId,t,minimum,maximum,sParser,parents);
558       //      elems_.push_back(p);       TODO
559 
560     }
561 
562 
563     const ComplexType * ct =
564       static_cast<const ComplexType*>(pType);
565 
566     //complex types handling
567     if (ct->getNumAttributes() > 0) {
568 
569       for (int i = 0; i < ct->getNumAttributes(); i++) {
570 
571 	const Attribute*at = ct->getAttribute(i);
572 	/*
573 	 * Check for the correctness of each attribute
574 	 */
575 	if (at->isRequired()){
576 
577 	  if (serializeMode_ == false){
578 
579 	    std::vector<std::string> attparents(parents);
580 	    attparents.push_back(tag);
581 	    attparents.push_back("#" + at->getName() + "#");
582 	    Parameter p((Schema::Type)at->getType(),at->getName(),elems_.size(),0,sParser,
583 	                attparents);
584 	    elems_.push_back(p);
585 	  }
586 	  else{
587 	    //generate the xml
588 
589 	    xmlStream_->attribute(sParser->getNamespace(),at->getName(),elems_[n_++].data_[0]);
590 	  }
591 	}
592 	else
593 	  continue;
594       }
595     }
596 
597     if (ct->getContentModel() == Schema::Simple) {
598 
599       if (serializeMode_ == false){
600 
601 	parents.push_back(tag);
602         Parameter p((Schema::Type)ct->getContentType(),tag,minimum,maximum,sParser,parents);
603 	elems_.push_back(p);
604       }
605       else{
606 	//generate the xml
607 	serializeParam(n_++,t,sParser,nsp,isRoot);
608       }
609     }
610     else{
611 
612       const XSDType * baseType=sParser->getType(ct->getBaseTypeId());
613       if (baseType && !baseType->isSimple()){
614 
615 	const ComplexType * cType=static_cast<const ComplexType*>(baseType);
616 	ContentModel * bCm = cType->getContents();
617 	if (bCm){
618 	  if (!isSoapArray(ct,sParser)){
619 	    //hack ..for soap arrays base type is SOAP-ENC:Array, but dont serialize it
620 	    parents.push_back(tag);
621 	    serializeContentModel(bCm,sParser,parents);
622 	  }
623 	}
624       }
625       ContentModel* cm=ct->getContents();
626       if(cm){
627 
628 	parents.push_back(tag);
629 	serializeContentModel(cm,sParser,parents);
630       }
631     }
632 
633     if (serializeMode_){
634 
635       if (style_ == Soap::DOC ){
636 
637 	if (sParser->getElementQualified()) {
638 
639 	  xmlStream_->endTag("",t);
640 	}
641 	else {
642 
643 	  if (isRoot) {
644 
645 	    xmlStream_->endTag(nsp,t);
646 	  }
647 	  else {
648 	      xmlStream_->endTag("",t);
649 	  }
650 	}
651       }
652       else{
653 
654 	xmlStream_->endTag("",t);
655       }
656     }
657   }
658   avoidrecurse_.pop_back();
659 }
660 
661 void
serializeContentModel(ContentModel * cm,const SchemaParser * sParser,std::vector<std::string> parents)662 WsdlInvoker::serializeContentModel(ContentModel *cm,
663 				   const SchemaParser *sParser,
664 				   std::vector<std::string> parents)
665 {
666 
667   ContentModel::ContentsIterator cit_b=cm->begin();
668   ContentModel::ContentsIterator cit_e=cm->end();
669   ContentModel::ContentsIterator ci=cit_b;
670 
671 
672   switch (cm->getCompositor())
673     {
674     case Schema::All:
675     case Schema::Sequence:
676     case Schema::Choice:
677       {
678 	// a simple logic to start with
679 	// not taking care of all,choice ,sequence as of now
680 
681 	for (ci=cit_b;ci!=cit_e;ci++){
682 
683 	  if(ci->second==ContentModel::Particle &&
684              ci->first.e->getMax() > 0){
685 
686 
687 	    const SchemaParser* s1Parser = sParser;
688 	    bool isRoot = false;
689 	    std::string nsp;
690 	    Schema::Type t=(Schema::Type)ci->first.e->getType();
691 
692 	    if (!ci->first.e->getTypeNamespace().empty() &&
693 		sParser->isImported(ci->first.e->getTypeNamespace()) &&
694                 sParser->getNamespace() != ci->first.e->getTypeNamespace()) {
695 
696 	      //here the type of the element is defined in another imported schemaparser
697 	      //so try to get the pointer.
698 	      if ( !sParser->isBasicType(t)){
699 	          t = (Schema::Type)sParser->getType(t)->getTypeId();
700 	          sParser = sParser->getImportedSchemaParser(ci->first.e->getTypeNamespace());
701 	      }
702 	      if(ci->first.e->getNamespace() != s1Parser->getNamespace()){
703 		nsp = ci->first.e->getNamespace();
704 		isRoot = true ;// the element is from another namespace so need to qualify it
705 	      }
706 	    }
707 
708 
709 	    if ((ci->first.e->getMin() == 0) &&  //nillable check for complex types
710 		serializeMode_ && !sParser->isBasicType(ci->first.e->getType()) && isSubTreeNil() ) {
711 
712 	      serializeParam(-1,ci->first.e->getName(),sParser,nsp,isRoot);
713 
714 	      //if an elements contents are nil and the element is nillable then nil the element
715 
716 	    }
717 	    else {
718 
719 	      serializeType(t,
720 			    ci->first.e->getName(),
721 			    sParser,
722 			    ci->first.e->getMin(),
723 			    ci->first.e->getMax(),
724 			    parents,
725 			    nsp,isRoot);
726 	    }
727 	    sParser = s1Parser;
728 	  }
729 	  else if (ci->second==ContentModel::Container) {
730 
731 	    //nested xsd:sequence inside choice..nested content models
732 	    serializeContentModel(ci->first.c,
733 				  sParser,
734 				  parents);
735 
736 	  }
737 	  else if (ci->second==ContentModel::ParticleGroup){
738 
739 	    //xsd:group inside
740 	    serializeContentModel(ci->first.g->getContents(),
741 				  sParser,
742 				  parents);
743 	  }
744 	}
745 	break;
746       }
747     }
748 }
749 
750 
751 void
serializeParam(int n,const std::string & tag,const SchemaParser * sParser,const std::string nsp,bool isRoot)752 WsdlInvoker::serializeParam(int n,const std::string & tag,
753 			    const SchemaParser * sParser,
754 			    const std::string nsp,
755 			    bool isRoot)
756 {
757 
758   std::string t=tag;
759   if (tag=="*")
760     t="item";
761 
762   if (n == -1 ) {
763     xmlStream_->startTag("",t);
764     xmlStream_->endTag("",t);
765     return;//for nillable element ,just generate an empty tag
766   }
767 
768   for (int i = 0 ;i<elems_[n].n_;i++){
769 
770     if (style_ == Soap::DOC){
771 
772       if (!isRoot)
773 	xmlStream_->startTag("",t);
774 
775       else {
776 
777 	if (!nsp.empty())
778 	  xmlStream_->setPrefix(getPrefix(nsp),nsp);
779 
780 	xmlStream_->startTag(nsp,t);
781 
782       }
783     }
784     else{
785 
786 	xmlStream_->startTag("",t);
787 
788 	//xsi::type is needed for many SOAP servers
789 	if (sParser->isBasicType(elems_[n].type_) &&
790 	    use_ == Soap::ENCODED){
791 
792 	  xmlStream_->attribute(Schema::SchemaInstaceUri,
793 				"type",
794 				"xsd:"+sParser->getTypeName(elems_[n].type_));
795 	}
796     }
797 
798     xmlStream_->text(elems_[n].data_[i]);
799     if (style_ == Soap::DOC && isRoot)
800       xmlStream_->endTag(nsp,t);
801     else
802       xmlStream_->endTag("",t);
803   }
804 }
805 
806 
807 bool
setInputValue(const int param,void ** values,unsigned int occurs)808 WsdlInvoker::setInputValue(const int param,void** values,unsigned int occurs)
809 {
810 
811   if (occurs < elems_[param].min_ ||
812       occurs > elems_[param].max_)
813     return false;
814 
815   SchemaValidator *sv = new SchemaValidator (elems_[param].sParser_);
816   for (unsigned int i = 0 ;i < occurs ;i++){
817 
818     TypeContainer * tc = sv->validate(values[i],
819 				      elems_[param].type_);
820     if (!tc->isValueValid()){
821 
822       return false;
823     }
824     std::ostringstream oss;
825     tc->print(oss);
826     elems_[param].data_.push_back(oss.str());
827     delete tc;
828   }
829   delete sv;
830 
831   elems_[param].n_ = occurs;
832   return true;
833 }
834 
835 bool
setInputValue(const int param,std::vector<std::string> values)836 WsdlInvoker::setInputValue(const int param,std::vector<std::string> values)
837 {
838 
839 
840   if (values.size() < elems_[param].min_ ||
841       values.size() > elems_[param].max_)
842     return false;
843 
844   SchemaValidator *sv = new SchemaValidator (elems_[param].sParser_);
845 
846   for (size_t i = 0 ;i < values.size() ;i++){
847 
848     TypeContainer * tc = sv->validate(values[i],
849 				      elems_[param].type_);
850     if (!tc->isValueValid()){
851 
852       return false;
853     }
854     elems_[param].data_.push_back(values[i]);
855     delete tc;
856   }
857   delete sv;
858 
859   elems_[param].n_ = values.size();
860   return true;
861 }
862 
863 bool
setInputValue(const int param,std::string val)864 WsdlInvoker::setInputValue(const int param,std::string val)
865 {
866 
867   const SchemaParser* sParser = elems_[param].sParser_;
868   SchemaValidator *sv = new SchemaValidator (sParser);
869   Schema::Type t = elems_[param].type_;
870   const XSDType * pType = sParser->getType(t);
871   if (pType && !pType->isSimple()){
872 
873     if (pType->getContentModel() != Schema::Simple)
874       return false;
875 
876     const ComplexType * ct = static_cast<const ComplexType*>(pType);
877     t = (Schema::Type)ct->getContentType();
878   }
879 
880   TypeContainer * tc = sv->validate(val,t);
881   if (!(tc && tc->isValueValid())){
882 
883     return false;
884   }
885   if (elems_[param].data_.size() == 0)
886     elems_[param].data_.push_back(val);
887   else
888     elems_[param].data_[0]=val;
889 
890   delete tc;
891 
892   delete sv;
893 
894   elems_[param].n_ = 1;
895   return true;
896 }
897 
898 
899 
900 bool
setInputValue(const int param,void * val)901 WsdlInvoker::setInputValue(const int param,void* val)
902 {
903 
904   const SchemaParser*  sParser = elems_[param].sParser_;
905   SchemaValidator *sv = new SchemaValidator (sParser);
906   Schema::Type t = elems_[param].type_;
907   const XSDType * pType = sParser->getType(t);
908   if (pType && !pType->isSimple()){
909 
910     if (pType->getContentModel() != Schema::Simple)
911       return false;
912 
913     const ComplexType * ct = static_cast<const ComplexType*>(pType);
914     t = (Schema::Type)ct->getContentType();
915   }
916 
917   TypeContainer * tc = sv->validate(val,t);
918   if (!(tc && tc->isValueValid())){
919 
920     return false;
921   }
922   std::ostringstream oss;
923   tc->print(oss);
924   if (elems_[param].data_.size() == 0)
925     elems_[param].data_.push_back(oss.str());
926   else
927     elems_[param].data_[0]=oss.str();
928   delete tc;
929   delete sv;
930   elems_[param].n_ = 1;
931   return true;
932 }
933 
934 bool
setValue(const std::string & param,void * val)935 WsdlInvoker::setValue(const std::string & param,void* val)
936 {
937   for (size_t s = 0;s<elems_.size();s++){
938 
939     if (elems_[s].tag_ == param)
940       return setInputValue(s,val);
941   }
942   return false;
943 }
944 
945 bool
setValue(const std::string & param,void ** values,unsigned int occur)946 WsdlInvoker::setValue(const std::string & param,void** values,unsigned int occur)
947 {
948 
949   for (size_t s = 0;s<elems_.size();s++){
950 
951     if (elems_[s].tag_ == param)
952       return setInputValue(s,values,occur);
953   }
954   return false;
955 }
956 
957 bool
setValue(const std::string & param,std::string val)958 WsdlInvoker::setValue(const std::string & param,std::string val)
959 {
960   for (size_t s = 0;s<elems_.size();s++){
961 
962     if (elems_[s].tag_ == param)
963       return setInputValue(s,val);
964   }
965   return false;
966 }
967 
968 bool
setValue(const std::string & param,std::vector<std::string> values)969 WsdlInvoker::setValue(const std::string & param,std::vector<std::string> values)
970 {
971   for (size_t s = 0;s<elems_.size();s++){
972 
973     if (elems_[s].tag_ == param)
974       return setInputValue(s,values);
975   }
976   return false;
977 }
978 
979 
980 std::string
getSoapMessage()981 WsdlInvoker::getSoapMessage(){
982 
983   dontPost_ = true;
984   invoke();
985   dontPost_ = false;
986   return soapstr_->str();
987 }
988 
989 std::string
getXMLResponse()990 WsdlInvoker::getXMLResponse(){
991 
992   return strResults_;
993 }
994 
995 
996 bool
invoke(long timeout,bool processResponse)997 WsdlInvoker::invoke(long timeout,bool processResponse)
998 {
999 
1000 try{
1001 
1002   if (xmlStream_){
1003 
1004     delete xmlStream_;
1005   }
1006   if (soapstr_){
1007 
1008     delete soapstr_;
1009   }
1010   if (!strResults_.empty()){
1011     strResults_.clear();
1012   }
1013 
1014 
1015   for (size_t x = 0;x<outputs_.size();x++)
1016     delete outputs_[x].second;
1017 
1018   outputs_.clear();
1019 
1020   soapstr_ = new std::ostringstream();
1021   xmlStream_ = new XmlSerializer(*soapstr_);
1022 
1023   serializeMode_ = true;
1024 
1025   xmlStream_->startDocument("UTF-8",false);
1026   xmlStream_->setPrefix("SOAP-ENV",soap_->getEnvelopeUri());
1027   xmlStream_->setPrefix("SOAP-ENC",soap_->getEncodingUri());
1028   xmlStream_->setPrefix("xsd",Schema::SchemaUri);
1029   xmlStream_->setPrefix("xsi",Schema::SchemaInstaceUri);
1030   xmlStream_->setPrefix(getPrefix(nsp_),nsp_);
1031   xmlStream_->startTag(soap_->getEnvelopeUri(),"Envelope");
1032 
1033   if (style_ == Soap::RPC) {
1034 
1035     xmlStream_->attribute(soap_->getEnvelopeUri(),
1036 			  "encodingStyle",
1037 			  soap_->getEncodingUri());
1038   }
1039 
1040   n_ = 0;
1041   if (soapheaders_){
1042     xmlStream_->startTag(soap_->getEnvelopeUri(),"Header");
1043     serializeHeader();
1044     xmlStream_->endTag(soap_->getEnvelopeUri(),"Header");
1045   }
1046 
1047   xmlStream_->startTag(soap_->getEnvelopeUri(),"Body");
1048   if (style_ == Soap::RPC){
1049 
1050     xmlStream_->startTag(nsp_,op_->getName());
1051   }
1052 
1053   serialize();
1054   if (style_ == Soap::RPC){
1055     xmlStream_->endTag(nsp_,op_->getName());
1056   }
1057 
1058   xmlStream_->endTag(soap_->getEnvelopeUri(),"Body");
1059   xmlStream_->endTag(soap_->getEnvelopeUri(),"Envelope");
1060   xmlStream_->flush();
1061 
1062 
1063 
1064   //test
1065   //  status_ = true;
1066   // if(processResponse)
1067   //   processResults();
1068   // return status_;
1069   //test
1070 
1071   if (dontPost_)
1072     return true;
1073 
1074   post(timeout);
1075   if (!strResults_.empty()){
1076 
1077     if (processResponse)
1078       processResults();
1079 
1080     m_xmlTreeProduced = false;
1081 
1082     if( m_buildXmlTree == true) {
1083 
1084       std::istringstream l_respstr( strResults_);
1085       //std::ifstream l_respstr( "r.xml");//test
1086 
1087       XmlPullParser l_xpp( l_respstr);
1088       l_xpp.setFeature( FEATURE_PROCESS_NAMESPACES, true);
1089       l_xpp.require( XmlPullParser::START_DOCUMENT, "", "");
1090 
1091       m_xmlDoc.clear();
1092 
1093       buildXmlTree( l_xpp, m_xmlDoc.getRootNode());
1094       m_xmlTreeProduced = true;
1095     }
1096 
1097     if (status_)
1098       return true;
1099   }
1100   else{
1101 
1102     if (!op_->getMessage(WsdlPull::Output))
1103       return true; //for web services which have no output
1104 
1105     logger_<<"Couldnt connect to "<<location_;
1106   }
1107   return false;
1108 }
1109 catch (WsdlException we)
1110   {
1111     logger_<<"A WSDL exception occurred at"<<we.line
1112 	   <<":"<<we.col<<std::endl;
1113     logger_<<we.description<<std::endl;
1114     return false;
1115   }
1116 catch (SchemaParserException spe)
1117   {
1118     logger_<<"A Schema Parser exception occurred at "<<spe.line
1119 	   <<":"<<spe.col<<std::endl;
1120     logger_<<spe.description<<std::endl;
1121     return false;
1122   }
1123 catch (XmlPullParserException xpe)
1124   {
1125     logger_<<"An Xml Parsing exception occurred at row:col "<<xpe.line
1126 	   <<":"<<xpe.col<<std::endl;
1127     logger_<<xpe.description<<std::endl;
1128     return false;
1129   }
1130 }
1131 
1132 int
getNextInput(std::string & param,Schema::Type & type,int & minimum,int & maximum)1133 WsdlInvoker::getNextInput(std::string & param ,Schema::Type & type,int & minimum,int & maximum)
1134 {
1135   std::vector<std::string> parents;
1136   return getNextInput(param, type, minimum, maximum, parents);
1137 }
1138 
1139 int
getNextInput(std::string & param,Schema::Type & type,int & minimum,int & maximum,std::vector<std::string> & parents)1140 WsdlInvoker::getNextInput(std::string & param ,Schema::Type & type,int & minimum,int & maximum,
1141 			  std::vector<std::string> & parents)
1142 {
1143   if (n_ < elems_.size()){
1144 
1145     param = elems_[n_].tag_;
1146     type = elems_[n_].type_;
1147     minimum = elems_[n_].min_;
1148     parents = elems_[n_].parents_;
1149     maximum = elems_[n_].max_;
1150     return n_++;
1151   }
1152   else{
1153     return -1;
1154   }
1155 }
1156 
1157 int
getNextHeaderInput(std::string & param,Schema::Type & type,int & minimum,int & maximum)1158 WsdlInvoker::getNextHeaderInput(std::string & param ,Schema::Type & type,
1159 				int & minimum,int & maximum)
1160 {
1161 
1162   std::vector<std::string> parents;
1163   return getNextHeaderInput(param,type,minimum,maximum,parents);
1164 }
1165 
1166 int
getNextHeaderInput(std::string & param,Schema::Type & type,int & minimum,int & maximum,std::vector<std::string> & parents)1167 WsdlInvoker::getNextHeaderInput(std::string & param ,Schema::Type & type,
1168 				int & minimum,int & maximum,
1169 				std::vector<std::string> & parents)
1170 {
1171   static int h = 0;
1172   if (h<iHeaders_){
1173     param = elems_[h].tag_;
1174     type = elems_[h].type_;
1175     minimum = elems_[h].min_;
1176     maximum = elems_[h].max_;
1177     parents = elems_[h].parents_;
1178     return h++;
1179   }
1180   else{
1181     h = 0;
1182     return -1;
1183   }
1184 }
1185 
1186 void
processResults()1187 WsdlInvoker::processResults()
1188 {
1189   XmlPullParser* xpp = 0;
1190   try{
1191 
1192     const Message* m = op_->getMessage(WsdlPull::Output);
1193     std::istringstream respstr(strResults_);
1194     //std::ifstream respstr("response.xml");//test
1195     xpp = new XmlPullParser(respstr);
1196     xpp->setFeature (FEATURE_PROCESS_NAMESPACES, true);
1197     xpp->require (XmlPullParser::START_DOCUMENT, "", "");
1198 
1199     while (status_ &&
1200 	   xpp->getEventType () != XmlPullParser::END_DOCUMENT) {
1201 
1202       if (xpp->getEventType () == XmlPullParser::END_DOCUMENT)
1203 	break;
1204 
1205       if (xpp->getEventType () == XmlPullParser::END_TAG &&
1206 	  xpp->getName() == "Envelope" &&
1207 	  xpp->getNamespace() == soap_->getEnvelopeUri())
1208 	break;
1209 
1210 
1211       xpp->nextTag();
1212       Qname elemName (xpp->getName ());
1213       elemName.setNamespace(xpp->getNamespace());
1214 
1215       if (elemName.getNamespace() == soap_->getEnvelopeUri()){
1216 
1217 	if (elemName.getLocalName() == "Fault"){
1218 	  processFault(xpp);
1219 	  status_ = false;
1220 	  delete xpp;
1221 	  return;
1222 	}
1223 	else if (elemName.getLocalName() == "Header"){
1224 
1225 	  processHeader(xpp);
1226 	}
1227         else if (elemName.getLocalName() == "Body"){
1228 
1229 	  xpp->nextTag();
1230 	  processBody(m,xpp);
1231 	}
1232       }
1233     }
1234     delete xpp;
1235     n_ = oHeaders_;
1236   }
1237   catch (WsdlException we)
1238     {
1239 
1240       logger_<<"A WSDL exception occurred while parsing the response at line "<<we.line
1241 	     <<":"<<we.col<<std::endl;
1242       logger_<<we.description<<std::endl;
1243       status_ =false;
1244       if (xpp) delete xpp;
1245     }
1246   catch (SchemaParserException spe)
1247     {
1248       logger_<<"A Schema Parser exception occurred while parsing the response at line "<<spe.line
1249 	     <<":"<<spe.col<<std::endl;
1250       logger_<<spe.description<<std::endl;
1251       status_ =false;
1252       if (xpp) delete xpp;
1253     }
1254   catch (XmlPullParserException xpe)
1255     {
1256       logger_<<"An Xml Parsing exception occurred while parsing the response at line "<<xpe.line
1257 	     <<":"<<xpe.col<<std::endl;
1258       logger_<<xpe.description<<std::endl;
1259       status_ =false;
1260       if (xpp) delete xpp;
1261     }
1262   return;
1263 }
1264 
~WsdlInvoker()1265 WsdlInvoker::~WsdlInvoker()
1266 {
1267   reset();
1268   if (ourParser_){
1269       delete ourParser_;
1270   }
1271   if (xmlStream_){
1272 
1273     delete xmlStream_;
1274   }
1275   if (soapstr_){
1276 
1277     delete soapstr_;
1278   }
1279 
1280 #ifdef WITH_CURL
1281   if(ctx) {
1282         curl_easy_cleanup(ctx) ;
1283   }
1284 #endif
1285 }
1286 
1287 void
reset()1288 WsdlInvoker::reset()
1289 {
1290   n_ =  iHeaders_ = oHeaders_ = 0;
1291   elems_.clear();
1292 
1293   for (size_t x = 0;x<outputs_.size();x++)
1294     delete outputs_[x].second;
1295 
1296   outputs_.clear();
1297   serializeMode_ = false;
1298 
1299 
1300 
1301 }
1302 
1303 bool
getNextOutput(std::string & name,TypeContainer * & tc)1304 WsdlInvoker::getNextOutput(std::string & name,TypeContainer * & tc)
1305 {
1306   if (status_ && n_ < outputs_.size()){
1307 
1308     name = outputs_[n_].first;
1309     tc = outputs_[n_].second;
1310     n_++;
1311     return true;
1312   }
1313   n_ = oHeaders_;
1314   return false;
1315 }
1316 
1317 
1318 TypeContainer*
getOutput(const std::string & name)1319 WsdlInvoker::getOutput(const std::string  & name)
1320 {
1321   for (unsigned int i = 0 ;status_ && i <outputs_.size();i++){
1322 
1323     if ( name == outputs_[i].first)
1324       return outputs_[i].second;
1325   }
1326   return 0;
1327 }
1328 
1329 bool
getNextHeaderOutput(std::string & name,TypeContainer * & tc)1330 WsdlInvoker::getNextHeaderOutput(std::string & name,TypeContainer*& tc)
1331 {
1332   static int j = 0;
1333   if(j<oHeaders_){
1334     name = outputs_[j].first;
1335     tc = outputs_[j].second;
1336     j++;
1337     return true;
1338   }
1339   else{
1340     j = 0;
1341     return false;
1342   }
1343 }
1344 
1345 void *
getValue(const std::string & name,Schema::Type & t)1346 WsdlInvoker::getValue(const std::string  & name ,Schema::Type & t)
1347 {
1348   for (unsigned int i = 0 ;status_ && i <outputs_.size();i++){
1349 
1350     if (outputs_[i].second!=0){
1351       outputs_[i].second->rewind();
1352       void * tmp= outputs_[i].second->getValue(name,t);
1353       if (tmp)
1354 	return tmp;
1355     }
1356   }
1357   return 0;
1358 }
1359 
1360 //a complete xpath lookup
1361 std::string
getAsStringFromXPath(const std::string & p_xpath,size_t p_index,std::vector<std::string> * p_array)1362 WsdlInvoker::getAsStringFromXPath( const std::string &p_xpath,
1363 				   size_t p_index,
1364 				   std::vector<std::string> *p_array)
1365 {
1366   //if( status_) {//test
1367   if( status_ && !strResults_.empty()){
1368 
1369     if( p_xpath.empty())
1370       return "";
1371 
1372     if( m_xmlTreeProduced == true) {
1373 
1374       std::vector< std::string> l_results;
1375       m_xmlDoc.xpath( p_xpath, l_results, p_index);
1376 
1377       if( p_array == NULL) {
1378 
1379 	if( l_results.empty() == false)
1380 	  return l_results[ 0];
1381 
1382 	return "";
1383       }
1384 
1385       *p_array = l_results;
1386       return "";
1387     }
1388 
1389     //get all the nodes in the expression into an array
1390     std::vector< std::string> l_xpathList;
1391 
1392     size_t l_xpathTotalLevels = 0; // Number of nodes in the xpath expression (not including attribute)
1393     bool l_matchFromRoot = false; // If match must only be made from root node
1394     bool l_doubleSlashMatch = false; //
1395     size_t l_matchAllAtXPathLevel = 0;
1396     bool l_matchAttribute = false; // True if match must be an attribute
1397 
1398 
1399     // Parse the Xpath-like expression
1400     std::string l_tmpElementText; // Temporary string
1401     bool l_seenSlash = false;
1402     for( size_t l_i = 0; l_i < p_xpath.size(); l_i++) {
1403 
1404       if( p_xpath[ l_i] == '/') {
1405 	// We have found a xpath node separator: '/'
1406 
1407 	if( l_seenSlash == false) {
1408 	  // No separator has just been seen before
1409 	  l_seenSlash = true;
1410 
1411 	  if( l_tmpElementText.empty() == false) {
1412 	    // if text was collected between 2 separators
1413 	    // store it in the xpathList
1414 	    l_xpathList.push_back( l_tmpElementText);
1415 	    l_tmpElementText.clear();
1416 	  }
1417 	} else { // l_SeenSlash == false
1418 	  // Two '/' in a row indicate a all-elements match after a certain point
1419 	  // in the xpath string. Mark the start of the all-elements match
1420 	  // by inserting an empty string
1421 	  l_doubleSlashMatch = true;
1422 	  l_matchAllAtXPathLevel = l_xpathList.size();
1423 
1424 	  // Clear the "seenSlash" flag
1425 	  l_seenSlash = false;
1426 	}
1427       } else { // xpath[ l_i] == '/'
1428 	// Normal char seen
1429 
1430 	// if first char is '/' and second is a regular char
1431 	// we will have to match from the Xml root level
1432 	if( l_i == 1 && l_seenSlash == true)
1433 	  l_matchFromRoot = true;
1434 
1435 	// Mark that we didn't see a separator
1436 	l_seenSlash = false;
1437 	// Append the text to the temporary string until we find a separator
1438 	l_tmpElementText.append( 1, p_xpath[ l_i]);
1439       }
1440     }
1441 
1442     // push the last node (or attribute) into the xpathList (if any)
1443     if( l_tmpElementText.empty() == false)
1444       l_xpathList.push_back( l_tmpElementText);
1445 
1446     // Store the number of xpathTotalLevels that we must traverse
1447     l_xpathTotalLevels = l_xpathList.size();
1448 
1449     if( l_xpathList[ l_xpathTotalLevels - 1][ 0] == '@') {
1450       // If an attribute is to be matched, mark it so
1451       l_matchAttribute = true;
1452       // xpathLevels is decremented as the attribute is not a node to traverse
1453       l_xpathTotalLevels--;
1454     }
1455 
1456     // Parse the XML to deliver the results
1457 
1458     std::istringstream respstr( strResults_);
1459     //std::ifstream respstr( "r.xml");//test
1460 
1461     XmlPullParser l_xpp( respstr);
1462     l_xpp.setFeature( FEATURE_PROCESS_NAMESPACES, true);
1463     l_xpp.require( XmlPullParser::START_DOCUMENT, "", "");
1464 
1465     size_t l_xpathLevel = 0;
1466     size_t l_xmlLevel = 0;
1467     size_t l_failedXpathMatchAtXmlLevel = 0;
1468 
1469     bool l_textWasRetrieved = false;
1470     std::string l_retrievedText;
1471     std::string l_xmlTagName;
1472 
1473     int l_xmlPullEvent;
1474 
1475     do {
1476       l_xmlPullEvent = l_xpp.nextToken();
1477 
1478       if( l_xmlPullEvent == XmlPullParser::START_TAG) {
1479 
1480 	l_xmlTagName = l_xpp.getName();
1481 
1482 	// Skip envelope and body tags at xml root level
1483 	if( l_xmlLevel == 0 && ( l_xmlTagName == "Envelope" || l_xmlTagName == "Body"))
1484 	  continue;
1485 
1486 	// Mark the entrace to xmlLevel
1487 	l_xmlLevel++;
1488 
1489 	//bool l_doubleSlashMatch = false;
1490 	//size_t l_matchAllAtXPathLevel = 0;
1491 
1492 	if( l_xmlTagName == l_xpathList[ l_xpathLevel] &&
1493 	    ( l_failedXpathMatchAtXmlLevel == 0 ||
1494 	      ( l_doubleSlashMatch == true && l_xpathLevel >= l_matchAllAtXPathLevel))
1495 	    ) {
1496 
1497 	  // Check if we must match at root level
1498 	  // See if "root" levels match (0 for xpathLevel and 1 for xmlLevel)
1499 	  // if root levels do not match -- skip checks
1500 	  if( l_matchFromRoot == true)
1501 	    if( l_xpathLevel == 0 && l_xmlLevel != 1)
1502 	      continue;
1503 
1504 	  l_xpathLevel++;
1505 
1506 	  // If we have not reached the final sought node, carry on
1507 	  if( l_xpathLevel < l_xpathTotalLevels)
1508 	    continue;
1509 
1510 	  // if we have reached the last element of the xpath expression
1511 	  // and given that all preconditions were met
1512 	  // store the results
1513 
1514 	  // Since we have already processed a "start_tag" event the next
1515 	  // has to be content. "Text" events may be delivered in several
1516 	  // consecutive events, hence the loop
1517 	  // Entity references will be shown as independent events
1518 
1519 	  if( l_matchAttribute == false) {
1520 	    // We have to store/return the text of the node
1521 	    // Clear the temporary storage before starting
1522 	    l_retrievedText.clear();
1523 
1524 	    do {
1525 	      // First token after a START_TAG has to be "text or entity" (the returned string might be empty)
1526 	      l_xmlPullEvent = l_xpp.nextToken();
1527 	      l_retrievedText += l_xpp.getText();
1528 	      // Carry on while Text or Entity are returned
1529 	    } while( l_xmlPullEvent == XmlPullParser::ENTITY_REF || l_xmlPullEvent == XmlPullParser::TEXT);
1530 
1531 	    // Mark that we have content in "tmp" to be stored or returned
1532 	    l_textWasRetrieved = true;
1533 
1534 	  } else {
1535 
1536 	    // Retrieve the attribue
1537 	    l_retrievedText = l_xpp.getAttributeValue( "", l_xpathList[ l_xpathLevel].substr( 1));
1538 	    // Mark that we have content in "tmp" to be stored or returned
1539 	    l_textWasRetrieved = true;
1540 	  }
1541 
1542 	  if( l_textWasRetrieved == true) {
1543 	    // If something (node's text or attribute's value) was retrieved
1544 	    if( p_array == NULL)
1545 	      return l_retrievedText; // return it, as only one value was sought
1546 
1547 	    // Store it in the array to be returned
1548 	    p_array->push_back( l_retrievedText);
1549 	    // Decrease the xpathLevel, to enable a new match by re-entering the loop
1550 	    l_xpathLevel--;
1551 
1552 	    // Clear the "textRetrieved" flag
1553 	    l_textWasRetrieved = false;
1554 	  }
1555 	} // if( l_xmlTagName == l_xpathList[ l_xpathLevel]) {
1556 	else if( l_xpathLevel > 0 && l_failedXpathMatchAtXmlLevel == 0) {
1557 	  // If a match has already happened (xpathLevel > 0) and we find ourselves here
1558 	  // the name of the node did not match, we record the xmllevel, so skip
1559 	  // any deeper tag
1560 	  // The value will be reset to 0, as soon as END_TAG at the same level is seen
1561 	  l_failedXpathMatchAtXmlLevel = l_xmlLevel;
1562 	}
1563       }
1564 
1565       if( l_xmlPullEvent == XmlPullParser::END_TAG) {
1566 
1567 	// Check if we may clear the "failedXpathMatchAtXmlLevel" flag
1568 	if( l_failedXpathMatchAtXmlLevel == l_xmlLevel) {
1569 	  l_failedXpathMatchAtXmlLevel = 0;
1570 	}
1571 	else if( l_failedXpathMatchAtXmlLevel == 0) {
1572 	  if( l_xpathLevel > 0 && l_xpp.getName() == l_xpathList[ l_xpathLevel - 1])
1573 	    l_xpathLevel--;
1574 	  // Just above. If we have just seen a closing tag that corresponds to the previous xpathLevel
1575 	  // decrease one xpathLevel (it is 0 based, unlike xmlLevel which is 1 based)
1576 	}
1577 
1578 	// Skip the envelope and body tags at xml root level
1579 	if( l_xmlLevel == 0)
1580 	  continue;
1581 
1582 	l_xmlLevel--;
1583       }
1584 
1585     } while( l_xmlPullEvent != XmlPullParser::END_DOCUMENT);
1586 
1587   } // if (status_ && !strResults_.empty())
1588   else {
1589     //throw exception
1590     WsdlException we("Attempted to extract response when web service invocation did not succeed");
1591     throw we;
1592   }
1593 
1594   return "";//nothing found or values returned in vector 'arr'
1595 }
1596 
1597 
1598 
1599 void
post(long timeout,std::string username,std::string passwd)1600 WsdlInvoker::post(long timeout, std::string username, std::string passwd)
1601 {
1602   const std::string  postData = soapstr_->str();
1603   if(verbose_){
1604 
1605     std::ofstream ofs("request.log",std::ios::app);
1606     ofs<<postData;
1607     ofs<<std::endl;
1608     ofs.flush();
1609   }
1610 
1611 #ifdef WITH_CURL
1612   CURLcode res;
1613   std::string strCurlBuffer = "";
1614   if (!ctx){
1615     ctx=curl_easy_init();
1616   }
1617 
1618   if (!ctx)
1619     return ;
1620   curl_easy_setopt( ctx , CURLOPT_URL,  location_.c_str()) ;
1621 
1622   curl_easy_setopt( ctx , CURLOPT_NOPROGRESS , 1 ) ;
1623   if(timeout){
1624     curl_easy_setopt( ctx ,CURLOPT_TIMEOUT, timeout);
1625     curl_easy_setopt( ctx , CURLOPT_CONNECTTIMEOUT, timeout);
1626   }
1627 
1628   if (verbose_) {
1629     curl_easy_setopt( ctx , CURLOPT_VERBOSE,1);
1630     curl_easy_setopt( ctx , CURLOPT_NOPROGRESS , 0 ) ;
1631   }
1632 
1633   curl_easy_setopt( ctx , CURLOPT_POST , 1 );
1634   curl_easy_setopt( ctx , CURLOPT_POSTFIELDS , postData.c_str()) ;
1635   curl_slist* responseHeaders = NULL ;
1636   std::string tmp="SOAPAction: ";
1637   tmp.push_back('"');
1638   tmp+=action_;
1639   tmp.push_back('"');
1640   responseHeaders = curl_slist_append( responseHeaders , tmp.c_str());
1641   responseHeaders = curl_slist_append( responseHeaders ,"Content-Type: text/xml; charset=UTF-8");
1642   responseHeaders = curl_slist_append( responseHeaders ,"Accept: text/xml;");
1643   curl_easy_setopt( ctx , CURLOPT_HTTPHEADER , responseHeaders ) ;
1644   tmp = "wsdlpull";
1645 #ifdef HAVE_CONFIG_H
1646   tmp=tmp+"/"+VERSION;
1647 #endif
1648   curl_easy_setopt( ctx,CURLOPT_USERAGENT,tmp.c_str());
1649   curl_easy_setopt( ctx,CURLOPT_POSTFIELDSIZE,postData.length());
1650 
1651   if (XmlUtils::getProxy()){
1652     curl_easy_setopt(ctx,CURLOPT_PROXY,XmlUtils::getProxyHost().c_str());
1653     tmp=XmlUtils::getProxyUser()+":"+XmlUtils::getProxyPass();
1654     curl_easy_setopt(ctx,CURLOPT_PROXYUSERPWD,tmp.c_str());
1655   }
1656   curl_easy_setopt(ctx, CURLOPT_WRITEDATA, &strCurlBuffer) ;
1657   curl_easy_setopt( ctx ,CURLOPT_WRITEFUNCTION,storeResults) ;
1658 
1659   if (bAuth) {
1660     curl_easy_setopt(ctx, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
1661     std::string tmp = sAuthUser + ":" + sAuthPass;
1662     curl_easy_setopt(ctx, CURLOPT_USERPWD, tmp.c_str());
1663   }
1664   curl_easy_setopt(ctx, CURLOPT_COOKIEFILE, "");
1665   // std::logger_ << "- - - BEGIN: response - - -" << std::endl ;
1666   res=curl_easy_perform(ctx);
1667   //  std::logger_ << "- - - END: response - - -" << std::endl ;
1668 
1669   curl_slist_free_all( responseHeaders ) ;
1670   strResults_ = strCurlBuffer;
1671 
1672 #elif _WIN32
1673 
1674   char* sResults = (char*)0;
1675   XmlUtils::winPost(location_,username,passwd,postData,action_,sResults);
1676   strResults_ = (sResults != (char*)0) ? std::string(sResults) : "";
1677 #endif
1678 
1679   if(verbose_ && !strResults_.empty()){
1680 
1681     std::ofstream ofs("response.log",std::ios::app);
1682     ofs<<strResults_;
1683     ofs<<std::endl;
1684     ofs.flush();
1685   }
1686 
1687 }
1688 
1689 void
printTypeNames(bool f)1690 WsdlInvoker::printTypeNames(bool f)
1691 {
1692   TypeContainer::printTypeNames_ = false;
1693 }
1694 
1695 //build an XML Tree from the results
1696 void
buildXmlTree(XmlPullParser & p_xmlPullParser,XmlNode_t & p_xmlNode,bool p_pendingEvent)1697 WsdlInvoker::buildXmlTree( XmlPullParser &p_xmlPullParser, XmlNode_t &p_xmlNode, bool p_pendingEvent)
1698 {
1699   int l_xmlPullEvent;
1700 
1701   do {
1702 
1703     if( p_pendingEvent == false) {
1704       l_xmlPullEvent = p_xmlPullParser.nextToken();
1705     } else {
1706       p_pendingEvent = false;
1707       l_xmlPullEvent = p_xmlPullParser.getEventType();
1708     }
1709 
1710     if( l_xmlPullEvent == XmlPullParser::START_TAG) {
1711 
1712       if( p_xmlNode.empty() == true) {
1713 
1714 	p_xmlNode.setName( p_xmlPullParser.getName(), XmlNode_t::NON_EMPTY_NODE);
1715 
1716 	size_t l_numAttributes = static_cast< size_t>( p_xmlPullParser.getAttributeCount());
1717 	for( size_t l_i = 0; l_i < l_numAttributes; l_i++) {
1718 
1719 	  p_xmlNode.addAttribute( p_xmlPullParser.getAttributeName( l_i),
1720 				  p_xmlPullParser.getAttributeValue( l_i));
1721 	}
1722       } else {
1723 	XmlNode_t &l_childNodeRef = p_xmlNode.addNode( p_xmlPullParser.getName(), XmlNode_t::EMPTY_NODE);
1724 	buildXmlTree( p_xmlPullParser, l_childNodeRef, true);
1725       }
1726     }
1727     else if( l_xmlPullEvent == XmlPullParser::TEXT || l_xmlPullEvent == XmlPullParser::ENTITY_REF) {
1728 
1729       ::std::string l_tmpTxt;
1730       do {
1731 	l_tmpTxt += p_xmlPullParser.getText();
1732 	l_xmlPullEvent = p_xmlPullParser.nextToken();
1733       } while( l_xmlPullEvent == XmlPullParser::ENTITY_REF || l_xmlPullEvent == XmlPullParser::TEXT);
1734 
1735       p_xmlNode.setText( l_tmpTxt);
1736 
1737       // The previous loop leaves an unprocessed event after calling "nextToken" and seeing
1738       // that it's not text or entity_ref
1739       p_pendingEvent = true;
1740     }
1741     else if( l_xmlPullEvent == XmlPullParser::END_TAG) {
1742       break;
1743     }
1744 
1745   } while( l_xmlPullEvent != XmlPullParser::END_DOCUMENT);
1746 }
1747 
1748 void
processFault(XmlPullParser * xpp)1749 WsdlInvoker::processFault(XmlPullParser* xpp)
1750 {
1751 
1752   if (soap_->getSoapVersion() == Soap::SOAP12) {
1753 
1754     while (!(xpp->getEventType() == XmlPullParser::END_TAG && xpp->getName() == "Fault")) {
1755 
1756       if (xpp->getEventType() == XmlPullParser::START_TAG && xpp->getName() == "Code") {
1757 	xpp->next();
1758 
1759 	while (!(xpp->getEventType() == XmlPullParser::END_TAG && xpp->getName() == "Code")) {
1760 
1761 	  if (xpp->getEventType() == XmlPullParser::START_TAG && xpp->getName() == "Value") {
1762 	    xpp->next();
1763 	    sFaultCode = xpp->getText();
1764 	    logger_ << "SOAP Fault Code: " << sFaultCode << std::endl;
1765 	  }
1766 
1767 	  if (xpp->getEventType() == XmlPullParser::START_TAG && xpp->getName() == "Subcode") {
1768 	    xpp->next();
1769 
1770 	    if (xpp->getEventType() == XmlPullParser::START_TAG && xpp->getName() == "Value") {
1771 	      xpp->next();
1772 	      sFaultSubCode = xpp->getText();
1773 	      logger_ << "SOAP Fault SubCode: " << sFaultSubCode << std::endl;
1774 	    }
1775 	  }
1776 	  xpp->next();
1777 	}
1778       }
1779 
1780       if (xpp->getEventType() == XmlPullParser::START_TAG && xpp->getName() == "Reason") {
1781 	xpp->next();
1782 
1783 	if (xpp->getEventType() == XmlPullParser::START_TAG && xpp->getName() == "Text") {
1784 	  xpp->next();
1785 	  sFaultString = xpp->getText();
1786 	  logger_ << "SOAP Fault String: " << sFaultString << std::endl;
1787 	}
1788       }
1789       xpp->next();
1790     }
1791   } else {	// SOAP 1.1
1792 
1793     while (!(xpp->getEventType () == XmlPullParser::END_TAG &&
1794 	     xpp->getName() == "Fault")) {
1795 
1796       if (xpp->getEventType() == XmlPullParser::START_TAG &&
1797 	  xpp->getName() == "faultcode"){
1798 
1799 	xpp->next();
1800 	sFaultCode = xpp->getText();
1801 	logger_<<"SOAP Fault Code: "<<sFaultCode<<std::endl;
1802       }
1803 
1804       if (xpp->getEventType() == XmlPullParser::START_TAG &&
1805 	  xpp->getName() == "faultstring"){
1806 
1807 	xpp->next();
1808 	sFaultString = xpp->getText();
1809 	logger_<<"SOAP Fault String: "<<sFaultString<<std::endl;
1810       }
1811       if (xpp->getEventType() == XmlPullParser::START_TAG &&
1812 	  xpp->getName() == "faultactor"){
1813 
1814 	xpp->next();
1815 	sFaultActor = xpp->getText();
1816 	logger_<<"SOAP Fault Actor: "<<sFaultActor<<std::endl;
1817       }
1818       xpp->next();
1819     }
1820   }
1821 }
1822 
1823 void
processBody(const Message * m,XmlPullParser * xpp)1824 WsdlInvoker::processBody(const Message* m,
1825 			 XmlPullParser* xpp)
1826 {
1827 
1828   if (xpp->getName() == "Fault") {
1829 
1830     processFault(xpp);
1831     status_ = false;
1832     return;
1833   }
1834 
1835   if (style_ == Soap::RPC && use_==Soap::ENCODED){
1836 
1837     if (xpp->getName () == op_->getName()+"Response") {
1838 
1839       //operation's name followed by 'Response' must be the containing element
1840       xpp->nextTag ();
1841 
1842       do {
1843 
1844 
1845 	//first look for xsi:type
1846 	Qname typ(xpp->getAttributeValue(Schema::SchemaInstaceUri, "type"));
1847 	typ.setNamespace(xpp->getNamespace(typ.getPrefix()));
1848 	const SchemaParser * sParser = 0;
1849 	int typeId = 0;
1850 
1851 	if (!(typ.getNamespace() == soap_->getEncodingUri() &&
1852 	      typ.getLocalName() == "Array"))//for soap array just use the part's type info
1853 	  sParser= wParser_->getSchemaParser(typ.getNamespace());
1854 
1855 	if (sParser){
1856 
1857 	  typeId = (const_cast<SchemaParser*>(sParser))->getTypeId(typ);
1858 	}
1859 	else{
1860 
1861 	  //if xsi:type doesnt give a clue then see if the part name matches
1862 	  const Part * p = m->getMessagePart(xpp->getName ());
1863 	  if (p){
1864 
1865 	    sParser = wParser_->getSchemaParser(p->schemaId());
1866 	    typeId = p->type();
1867 	  }else {
1868 
1869 
1870 	  }
1871 	}
1872 	if (sParser && typeId !=0){
1873 
1874 	  SchemaValidator * sv= new SchemaValidator(sParser);
1875 	  std::string tag = xpp->getName();
1876 	  TypeContainer * t = sv->validate (xpp, typeId);
1877 	  outputs_.push_back(std::pair<std::string,TypeContainer*>(tag,t));
1878 	  xpp->nextTag();
1879 	  delete sv;
1880 	}
1881 	else{
1882 
1883 	  status_ = false;
1884 	  logger_<<"Unknown element "<<xpp->getName()<<std::endl;
1885 	  return;
1886 	}
1887       } while (!(xpp->getName() == op_->getName()+"Response" &&
1888 		 xpp->getEventType() == XmlPullParser::END_TAG));
1889     }
1890   }
1891   else{
1892 
1893     while (!(xpp->getName() == "Body" &&
1894 	     xpp->getNamespace() == soap_->getEnvelopeUri() &&
1895 	     xpp->getEventType() == XmlPullParser::END_TAG)) {
1896 
1897       Qname elemName (xpp->getName ());
1898       elemName.setNamespace(xpp->getNamespace());
1899 
1900       //doc/literal has ref type element in the part
1901       const SchemaParser * sParser =
1902 	wParser_->getSchemaParser(elemName.getNamespace());
1903       if (!sParser){
1904 
1905 	status_ = false;
1906 	logger_<<"Unknown element "<<elemName<<std::endl;
1907 	return;
1908       }
1909       SchemaValidator * sv= new SchemaValidator(sParser);
1910 
1911       const Element * e = sParser->getElement (elemName);
1912       if(e){
1913 	int typeId = e->getType () ;
1914 	TypeContainer * t = sv->validate (xpp, typeId);
1915 	std::pair<std::string,TypeContainer*> pr(elemName.getLocalName(),t);
1916 	outputs_.push_back(pr);
1917       }
1918       else{
1919 	status_ = false;
1920 	std::cerr<<"Unknown element "<<elemName.getLocalName()<<std::endl;
1921 	return;
1922       }
1923       delete sv;
1924       xpp->nextTag();
1925     }
1926   }
1927   status_ = true;
1928 }
1929 
1930 void
processHeader(XmlPullParser * xpp)1931 WsdlInvoker::processHeader(XmlPullParser *xpp)
1932 {
1933   Qname elem;
1934   const SchemaParser * sParser = 0;
1935   int type = Schema::XSD_INVALID;
1936   xpp->nextTag ();
1937   std::string tag = xpp->getName();
1938 
1939   while (!(xpp->getEventType() == XmlPullParser::END_TAG &&
1940 	   xpp->getName() == "Header")){
1941 
1942 
1943     //first look for xsi:type
1944     if (xpp->getAttributeValue(Schema::SchemaInstaceUri, "type") != "" ) {
1945 
1946       elem = Qname(xpp->getAttributeValue(Schema::SchemaInstaceUri, "type"));
1947       elem.setNamespace(xpp->getNamespace(elem.getPrefix()));
1948       sParser= wParser_->getSchemaParser(elem.getNamespace());
1949       type = (const_cast<SchemaParser*>(sParser))->getTypeId(elem);
1950     }
1951     else {
1952 
1953       elem = Qname(xpp->getName());
1954       elem.setNamespace(xpp->getNamespace());
1955       sParser=wParser_->getSchemaParser(elem.getNamespace());
1956       const Element * e = sParser->getElement (elem);
1957       if(e){
1958 	     type = e->getType ();
1959       }
1960     }
1961     SchemaValidator * sv= new SchemaValidator(sParser);
1962     TypeContainer * t = sv->validate (xpp, type);
1963     outputs_.push_back(std::pair<std::string,TypeContainer*>(tag,t));
1964     oHeaders_++;
1965     xpp->nextTag();
1966     delete sv;
1967   }
1968 }
1969 
1970 bool
isSoapArray(const ComplexType * ct,const SchemaParser * sParser)1971 WsdlInvoker::isSoapArray (const ComplexType * ct,
1972 			  const SchemaParser * sParser)
1973 {
1974   const XSDType * baseType=sParser->getType(ct->getBaseTypeId());
1975   if (baseType) {
1976     if(baseType->getNamespace()==soap_->getEncodingUri() &&
1977        baseType->getName()=="Array")
1978       return true;
1979   }
1980   return false;
1981 }
1982 
1983 void
setCredentials(const std::string & user,const std::string & pass)1984 WsdlInvoker::setCredentials(const std::string & user, const std::string & pass)
1985 {
1986   username_ = user;
1987   password_ = pass;
1988   XmlUtils::setProxyUser(user);
1989   XmlUtils::setProxyPass(pass);
1990   XmlUtils::setProxy(true);
1991 }
1992 
1993 void
setBuildXmlTree(bool p_buildXmlTree)1994 WsdlInvoker::setBuildXmlTree( bool p_buildXmlTree)
1995 {
1996   m_buildXmlTree = p_buildXmlTree;
1997 }
1998 
1999 bool
getBuildXmlTree(void) const2000 WsdlInvoker::getBuildXmlTree( void) const
2001 {
2002   return m_buildXmlTree;
2003 }
2004 
2005 void
setProcessEnvAndBody(bool p_processEnvAndBody)2006 WsdlInvoker::setProcessEnvAndBody( bool p_processEnvAndBody)
2007 {
2008   m_xmlDoc.setProcessEnvAndBody( p_processEnvAndBody);
2009 }
2010 
2011 bool
getProcessEnvAndBody(void) const2012 WsdlInvoker::getProcessEnvAndBody( void) const
2013 {
2014   return m_xmlDoc.getProcessEnvAndBody();
2015 }
2016 
2017 void
setLazyRelativeMatch(bool p_lazyRelativeMatch)2018 WsdlInvoker::setLazyRelativeMatch( bool p_lazyRelativeMatch)
2019 {
2020   m_xmlDoc.setLazyRelativeMatch( p_lazyRelativeMatch);
2021 }
2022 
2023 bool
getLazyRelativeMatch(void) const2024 WsdlInvoker::getLazyRelativeMatch( void) const
2025 {
2026   return m_xmlDoc.getLazyRelativeMatch();
2027 
2028 }
2029 
2030 void
setAuth(const std::string & user,const std::string & pass)2031 WsdlInvoker::setAuth(const std::string & user, const std::string & pass)
2032 {
2033   sAuthUser = user;
2034   sAuthPass = pass;
2035   bAuth = true;
2036 }
2037 
2038 void
setProxy(const std::string & host,int port)2039 WsdlInvoker::setProxy(const std::string & host,int  port)
2040 {
2041   host_ = host;
2042   port_ = port;
2043   std::ostringstream oss;
2044   oss<<host<<":"<<port;
2045   XmlUtils::setProxyHost(oss.str());
2046   XmlUtils::setProxy(true);
2047 }
2048 
2049 std::string
getPrefix(const std::string & nsp)2050 WsdlInvoker::getPrefix(const std::string & nsp)
2051 {
2052 
2053   unsigned int i = 0;
2054   char prefix='1';
2055   while (i<prefixes_.size()) {
2056     if (prefixes_[i] == nsp)
2057       break;
2058     i++;
2059   }
2060 
2061   std::string tmp("ns");
2062   tmp.append(1,prefix+i);
2063   if (i == prefixes_.size())
2064     prefixes_.push_back(nsp);
2065 
2066   return tmp;
2067 
2068 }
2069 
2070 bool
isSubTreeNil()2071 WsdlInvoker::isSubTreeNil() {
2072 
2073   if (!serializeMode_)
2074     return false;
2075   size_t i = n_;
2076   size_t depth =  elems_[n_].parents_.size() - 1;
2077   std::string parent ;
2078   if (depth > 0 )
2079    parent = elems_[n_].parents_[depth - 1 ];
2080   bool nil = false;
2081   for (; i< elems_.size() && elems_[i].parents_.size() >= (depth + 1) &&
2082 	 ( depth == 0  || elems_[i].parents_[depth - 1 ] == parent );i ++){
2083 
2084 	   nil = true;//there are child elements
2085 	   if (!elems_[i].data_[0].empty() )
2086 	     nil = false; //check if it is empty
2087 
2088 	   if (!nil) break; //if non empty then break loop right away
2089 
2090   }
2091   if (nil)
2092     n_ = i;//since this is called only in serializeMode = true advance the counter
2093   return nil;
2094 }
2095 
2096 }
2097 
2098 #ifdef WITH_CURL
2099 size_t
storeResults(void * buf,size_t sz,size_t nmemb,void * userdata)2100 storeResults(void * buf,size_t sz,size_t nmemb,void* userdata)
2101 {
2102     char* sBuffer = (char*) buf;
2103     std::string* strCurlBuffer = (std::string*) userdata;
2104 
2105     int result = 0;
2106     if (strCurlBuffer) {
2107 	strCurlBuffer->append(sBuffer, sz * nmemb);
2108 	result = sz * nmemb;
2109     }
2110 
2111     return result;
2112 }
2113 #endif
2114