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