stdsoap2.cpp 706 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105
  1. /*
  2. stdsoap2.c[pp] 2.8.83
  3. gSOAP runtime engine
  4. gSOAP XML Web services tools
  5. Copyright (C) 2000-2019, Robert van Engelen, Genivia Inc., All Rights Reserved.
  6. This part of the software is released under ONE of the following licenses:
  7. GPL, or the gSOAP public license, or Genivia's license for commercial use.
  8. --------------------------------------------------------------------------------
  9. Contributors:
  10. Wind River Systems, Inc., for the following addition licensed under the gSOAP
  11. public license:
  12. - vxWorks compatible, enabled with compiler option -DVXWORKS
  13. --------------------------------------------------------------------------------
  14. gSOAP public license.
  15. The contents of this file are subject to the gSOAP Public License Version 1.3
  16. (the "License"); you may not use this file except in compliance with the
  17. License. You may obtain a copy of the License at
  18. http://www.cs.fsu.edu/~engelen/soaplicense.html
  19. Software distributed under the License is distributed on an "AS IS" basis,
  20. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  21. for the specific language governing rights and limitations under the License.
  22. The Initial Developer of the Original Code is Robert A. van Engelen.
  23. Copyright (C) 2000-2019, Robert van Engelen, Genivia Inc., All Rights Reserved.
  24. --------------------------------------------------------------------------------
  25. GPL license.
  26. This program is free software; you can redistribute it and/or modify it under
  27. the terms of the GNU General Public License as published by the Free Software
  28. Foundation; either version 2 of the License, or (at your option) any later
  29. version.
  30. This program is distributed in the hope that it will be useful, but WITHOUT ANY
  31. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  32. PARTICULAR PURPOSE. See the GNU General Public License for more details.
  33. You should have received a copy of the GNU General Public License along with
  34. this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  35. Place, Suite 330, Boston, MA 02111-1307 USA
  36. Author contact information:
  37. engelen@genivia.com / engelen@acm.org
  38. This program is released under the GPL with the additional exemption that
  39. compiling, linking, and/or using OpenSSL is allowed.
  40. --------------------------------------------------------------------------------
  41. A commercial use license is available from Genivia, Inc., contact@genivia.com
  42. --------------------------------------------------------------------------------
  43. */
  44. const char *debug;
  45. //std::cerr<<"Recieved data: s "<<soap->body<<std::endl;
  46. #define GSOAP_LIB_VERSION 20883
  47. #ifdef AS400
  48. # pragma convert(819) /* EBCDIC to ASCII */
  49. #endif
  50. #if defined(__gnu_linux__) && !defined(_GNU_SOURCE)
  51. # define _GNU_SOURCE 1
  52. #endif
  53. #include "stdsoap2.h"
  54. #if GSOAP_VERSION != GSOAP_LIB_VERSION
  55. # error "GSOAP VERSION MISMATCH IN LIBRARY: PLEASE REINSTALL PACKAGE"
  56. #endif
  57. #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
  58. # include <ipcom_key_db.h> /* vxWorks compatible */
  59. #endif
  60. #ifdef __BORLANDC__
  61. # pragma warn -8060
  62. #else
  63. # ifdef WIN32
  64. # ifdef UNDER_CE
  65. # pragma comment(lib, "ws2.lib") /* WinCE */
  66. # else
  67. # pragma comment(lib, "Ws2_32.lib")
  68. # endif
  69. # pragma warning(disable : 4996) /* disable deprecation warnings */
  70. # endif
  71. #endif
  72. #ifdef __cplusplus
  73. SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.8.83 2019-04-18 00:00:00 GMT")
  74. extern "C" {
  75. #else
  76. SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.8.83 2019-04-18 00:00:00 GMT")
  77. #endif
  78. /* 8bit character representing unknown character entity or multibyte data */
  79. #ifndef SOAP_UNKNOWN_CHAR
  80. # define SOAP_UNKNOWN_CHAR (0x7F)
  81. #endif
  82. /* unicode character representing unknown characters outside the XML 1.0 UTF8 unicode space */
  83. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  84. # ifndef SOAP_UNKNOWN_UNICODE_CHAR
  85. # define SOAP_UNKNOWN_UNICODE_CHAR (0xFFFD)
  86. # endif
  87. #endif
  88. /* EOF=-1 */
  89. #define SOAP_LT (soap_wchar)(-2) /* XML-specific '<' */
  90. #define SOAP_TT (soap_wchar)(-3) /* XML-specific '</' */
  91. #define SOAP_GT (soap_wchar)(-4) /* XML-specific '>' */
  92. #define SOAP_QT (soap_wchar)(-5) /* XML-specific '"' */
  93. #define SOAP_AP (soap_wchar)(-6) /* XML-specific ''' */
  94. #define soap_coblank(c) ((c)+1 > 0 && (c) <= 32)
  95. #if defined(WIN32) && !defined(UNDER_CE)
  96. #define soap_hash_ptr(p) ((size_t)((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1)))
  97. #else
  98. #define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1)))
  99. #endif
  100. #ifdef SOAP_DEBUG
  101. static void soap_init_logs(struct soap*);
  102. static void soap_close_logfile(struct soap*, int);
  103. static void soap_set_logfile(struct soap*, int, const char*);
  104. #endif
  105. #ifdef SOAP_MEM_DEBUG
  106. static void soap_init_mht(struct soap *);
  107. static void soap_free_mht(struct soap *);
  108. static void soap_track_unlink(struct soap *, const void *);
  109. #endif
  110. static int soap_set_error(struct soap *, const char *, const char *, const char *, const char *, int);
  111. static int soap_copy_fault(struct soap *, const char *, const char *, const char *, const char *);
  112. static int soap_getattrval(struct soap *, char *, size_t *, soap_wchar);
  113. static void soap_version(struct soap *);
  114. static void soap_free_ns(struct soap *);
  115. static soap_wchar soap_char(struct soap *);
  116. static soap_wchar soap_getpi(struct soap *);
  117. static int soap_isxdigit(int);
  118. static void *fplugin(struct soap *, const char *);
  119. static ULONG64 soap_count_attachments(struct soap *);
  120. static int soap_try_connect_command(struct soap *, int http_command, const char *endpoint, const char *action);
  121. static int soap_init_send(struct soap *);
  122. #ifdef WITH_NTLM
  123. static int soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const char *host, int port);
  124. #endif
  125. #ifndef WITH_NOIDREF
  126. static int soap_has_copies(struct soap *, const char *, const char *);
  127. static int soap_type_punned(struct soap *, const struct soap_ilist *);
  128. static int soap_is_shaky(struct soap *, void *);
  129. static void soap_init_iht(struct soap *);
  130. static void soap_free_iht(struct soap *);
  131. #endif
  132. static void soap_init_pht(struct soap *);
  133. static void soap_free_pht(struct soap *);
  134. #ifndef WITH_LEAN
  135. static const char *soap_set_validation_fault(struct soap *, const char *, const char *);
  136. static int soap_isnumeric(struct soap *, const char *);
  137. static struct soap_nlist *
  138. soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized, short isearly);
  139. static void soap_utilize_ns(struct soap *soap, const char *tag, short isearly);
  140. static const wchar_t *
  141. soap_wstring(struct soap *soap, const char *s, int flag, long minlen, long maxlen, const char *pattern);
  142. static wchar_t *soap_wcollapse(struct soap *soap, wchar_t *s, int flag, int insitu);
  143. #endif
  144. static const char *
  145. soap_string(struct soap *soap, const char *s, int flag, long minlen, long maxlen, const char *pattern);
  146. static char *soap_collapse(struct soap *soap, char *s, int flag, int insitu);
  147. static const char *soap_QName(struct soap *soap, const char *s, long minlen, long maxlen, const char *pattern);
  148. #ifndef WITH_LEANER
  149. static int soap_begin_attachments(struct soap *);
  150. static int soap_end_attachments(struct soap *soap);
  151. static struct soap_multipart *
  152. soap_alloc_multipart(struct soap *, struct soap_multipart **, struct soap_multipart **, const char *, size_t);
  153. static int soap_putdimefield(struct soap *, const char *, size_t);
  154. static char *soap_getdimefield(struct soap *, size_t);
  155. static void soap_select_mime_boundary(struct soap *);
  156. static int soap_valid_mime_boundary(struct soap *);
  157. static void soap_resolve_attachment(struct soap *, struct soap_multipart *);
  158. #endif
  159. #ifdef WITH_GZIP
  160. static int soap_getgziphdr(struct soap*);
  161. #endif
  162. #ifdef WITH_OPENSSL
  163. # ifndef SOAP_SSL_RSA_BITS
  164. # define SOAP_SSL_RSA_BITS 2048
  165. # endif
  166. static int soap_ssl_init_done = 0;
  167. static int ssl_auth_init(struct soap*);
  168. static int ssl_verify_callback(int, X509_STORE_CTX*);
  169. static int ssl_verify_callback_allow_expired_certificate(int, X509_STORE_CTX*);
  170. static int ssl_password(char*, int, int, void *);
  171. #endif
  172. #ifdef WITH_GNUTLS
  173. # ifndef SOAP_SSL_RSA_BITS
  174. # define SOAP_SSL_RSA_BITS 2048
  175. # endif
  176. static int soap_ssl_init_done = 0;
  177. static int ssl_auth_init(struct soap*);
  178. static const char *ssl_verify(struct soap *soap, const char *host);
  179. # if GNUTLS_VERSION_NUMBER < 0x020b00
  180. # if defined(HAVE_PTHREAD_H)
  181. # include <pthread.h>
  182. /* make GNUTLS thread safe with pthreads */
  183. GCRY_THREAD_OPTION_PTHREAD_IMPL;
  184. # elif defined(HAVE_PTH_H)
  185. #include <pth.h>
  186. /* make GNUTLS thread safe with PTH */
  187. GCRY_THREAD_OPTION_PTH_IMPL;
  188. # endif
  189. # endif
  190. #endif
  191. #ifdef WITH_SYSTEMSSL
  192. static int ssl_auth_init(struct soap*);
  193. static int ssl_recv(int sk, void *s, int n, char *user);
  194. static int ssl_send(int sk, void *s, int n, char *user);
  195. #endif
  196. #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
  197. static const char *soap_decode(char *, size_t, const char *, const char *);
  198. #endif
  199. #ifndef WITH_NOHTTP
  200. static soap_wchar soap_getchunkchar(struct soap *);
  201. static const char *http_error(struct soap *, int);
  202. static int http_get(struct soap *);
  203. static int http_put(struct soap *);
  204. static int http_patch(struct soap *);
  205. static int http_del(struct soap *);
  206. static int http_200(struct soap *);
  207. static int http_post(struct soap *, const char *, const char *, int, const char *, const char *, ULONG64);
  208. static int http_send_header(struct soap *, const char *);
  209. static int http_post_header(struct soap *, const char *, const char *);
  210. static int http_response(struct soap *, int, ULONG64);
  211. static int http_parse(struct soap *);
  212. static int http_parse_header(struct soap *, const char *, const char *);
  213. #endif
  214. #ifndef WITH_NOIO
  215. static int fsend(struct soap *, const char *, size_t);
  216. static size_t frecv(struct soap *, char *, size_t);
  217. static int tcp_init(struct soap *);
  218. static const char *tcp_error(struct soap *);
  219. #if !defined(WITH_IPV6)
  220. static int tcp_gethost(struct soap *, const char *addr, struct in_addr *inaddr);
  221. #endif
  222. #if !defined(WITH_IPV6) || defined(WITH_COOKIES)
  223. static int tcp_gethostbyname(struct soap *, const char *addr, struct hostent *hostent, struct in_addr *inaddr);
  224. #endif
  225. static SOAP_SOCKET tcp_connect(struct soap *, const char *endpoint, const char *host, int port);
  226. static SOAP_SOCKET tcp_accept(struct soap *, SOAP_SOCKET, struct sockaddr *, int *);
  227. static int tcp_select(struct soap *, SOAP_SOCKET, int, int);
  228. static int tcp_disconnect(struct soap *);
  229. static int tcp_closesocket(struct soap *, SOAP_SOCKET);
  230. static int tcp_shutdownsocket(struct soap *, SOAP_SOCKET, int);
  231. static const char *soap_strerror(struct soap *);
  232. #define SOAP_TCP_SELECT_RCV 0x1
  233. #define SOAP_TCP_SELECT_SND 0x2
  234. #define SOAP_TCP_SELECT_ERR 0x4
  235. #define SOAP_TCP_SELECT_ALL 0x7
  236. #define SOAP_TCP_SELECT_PIP 0x8
  237. #if defined(WIN32)
  238. #define SOAP_SOCKBLOCK(fd) \
  239. { \
  240. u_long blocking = 0; \
  241. ioctlsocket(fd, FIONBIO, &blocking); \
  242. }
  243. #define SOAP_SOCKNONBLOCK(fd) \
  244. { \
  245. u_long nonblocking = 1; \
  246. ioctlsocket(fd, FIONBIO, &nonblocking); \
  247. }
  248. #elif defined(VXWORKS)
  249. #define SOAP_SOCKBLOCK(fd) \
  250. { \
  251. u_long blocking = 0; \
  252. ioctl(fd, FIONBIO, (int)(&blocking)); \
  253. }
  254. #define SOAP_SOCKNONBLOCK(fd) \
  255. { \
  256. u_long nonblocking = 1; \
  257. ioctl(fd, FIONBIO, (int)(&nonblocking)); \
  258. }
  259. #elif defined(__VMS)
  260. #define SOAP_SOCKBLOCK(fd) \
  261. { \
  262. int blocking = 0; \
  263. ioctl(fd, FIONBIO, &blocking); \
  264. }
  265. #define SOAP_SOCKNONBLOCK(fd) \
  266. { \
  267. int nonblocking = 1; \
  268. ioctl(fd, FIONBIO, &nonblocking); \
  269. }
  270. #elif defined(SYMBIAN)
  271. #define SOAP_SOCKBLOCK(fd) \
  272. { \
  273. long blocking = 0; \
  274. ioctl(fd, 0/*FIONBIO*/, &blocking); \
  275. }
  276. #define SOAP_SOCKNONBLOCK(fd) \
  277. { \
  278. long nonblocking = 1; \
  279. ioctl(fd, 0/*FIONBIO*/, &nonblocking); \
  280. }
  281. #else
  282. #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK);
  283. #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
  284. #endif
  285. #endif
  286. static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/";
  287. static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/";
  288. static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope";
  289. static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding";
  290. static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc";
  291. const union soap_double_nan soap_double_nan = {{0xFFFFFFFF, 0xFFFFFFFF}};
  292. const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  293. const char soap_base64i[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63";
  294. #ifndef WITH_LEAN
  295. static const char soap_indent[21] = "\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
  296. /* Alternative indentation form for SOAP_XML_INDENT with spaces instead of tabs:
  297. static const char soap_indent[41] = "\n ";
  298. */
  299. #endif
  300. #ifndef SOAP_CANARY
  301. # define SOAP_CANARY (0xC0DE)
  302. #endif
  303. static const char soap_padding[4] = "\0\0\0";
  304. #define SOAP_STR_PADDING (soap_padding)
  305. #define SOAP_STR_EOS (soap_padding)
  306. #define SOAP_NON_NULL (soap_padding)
  307. #ifndef WITH_LEAN
  308. static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */
  309. {
  310. {160, "nbsp"},
  311. {161, "iexcl"},
  312. {162, "cent"},
  313. {163, "pound"},
  314. {164, "curren"},
  315. {165, "yen"},
  316. {166, "brvbar"},
  317. {167, "sect"},
  318. {168, "uml"},
  319. {169, "copy"},
  320. {170, "ordf"},
  321. {171, "laquo"},
  322. {172, "not"},
  323. {173, "shy"},
  324. {174, "reg"},
  325. {175, "macr"},
  326. {176, "deg"},
  327. {177, "plusmn"},
  328. {178, "sup2"},
  329. {179, "sup3"},
  330. {180, "acute"},
  331. {181, "micro"},
  332. {182, "para"},
  333. {183, "middot"},
  334. {184, "cedil"},
  335. {185, "sup1"},
  336. {186, "ordm"},
  337. {187, "raquo"},
  338. {188, "frac14"},
  339. {189, "frac12"},
  340. {190, "frac34"},
  341. {191, "iquest"},
  342. {192, "Agrave"},
  343. {193, "Aacute"},
  344. {194, "Acirc"},
  345. {195, "Atilde"},
  346. {196, "Auml"},
  347. {197, "Aring"},
  348. {198, "AElig"},
  349. {199, "Ccedil"},
  350. {200, "Egrave"},
  351. {201, "Eacute"},
  352. {202, "Ecirc"},
  353. {203, "Euml"},
  354. {204, "Igrave"},
  355. {205, "Iacute"},
  356. {206, "Icirc"},
  357. {207, "Iuml"},
  358. {208, "ETH"},
  359. {209, "Ntilde"},
  360. {210, "Ograve"},
  361. {211, "Oacute"},
  362. {212, "Ocirc"},
  363. {213, "Otilde"},
  364. {214, "Ouml"},
  365. {215, "times"},
  366. {216, "Oslash"},
  367. {217, "Ugrave"},
  368. {218, "Uacute"},
  369. {219, "Ucirc"},
  370. {220, "Uuml"},
  371. {221, "Yacute"},
  372. {222, "THORN"},
  373. {223, "szlig"},
  374. {224, "agrave"},
  375. {225, "aacute"},
  376. {226, "acirc"},
  377. {227, "atilde"},
  378. {228, "auml"},
  379. {229, "aring"},
  380. {230, "aelig"},
  381. {231, "ccedil"},
  382. {232, "egrave"},
  383. {233, "eacute"},
  384. {234, "ecirc"},
  385. {235, "euml"},
  386. {236, "igrave"},
  387. {237, "iacute"},
  388. {238, "icirc"},
  389. {239, "iuml"},
  390. {240, "eth"},
  391. {241, "ntilde"},
  392. {242, "ograve"},
  393. {243, "oacute"},
  394. {244, "ocirc"},
  395. {245, "otilde"},
  396. {246, "ouml"},
  397. {247, "divide"},
  398. {248, "oslash"},
  399. {249, "ugrave"},
  400. {250, "uacute"},
  401. {251, "ucirc"},
  402. {252, "uuml"},
  403. {253, "yacute"},
  404. {254, "thorn"},
  405. {255, "yuml"},
  406. {0, NULL}
  407. };
  408. #endif
  409. #ifndef WITH_NOIO
  410. #ifndef WITH_LEAN
  411. static const struct soap_code_map h_error_codes[] =
  412. {
  413. #ifdef HOST_NOT_FOUND
  414. {HOST_NOT_FOUND, "Host not found"},
  415. #endif
  416. #ifdef TRY_AGAIN
  417. {TRY_AGAIN, "Try Again"},
  418. #endif
  419. #ifdef NO_RECOVERY
  420. {NO_RECOVERY, "No Recovery"},
  421. #endif
  422. #ifdef NO_DATA
  423. {NO_DATA, "No Data"},
  424. #endif
  425. #ifdef NO_ADDRESS
  426. {NO_ADDRESS, "No Address"},
  427. #endif
  428. {0, NULL}
  429. };
  430. #endif
  431. #endif
  432. #ifndef WITH_NOHTTP
  433. #ifndef WITH_LEAN
  434. static const struct soap_code_map h_http_error_codes[] =
  435. {
  436. {100, "Continue"},
  437. {101, "Switching Protocols"},
  438. {200, "OK"},
  439. {201, "Created"},
  440. {202, "Accepted"},
  441. {203, "Non-Authoritative Information"},
  442. {204, "No Content"},
  443. {205, "Reset Content"},
  444. {206, "Partial Content"},
  445. {300, "Multiple Choices"},
  446. {301, "Moved Permanently"},
  447. {302, "Found"},
  448. {303, "See Other"},
  449. {304, "Not Modified"},
  450. {305, "Use Proxy"},
  451. {307, "Temporary Redirect"},
  452. {400, "Bad Request"},
  453. {401, "Unauthorized"},
  454. {402, "Payment Required"},
  455. {403, "Forbidden"},
  456. {404, "Not Found"},
  457. {405, "Method Not Allowed"},
  458. {406, "Not Acceptable"},
  459. {407, "Proxy Authentication Required"},
  460. {408, "Request Time-out"},
  461. {409, "Conflict"},
  462. {410, "Gone"},
  463. {411, "Length Required"},
  464. {412, "Precondition Failed"},
  465. {413, "Request Entity Too Large"},
  466. {414, "Request-URI Too Large"},
  467. {415, "Unsupported Media Type"},
  468. {416, "Requested range not satisfiable"},
  469. {417, "Expectation Failed"},
  470. {422, "Unprocessable Entity"},
  471. {426, "Upgrade Required"},
  472. {428, "Precondition Required"},
  473. {429, "Too Many Requests"},
  474. {431, "Request Header Fields Too Large"},
  475. {500, "Internal Server Error"},
  476. {501, "Not Implemented"},
  477. {502, "Bad Gateway"},
  478. {503, "Service Unavailable"},
  479. {504, "Gateway Time-out"},
  480. {505, "HTTP Version not supported"},
  481. {511, "Network Authentication Required"},
  482. {0, NULL}
  483. };
  484. #endif
  485. #endif
  486. #ifdef WITH_OPENSSL
  487. static const struct soap_code_map h_ssl_error_codes[] =
  488. {
  489. #define _SSL_ERROR(e) { e, #e }
  490. _SSL_ERROR(SSL_ERROR_SSL),
  491. _SSL_ERROR(SSL_ERROR_ZERO_RETURN),
  492. _SSL_ERROR(SSL_ERROR_WANT_READ),
  493. _SSL_ERROR(SSL_ERROR_WANT_WRITE),
  494. _SSL_ERROR(SSL_ERROR_WANT_CONNECT),
  495. _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP),
  496. _SSL_ERROR(SSL_ERROR_SYSCALL),
  497. { 0, NULL }
  498. };
  499. #endif
  500. #ifndef WITH_LEANER
  501. static const struct soap_code_map mime_codes[] =
  502. {
  503. {SOAP_MIME_7BIT, "7bit"},
  504. {SOAP_MIME_8BIT, "8bit"},
  505. {SOAP_MIME_BINARY, "binary"},
  506. {SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable"},
  507. {SOAP_MIME_BASE64, "base64"},
  508. {SOAP_MIME_IETF_TOKEN, "ietf-token"},
  509. {SOAP_MIME_X_TOKEN, "x-token"},
  510. {0, NULL}
  511. };
  512. #endif
  513. #ifdef WIN32
  514. static int tcp_done = 0;
  515. #endif
  516. #if (defined(_AIX43) || defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R)
  517. #ifndef h_errno
  518. extern int h_errno;
  519. #endif
  520. #endif
  521. /******************************************************************************/
  522. #ifndef WITH_NOIO
  523. static int
  524. fsend(struct soap *soap, const char *s, size_t n) {
  525. int nwritten, err;
  526. SOAP_SOCKET sk;
  527. soap->errnum = 0;
  528. #if defined(__cplusplus) && !defined(WITH_COMPAT)
  529. if (soap->os) {
  530. soap->os->write(s, (std::streamsize) n);
  531. if (soap->os->good())
  532. return SOAP_OK;
  533. return SOAP_EOF;
  534. }
  535. #endif
  536. sk = soap->sendsk;
  537. if (!soap_valid_socket(sk))
  538. sk = soap->socket;
  539. while (n) {
  540. if (soap_valid_socket(sk)) {
  541. if (soap->send_timeout) {
  542. for (;;) {
  543. int r;
  544. #ifdef WITH_SELF_PIPE
  545. #ifdef WITH_OPENSSL
  546. if (soap->ssl)
  547. r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL | SOAP_TCP_SELECT_PIP, soap->send_timeout);
  548. else
  549. #endif
  550. #ifdef WITH_GNUTLS
  551. if (soap->session)
  552. r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL | SOAP_TCP_SELECT_PIP, soap->send_timeout);
  553. else
  554. #endif
  555. #ifdef WITH_SYSTEMSSL
  556. if (soap->ssl)
  557. r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL | SOAP_TCP_SELECT_PIP, soap->send_timeout);
  558. else
  559. #endif
  560. r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR | SOAP_TCP_SELECT_PIP, soap->send_timeout);
  561. if ((r & SOAP_TCP_SELECT_PIP)) /* abort if data is pending on pipe */
  562. {
  563. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection closed by self pipe\n"));
  564. return SOAP_EOF;
  565. }
  566. #else
  567. #ifdef WITH_OPENSSL
  568. if (soap->ssl)
  569. r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout);
  570. else
  571. #endif
  572. #ifdef WITH_GNUTLS
  573. if (soap->session)
  574. r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout);
  575. else
  576. #endif
  577. #ifdef WITH_SYSTEMSSL
  578. if (soap->ssl)
  579. r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout);
  580. else
  581. #endif
  582. r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout);
  583. #endif
  584. if (r > 0)
  585. break;
  586. if (!r)
  587. return SOAP_EOF;
  588. err = soap->errnum;
  589. if (!err)
  590. return soap->error;
  591. if (err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
  592. return SOAP_EOF;
  593. }
  594. }
  595. #ifndef WITH_LEAN
  596. if (soap->transfer_timeout) {
  597. time_t now = time(NULL);
  598. if ((soap->transfer_timeout > 0 &&
  599. difftime(now, (time_t) soap->start) > (double) soap->transfer_timeout)
  600. || (soap->transfer_timeout < 0 &&
  601. difftime(now, (time_t) soap->start) > -1000000.0 * (double) soap->transfer_timeout))
  602. return SOAP_EOF;
  603. }
  604. #endif
  605. #ifdef WITH_OPENSSL
  606. if (soap->ssl)
  607. nwritten = SSL_write(soap->ssl, s, (int)n);
  608. else if (soap->bio)
  609. nwritten = BIO_write(soap->bio, s, (int)n);
  610. else
  611. #endif
  612. #ifdef WITH_GNUTLS
  613. if (soap->session)
  614. nwritten = gnutls_record_send(soap->session, s, n);
  615. else
  616. #endif
  617. #ifdef WITH_SYSTEMSSL
  618. if (soap->ssl)
  619. {
  620. err = gsk_secure_socket_write(soap->ssl, (char*)s, n, &nwritten);
  621. if (err != GSK_OK)
  622. nwritten = 0;
  623. }
  624. else
  625. #endif
  626. #ifndef WITH_LEAN
  627. if ((soap->omode & SOAP_IO_UDP)) {
  628. if (soap->peerlen)
  629. nwritten = sendto(sk, (char *) s, (SOAP_WINSOCKINT) n, soap->socket_flags, &soap->peer.addr,
  630. (SOAP_WINSOCKINT) soap->peerlen);
  631. else
  632. nwritten = send(sk, s, (SOAP_WINSOCKINT) n, soap->socket_flags);
  633. /* retry and back-off algorithm */
  634. /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */
  635. if (nwritten < 0) {
  636. int udp_repeat;
  637. int udp_delay;
  638. if ((soap->connect_flags & SO_BROADCAST))
  639. udp_repeat = 2; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */
  640. else
  641. udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */
  642. udp_delay = ((unsigned int) soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */
  643. do {
  644. tcp_select(soap, sk, SOAP_TCP_SELECT_ERR, -1000 * udp_delay);
  645. if (soap->peerlen)
  646. nwritten = sendto(sk, (char *) s, (SOAP_WINSOCKINT) n, soap->socket_flags, &soap->peer.addr,
  647. (SOAP_WINSOCKINT) soap->peerlen);
  648. else
  649. nwritten = send(sk, s, (SOAP_WINSOCKINT) n, soap->socket_flags);
  650. udp_delay <<= 1;
  651. if (udp_delay > 500) /* UDP_UPPER_DELAY */
  652. udp_delay = 500;
  653. } while (nwritten < 0 && --udp_repeat > 0);
  654. }
  655. if (nwritten < 0) {
  656. err = soap_socket_errno(sk);
  657. if (err && err != SOAP_EINTR) {
  658. soap->errnum = err;
  659. return SOAP_EOF;
  660. }
  661. nwritten = 0; /* and call write() again */
  662. }
  663. } else
  664. #endif
  665. #if !defined(AS400)
  666. nwritten = send(sk, s, (int) n, soap->socket_flags);
  667. #else
  668. nwritten = send(sk, (void*)s, n, soap->socket_flags);
  669. #endif
  670. if (nwritten <= 0) {
  671. int r = 0;
  672. err = soap_socket_errno(sk);
  673. #ifdef WITH_OPENSSL
  674. if (soap->ssl && (r = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
  675. {
  676. soap->errnum = err;
  677. return SOAP_EOF;
  678. }
  679. #endif
  680. #ifdef WITH_GNUTLS
  681. if (soap->session)
  682. {
  683. if (nwritten == GNUTLS_E_INTERRUPTED)
  684. err = SOAP_EINTR;
  685. else if (nwritten == GNUTLS_E_AGAIN)
  686. err = SOAP_EAGAIN;
  687. }
  688. #endif
  689. if (err == SOAP_EWOULDBLOCK || err == SOAP_EAGAIN) {
  690. #if defined(WITH_OPENSSL)
  691. if (soap->ssl && r == SSL_ERROR_WANT_READ)
  692. r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
  693. else
  694. #elif defined(WITH_GNUTLS)
  695. if (soap->session && !gnutls_record_get_direction(soap->session))
  696. r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
  697. else
  698. #endif
  699. r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR,
  700. soap->send_timeout ? soap->send_timeout : -10000);
  701. if (!r && soap->send_timeout)
  702. return SOAP_EOF;
  703. if (r < 0)
  704. return SOAP_EOF;
  705. } else if (err && err != SOAP_EINTR) {
  706. soap->errnum = err;
  707. return SOAP_EOF;
  708. }
  709. nwritten = 0; /* and call write() again */
  710. }
  711. } else {
  712. #ifdef WITH_FASTCGI
  713. nwritten = fwrite((void*)s, 1, n, stdout);
  714. fflush(stdout);
  715. #else
  716. #ifdef UNDER_CE
  717. nwritten = fwrite(s, 1, n, soap->sendfd);
  718. #else
  719. #ifdef WMW_RPM_IO
  720. /* vxWorks compatible */
  721. if (soap->rpmreqid)
  722. nwritten = (httpBlockPut(soap->rpmreqid, (char*)s, n) == 0) ? n : -1;
  723. else
  724. #endif
  725. #ifdef WIN32
  726. nwritten = _write(soap->sendfd, s, (unsigned int)n);
  727. #else
  728. nwritten = write(soap->sendfd, s, (unsigned int) n);
  729. #endif
  730. #endif
  731. #endif
  732. if (nwritten <= 0) {
  733. #ifndef WITH_FASTCGI
  734. err = soap_errno;
  735. #else
  736. err = EOF;
  737. #endif
  738. if (err && err != SOAP_EINTR && err != SOAP_EWOULDBLOCK && err != SOAP_EAGAIN) {
  739. soap->errnum = err;
  740. return SOAP_EOF;
  741. }
  742. nwritten = 0; /* and call write() again */
  743. }
  744. }
  745. n -= nwritten;
  746. s += nwritten;
  747. }
  748. return SOAP_OK;
  749. }
  750. #endif
  751. /******************************************************************************/
  752. SOAP_FMAC1
  753. int
  754. SOAP_FMAC2
  755. soap_send_raw(struct soap *soap, const char *s, size_t n) {
  756. if (!n)
  757. return SOAP_OK;
  758. #ifndef WITH_LEANER
  759. if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE && (soap->mode & SOAP_IO_LENGTH) &&
  760. (soap->error = soap->fpreparesend(soap, s, n)) != SOAP_OK)
  761. return soap->error;
  762. if (soap->ffiltersend && (soap->error = soap->ffiltersend(soap, &s, &n)) != SOAP_OK)
  763. return soap->error;
  764. #endif
  765. if ((soap->mode & SOAP_IO_LENGTH)) {
  766. soap->count += n;
  767. } else if ((soap->mode & SOAP_IO)) {
  768. size_t i = sizeof(soap->buf) - soap->bufidx;
  769. while (n >= i) {
  770. (void) soap_memcpy((void *) (soap->buf + soap->bufidx), i, (const void *) s, i);
  771. soap->bufidx = sizeof(soap->buf);
  772. if (soap_flush(soap))
  773. return soap->error;
  774. s += i;
  775. n -= i;
  776. i = sizeof(soap->buf);
  777. }
  778. (void) soap_memcpy((void *) (soap->buf + soap->bufidx), sizeof(soap->buf) - soap->bufidx, (const void *) s, n);
  779. soap->bufidx += n;
  780. } else {
  781. return soap_flush_raw(soap, s, n);
  782. }
  783. return SOAP_OK;
  784. }
  785. /******************************************************************************/
  786. SOAP_FMAC1
  787. int
  788. SOAP_FMAC2
  789. soap_flush(struct soap *soap) {
  790. size_t n = soap->bufidx;
  791. if (!n)
  792. return soap->error = soap->fsend(soap, SOAP_STR_EOS, 0); /* force a zero send for HTTP GET and DELETE */
  793. #ifndef WITH_LEANER
  794. if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) {
  795. int r;
  796. if (soap->fpreparesend && (r = soap->fpreparesend(soap, soap->buf, n)) != SOAP_OK)
  797. return soap->error = r;
  798. }
  799. #endif
  800. soap->bufidx = 0;
  801. #ifdef WITH_ZLIB
  802. if ((soap->mode & SOAP_ENC_ZLIB) && soap->d_stream)
  803. {
  804. soap->d_stream->next_in = (Byte*)soap->buf;
  805. soap->d_stream->avail_in = (unsigned int)n;
  806. #ifdef WITH_GZIP
  807. soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n);
  808. #endif
  809. do
  810. {
  811. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream->avail_in));
  812. if (deflate(soap->d_stream, Z_NO_FLUSH) != Z_OK)
  813. {
  814. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
  815. return soap->error = SOAP_ZLIB_ERROR;
  816. }
  817. if (!soap->d_stream->avail_out)
  818. {
  819. if (soap_flush_raw(soap, soap->z_buf, sizeof(soap->buf)))
  820. return soap->error;
  821. soap->d_stream->next_out = (Byte*)soap->z_buf;
  822. soap->d_stream->avail_out = sizeof(soap->buf);
  823. }
  824. } while (soap->d_stream->avail_in);
  825. return SOAP_OK;
  826. }
  827. #endif
  828. return soap_flush_raw(soap, soap->buf, n);
  829. }
  830. /******************************************************************************/
  831. SOAP_FMAC1
  832. int
  833. SOAP_FMAC2
  834. soap_flush_raw(struct soap *soap, const char *s, size_t n) {
  835. if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) {
  836. void *t;
  837. t = soap_push_block(soap, NULL, n);
  838. if (!t)
  839. return soap->error = SOAP_EOM;
  840. (void) soap_memcpy(t, n, (const void *) s, n);
  841. return SOAP_OK;
  842. }
  843. #ifndef WITH_LEANER
  844. if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) {
  845. char t[24];
  846. (SOAP_SNPRINTF(t, sizeof(t), 20), &"\r\n%lX\r\n"[soap->chunksize ? 0 : 2], (unsigned long) n);
  847. DBGMSG(SENT, t, strlen(t));
  848. soap->error = soap->fsend(soap, t, strlen(t));
  849. if (soap->error)
  850. return soap->error;
  851. soap->chunksize += n;
  852. }
  853. DBGMSG(SENT, s, n);
  854. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send %u bytes to socket=%d/fd=%d\n", (unsigned int) n, (int) soap->socket,
  855. soap->sendfd));
  856. #endif
  857. return soap->error = soap->fsend(soap, s, n);
  858. }
  859. /******************************************************************************/
  860. SOAP_FMAC1
  861. int
  862. SOAP_FMAC2
  863. soap_send(struct soap *soap, const char *s) {
  864. if (s)
  865. return soap_send_raw(soap, s, strlen(s));
  866. return SOAP_OK;
  867. }
  868. /******************************************************************************/
  869. #ifndef WITH_LEANER
  870. SOAP_FMAC1
  871. int
  872. SOAP_FMAC2
  873. soap_send2(struct soap *soap, const char *s1, const char *s2) {
  874. if (soap_send(soap, s1))
  875. return soap->error;
  876. return soap_send(soap, s2);
  877. }
  878. #endif
  879. /******************************************************************************/
  880. #ifndef WITH_LEANER
  881. SOAP_FMAC1
  882. int
  883. SOAP_FMAC2
  884. soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3) {
  885. if (soap_send(soap, s1)
  886. || soap_send(soap, s2))
  887. return soap->error;
  888. return soap_send(soap, s3);
  889. }
  890. #endif
  891. /******************************************************************************/
  892. #ifndef WITH_LEANER
  893. SOAP_FMAC1
  894. int
  895. SOAP_FMAC2
  896. soap_query_send_key(struct soap *soap, const char *s) {
  897. if (!s)
  898. return SOAP_OK;
  899. if (!soap->body && soap_send_raw(soap, "&", 1))
  900. return soap->error;
  901. soap->body = 0;
  902. (void) soap_encode_url(s, soap->msgbuf,
  903. (int) sizeof(soap->msgbuf)); /* msgbuf length is max SOAP_TMPLEN or just 1024 bytes */
  904. return soap_send(soap, soap->msgbuf);
  905. }
  906. #endif
  907. /******************************************************************************/
  908. #ifndef WITH_LEANER
  909. SOAP_FMAC1
  910. int
  911. SOAP_FMAC2
  912. soap_query_send_val(struct soap *soap, const char *s) {
  913. if (!s)
  914. return SOAP_OK;
  915. if (soap_send_raw(soap, "=", 1))
  916. return soap->error;
  917. (void) soap_encode_url(s, soap->msgbuf,
  918. (int) sizeof(soap->msgbuf)); /* msgbuf length is max SOAP_TMPLEN or just 1024 bytes */
  919. return soap_send(soap, soap->msgbuf);
  920. }
  921. #endif
  922. /******************************************************************************/
  923. #ifndef WITH_LEANER
  924. SOAP_FMAC1
  925. char *
  926. SOAP_FMAC2
  927. soap_query(struct soap *soap) {
  928. return strchr(soap->path, '?');
  929. }
  930. #endif
  931. /******************************************************************************/
  932. #ifndef WITH_LEANER
  933. SOAP_FMAC1
  934. char *
  935. SOAP_FMAC2
  936. soap_query_key(struct soap *soap, char **s) {
  937. char *t = *s;
  938. (void) soap;
  939. if (t && *t) {
  940. *s = (char *) soap_query_decode(t, strlen(t), t + 1);
  941. return t;
  942. }
  943. return *s = NULL;
  944. }
  945. #endif
  946. /******************************************************************************/
  947. #ifndef WITH_LEANER
  948. SOAP_FMAC1
  949. char *
  950. SOAP_FMAC2
  951. soap_query_val(struct soap *soap, char **s) {
  952. char *t = *s;
  953. (void) soap;
  954. if (t && *t == '=') {
  955. *s = (char *) soap_query_decode(t, strlen(t), t + 1);
  956. return t;
  957. }
  958. return NULL;
  959. }
  960. #endif
  961. /******************************************************************************/
  962. #ifndef WITH_LEANER
  963. SOAP_FMAC1
  964. const char *
  965. SOAP_FMAC2
  966. soap_query_decode(char *buf, size_t len, const char *val) {
  967. const char *s;
  968. char *t;
  969. for (s = val; *s; s++)
  970. if (*s != ' ' && *s != '=')
  971. break;
  972. if (*s == '"') {
  973. t = buf;
  974. s++;
  975. while (*s && *s != '"' && --len)
  976. *t++ = *s++;
  977. *t = '\0';
  978. do s++;
  979. while (*s && *s != '&' && *s != '=');
  980. } else {
  981. t = buf;
  982. while (*s && *s != '&' && *s != '=' && --len) {
  983. switch (*s) {
  984. case '+':
  985. *t++ = ' ';
  986. s++;
  987. break;
  988. case '\t':
  989. case '\n':
  990. case '\r':
  991. case ' ':
  992. s++;
  993. break;
  994. case '%':
  995. *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4) +
  996. (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0');
  997. s += 3;
  998. break;
  999. default:
  1000. *t++ = *s++;
  1001. }
  1002. }
  1003. *t = '\0';
  1004. }
  1005. return s;
  1006. }
  1007. #endif
  1008. /******************************************************************************/
  1009. #ifndef WITH_NOIO
  1010. static size_t
  1011. frecv(struct soap *soap, char *s, size_t n) {
  1012. int r;
  1013. int retries = 100; /* max 100 retries with non-blocking sockets */
  1014. SOAP_SOCKET sk;
  1015. soap->errnum = 0;
  1016. #if defined(__cplusplus) && !defined(WITH_COMPAT)
  1017. if (soap->is) /* recv from C++ stream */
  1018. {
  1019. if (soap->is->good())
  1020. return (size_t) soap->is->read(s,
  1021. (std::streamsize) n).gcount(); /* downcast to std::streamsize is OK: gcount() returns how much we got in s[] */
  1022. return 0;
  1023. }
  1024. #else
  1025. if (soap->is) /* recv from C buffer until NUL */
  1026. {
  1027. size_t l = strlen(soap->is);
  1028. if (l > n)
  1029. l = n;
  1030. (void)soap_memcpy((void*)s, n, soap->is, l);
  1031. soap->is += l;
  1032. return l;
  1033. }
  1034. #endif
  1035. sk = soap->recvsk;
  1036. if (!soap_valid_socket(sk))
  1037. sk = soap->socket;
  1038. if (soap_valid_socket(sk)) {
  1039. for (;;) {
  1040. #if defined(WITH_OPENSSL) || defined(WITH_SYSTEMSSL)
  1041. int err = 0;
  1042. #endif
  1043. #ifdef WITH_OPENSSL
  1044. if (soap->recv_timeout && !soap->ssl) /* OpenSSL: sockets are nonblocking so go ahead to read */
  1045. #else
  1046. if (soap->recv_timeout)
  1047. #endif
  1048. {
  1049. for (;;) {
  1050. #ifdef WITH_SELF_PIPE
  1051. r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR | SOAP_TCP_SELECT_PIP, soap->recv_timeout);
  1052. if ((r & SOAP_TCP_SELECT_PIP)) /* abort if data is pending on pipe */
  1053. {
  1054. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection closed by self pipe\n"));
  1055. return 0;
  1056. }
  1057. #else
  1058. r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout);
  1059. #endif
  1060. if (r > 0)
  1061. break;
  1062. if (!r)
  1063. return 0;
  1064. r = soap->errnum;
  1065. if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
  1066. return 0;
  1067. }
  1068. }
  1069. #ifndef WITH_LEAN
  1070. if (soap->transfer_timeout) {
  1071. time_t now = time(NULL);
  1072. if ((soap->transfer_timeout > 0 &&
  1073. difftime(now, (time_t) soap->start) > (double) soap->transfer_timeout)
  1074. || (soap->transfer_timeout < 0 &&
  1075. difftime(now, (time_t) soap->start) > -1000000.0 * (double) soap->transfer_timeout))
  1076. return 0;
  1077. }
  1078. #endif
  1079. #ifdef WITH_OPENSSL
  1080. if (soap->ssl)
  1081. {
  1082. r = SSL_read(soap->ssl, s, (int)n);
  1083. if (r > 0)
  1084. return (size_t)r;
  1085. err = SSL_get_error(soap->ssl, r);
  1086. if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
  1087. return 0;
  1088. }
  1089. else if (soap->bio)
  1090. {
  1091. r = BIO_read(soap->bio, s, (int)n);
  1092. if (r > 0)
  1093. return (size_t)r;
  1094. return 0;
  1095. }
  1096. else
  1097. #endif
  1098. #ifdef WITH_GNUTLS
  1099. if (soap->session)
  1100. {
  1101. r = (int)gnutls_record_recv(soap->session, s, n);
  1102. if (r >= 0)
  1103. return (size_t)r;
  1104. }
  1105. else
  1106. #endif
  1107. #ifdef WITH_SYSTEMSSL
  1108. if (soap->ssl)
  1109. {
  1110. err = gsk_secure_socket_read(soap->ssl, s, n, &r);
  1111. if (err == GSK_OK && r > 0)
  1112. return (size_t)r;
  1113. if (err != GSK_OK && err != GSK_WOULD_BLOCK && err != GSK_WOULD_BLOCK_WRITE)
  1114. return 0;
  1115. }
  1116. else
  1117. #endif
  1118. {
  1119. #ifndef WITH_LEAN
  1120. if ((soap->omode & SOAP_IO_UDP)) {
  1121. SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T) sizeof(soap->peer);
  1122. memset((void *) &soap->peer, 0, sizeof(soap->peer));
  1123. r = recvfrom(sk, s, (SOAP_WINSOCKINT) n, soap->socket_flags, &soap->peer.addr,
  1124. &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h, SOAP_WINSOCKINT cast is safe due to limited range of n in the engine (64K) */
  1125. soap->peerlen = (size_t) k;
  1126. #ifdef WITH_IPV6
  1127. soap->ip = 0;
  1128. soap->ip6[0] = 0;
  1129. soap->ip6[1] = 0;
  1130. soap->ip6[2] = 0;
  1131. soap->ip6[3] = 0;
  1132. #else
  1133. soap->ip = ntohl(soap->peer.in.sin_addr.s_addr);
  1134. soap->ip6[0] = 0;
  1135. soap->ip6[1] = 0;
  1136. soap->ip6[2] = 0xFFFF;
  1137. soap->ip6[3] = soap->ip;
  1138. #endif
  1139. } else
  1140. #endif
  1141. r = recv(sk, s, (SOAP_WINSOCKINT) n,
  1142. soap->socket_flags); /* SOAP_WINSOCKINT cast is safe due to limited range of n in the engine (64K) */
  1143. if (r >= 0)
  1144. return (size_t) r;
  1145. r = soap_socket_errno(sk);
  1146. if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK) {
  1147. soap->errnum = r;
  1148. return 0;
  1149. }
  1150. }
  1151. #if defined(WITH_OPENSSL)
  1152. if (soap->ssl && err == SSL_ERROR_WANT_WRITE)
  1153. r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
  1154. else
  1155. #elif defined(WITH_GNUTLS)
  1156. if (soap->session && gnutls_record_get_direction(soap->session))
  1157. r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
  1158. else
  1159. #elif defined(WITH_SYSTEMSSL)
  1160. if (soap->ssl && err == GSK_WOULD_BLOCK_WRITE)
  1161. r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
  1162. else
  1163. #endif
  1164. r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR,
  1165. soap->recv_timeout ? soap->recv_timeout : 5);
  1166. if (!r && soap->recv_timeout)
  1167. return 0;
  1168. if (r < 0) {
  1169. r = soap->errnum;
  1170. if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
  1171. return 0;
  1172. }
  1173. if (retries-- <= 0)
  1174. return 0;
  1175. }
  1176. }
  1177. #ifdef WITH_FASTCGI
  1178. return fread(s, 1, n, stdin);
  1179. #else
  1180. #ifdef UNDER_CE
  1181. return fread(s, 1, n, soap->recvfd);
  1182. #else
  1183. #ifdef WMW_RPM_IO
  1184. if (soap->rpmreqid)
  1185. r = httpBlockRead(soap->rpmreqid, s, n);
  1186. else
  1187. #endif
  1188. #ifdef WIN32
  1189. r = _read(soap->recvfd, s, (unsigned int)n);
  1190. #else
  1191. r = read(soap->recvfd, s, n);
  1192. #endif
  1193. if (r >= 0)
  1194. return (size_t) r;
  1195. soap->errnum = soap_errno;
  1196. return 0;
  1197. #endif
  1198. #endif
  1199. }
  1200. #endif
  1201. /******************************************************************************/
  1202. #ifndef WITH_NOHTTP
  1203. static soap_wchar
  1204. soap_getchunkchar(struct soap *soap) {
  1205. if (soap->bufidx < soap->buflen)
  1206. return soap->buf[soap->bufidx++];
  1207. soap->bufidx = 0;
  1208. soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, sizeof(soap->buf));
  1209. DBGLOG(TEST,
  1210. SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int) soap->buflen, (int) soap->socket,
  1211. soap->recvfd));
  1212. DBGMSG(RECV, soap->buf, soap->buflen);
  1213. if (soap->buflen)
  1214. return soap->buf[soap->bufidx++];
  1215. return EOF;
  1216. }
  1217. #endif
  1218. /******************************************************************************/
  1219. static int
  1220. soap_isxdigit(int c) {
  1221. return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
  1222. }
  1223. /******************************************************************************/
  1224. SOAP_FMAC1
  1225. int
  1226. SOAP_FMAC2
  1227. soap_recv_raw(struct soap *soap) {
  1228. size_t ret;
  1229. #if !defined(WITH_LEANER) || defined(WITH_ZLIB)
  1230. int r;
  1231. #endif
  1232. #ifdef WITH_ZLIB
  1233. if ((soap->mode & SOAP_ENC_ZLIB) && soap->d_stream)
  1234. {
  1235. if (soap->d_stream->next_out == Z_NULL)
  1236. {
  1237. soap->bufidx = soap->buflen = 0;
  1238. return EOF;
  1239. }
  1240. if (soap->d_stream->avail_in || !soap->d_stream->avail_out)
  1241. {
  1242. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n"));
  1243. soap->d_stream->next_out = (Byte*)soap->buf;
  1244. soap->d_stream->avail_out = sizeof(soap->buf);
  1245. r = inflate(soap->d_stream, Z_NO_FLUSH);
  1246. if (r == Z_NEED_DICT && soap->z_dict)
  1247. r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len);
  1248. if (r == Z_OK || r == Z_STREAM_END)
  1249. {
  1250. soap->bufidx = 0;
  1251. ret = soap->buflen = sizeof(soap->buf) - soap->d_stream->avail_out;
  1252. if (soap->zlib_in == SOAP_ZLIB_GZIP)
  1253. soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)ret);
  1254. if (r == Z_STREAM_END)
  1255. {
  1256. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
  1257. soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
  1258. soap->d_stream->next_out = Z_NULL;
  1259. }
  1260. if (ret)
  1261. {
  1262. if (soap->count + ret < soap->count)
  1263. return soap->error = SOAP_EOF;
  1264. soap->count += ret;
  1265. if (soap->recv_maxlength && soap->count > soap->recv_maxlength)
  1266. return soap->error = SOAP_EOF;
  1267. if (soap->count > SOAP_MAXINFLATESIZE && soap->z_ratio_in < SOAP_MINDEFLATERATIO)
  1268. {
  1269. soap->d_stream->msg = (char*)"caught SOAP_MINDEFLATERATIO explosive decompression guard (remedy: increase SOAP_MAXINFLATESIZE and/or decrease SOAP_MINDEFLATERATIO)";
  1270. return soap->error = SOAP_ZLIB_ERROR;
  1271. }
  1272. DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
  1273. DBGMSG(RECV, soap->buf, ret);
  1274. DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n----\n"));
  1275. #ifndef WITH_LEANER
  1276. if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)) != SOAP_OK)
  1277. return soap->error = r;
  1278. #endif
  1279. return SOAP_OK;
  1280. }
  1281. }
  1282. else if (r != Z_BUF_ERROR)
  1283. {
  1284. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
  1285. soap->d_stream->next_out = Z_NULL;
  1286. return soap->error = SOAP_ZLIB_ERROR;
  1287. }
  1288. }
  1289. zlib_again:
  1290. if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize)
  1291. {
  1292. (void)soap_memcpy((void*)soap->buf, sizeof(soap->buf), (const void*)soap->z_buf, sizeof(soap->buf));
  1293. soap->buflen = soap->z_buflen;
  1294. }
  1295. DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- compressed ----\n"));
  1296. }
  1297. #endif
  1298. #ifndef WITH_NOHTTP
  1299. if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */
  1300. {
  1301. for (;;) {
  1302. soap_wchar c;
  1303. char *t, tmp[17];
  1304. if (soap->chunksize) {
  1305. soap->buflen = ret = soap->frecv(soap, soap->buf,
  1306. soap->chunksize > sizeof(soap->buf) ? sizeof(soap->buf)
  1307. : soap->chunksize);
  1308. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int) ret));
  1309. DBGMSG(RECV, soap->buf, ret);
  1310. soap->bufidx = 0;
  1311. if (!ret) {
  1312. soap->ahead = EOF;
  1313. return EOF;
  1314. }
  1315. soap->chunksize -= ret;
  1316. break;
  1317. }
  1318. if (!soap->chunkbuflen) {
  1319. soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, sizeof(soap->buf));
  1320. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket=%d\n", (unsigned int) ret,
  1321. (int) soap->socket));
  1322. DBGMSG(RECV, soap->buf, ret);
  1323. soap->bufidx = 0;
  1324. if (!ret) {
  1325. soap->ahead = EOF;
  1326. return EOF;
  1327. }
  1328. } else {
  1329. soap->bufidx = soap->buflen;
  1330. }
  1331. soap->buflen = soap->chunkbuflen;
  1332. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int) soap->bufidx,
  1333. (unsigned int) soap->buflen));
  1334. while (!soap_isxdigit((int) (c = soap_getchunkchar(soap)))) {
  1335. if ((int) c == EOF) {
  1336. soap->ahead = EOF;
  1337. return EOF;
  1338. }
  1339. }
  1340. t = tmp;
  1341. do {
  1342. *t++ = (char) c;
  1343. } while (soap_isxdigit((int) (c = soap_getchunkchar(soap))) && (size_t) (t - tmp) < sizeof(tmp) - 1);
  1344. while ((int) c != EOF && c != '\n')
  1345. c = soap_getchunkchar(soap);
  1346. if ((int) c == EOF) {
  1347. soap->ahead = EOF;
  1348. return EOF;
  1349. }
  1350. *t = '\0';
  1351. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunk size = %s (hex)\n", tmp));
  1352. soap->chunksize = (size_t) soap_strtoul(tmp, &t, 16);
  1353. if (!soap->chunksize) {
  1354. soap->bufidx = soap->buflen = soap->chunkbuflen = 0;
  1355. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n"));
  1356. ret = 0;
  1357. soap->ahead = EOF;
  1358. break;
  1359. }
  1360. soap->buflen = soap->bufidx + soap->chunksize;
  1361. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int) soap->bufidx,
  1362. (unsigned int) soap->buflen, tmp));
  1363. if (soap->buflen > soap->chunkbuflen) {
  1364. soap->buflen = soap->chunkbuflen;
  1365. soap->chunksize -= soap->buflen - soap->bufidx;
  1366. soap->chunkbuflen = 0;
  1367. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n",
  1368. (unsigned int) (soap->buflen - soap->bufidx)));
  1369. } else if (soap->chunkbuflen) {
  1370. soap->chunksize = 0;
  1371. }
  1372. ret = soap->buflen - soap->bufidx;
  1373. if (ret)
  1374. break;
  1375. }
  1376. } else
  1377. #endif
  1378. {
  1379. soap->bufidx = 0;
  1380. soap->buflen = ret = soap->frecv(soap, soap->buf, sizeof(soap->buf));
  1381. DBGLOG(TEST,
  1382. SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int) ret, (int) soap->socket,
  1383. soap->recvfd));
  1384. DBGMSG(RECV, soap->buf, ret);
  1385. }
  1386. #ifdef WITH_ZLIB
  1387. if ((soap->mode & SOAP_ENC_ZLIB))
  1388. {
  1389. (void)soap_memcpy((void*)soap->z_buf, sizeof(soap->buf), (const void*)soap->buf, sizeof(soap->buf));
  1390. soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
  1391. soap->d_stream->avail_in = (unsigned int)ret;
  1392. soap->d_stream->next_out = (Byte*)soap->buf;
  1393. soap->d_stream->avail_out = sizeof(soap->buf);
  1394. r = inflate(soap->d_stream, Z_NO_FLUSH);
  1395. if (r == Z_NEED_DICT && soap->z_dict)
  1396. r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len);
  1397. if (r == Z_OK || r == Z_STREAM_END)
  1398. {
  1399. soap->bufidx = 0;
  1400. soap->z_buflen = soap->buflen;
  1401. soap->buflen = sizeof(soap->buf) - soap->d_stream->avail_out;
  1402. if (soap->zlib_in == SOAP_ZLIB_GZIP)
  1403. soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen);
  1404. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)soap->buflen));
  1405. if (ret && !soap->buflen && r != Z_STREAM_END)
  1406. goto zlib_again;
  1407. ret = soap->buflen;
  1408. if (r == Z_STREAM_END)
  1409. {
  1410. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
  1411. soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
  1412. soap->d_stream->next_out = Z_NULL;
  1413. }
  1414. if (soap->count + ret > SOAP_MAXINFLATESIZE && soap->z_ratio_in < SOAP_MINDEFLATERATIO)
  1415. {
  1416. soap->d_stream->msg = (char*)"caught SOAP_MINDEFLATERATIO explosive decompression guard (remedy: increase SOAP_MAXINFLATESIZE and/or decrease SOAP_MINDEFLATERATIO)";
  1417. return soap->error = SOAP_ZLIB_ERROR;
  1418. }
  1419. DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
  1420. DBGMSG(RECV, soap->buf, ret);
  1421. #ifndef WITH_LEANER
  1422. if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)) != SOAP_OK)
  1423. return soap->error = r;
  1424. #endif
  1425. }
  1426. else
  1427. {
  1428. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
  1429. soap->d_stream->next_out = Z_NULL;
  1430. return soap->error = SOAP_ZLIB_ERROR;
  1431. }
  1432. }
  1433. #endif
  1434. #ifndef WITH_LEANER
  1435. if (soap->fpreparerecv
  1436. #ifdef WITH_ZLIB
  1437. && soap->zlib_in == SOAP_ZLIB_NONE
  1438. #endif
  1439. && (r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, ret)))
  1440. return soap->error = r;
  1441. #endif
  1442. if (ret) {
  1443. if (soap->count + ret < soap->count)
  1444. return EOF;
  1445. soap->count += ret;
  1446. if (soap->recv_maxlength && soap->count > soap->recv_maxlength)
  1447. return EOF;
  1448. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read count="
  1449. SOAP_ULONG_FORMAT
  1450. " (+%lu)\n", soap->count, (unsigned long) ret));
  1451. return SOAP_OK;
  1452. }
  1453. return EOF;
  1454. }
  1455. /******************************************************************************/
  1456. SOAP_FMAC1
  1457. int
  1458. SOAP_FMAC2
  1459. soap_recv(struct soap *soap) {
  1460. #ifndef WITH_LEANER
  1461. if ((soap->mode & SOAP_ENC_DIME)) {
  1462. if (soap->dime.buflen) {
  1463. char *s;
  1464. int i;
  1465. unsigned char tmp[12];
  1466. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked SOAP in DIME is in buffer\n"));
  1467. soap->buflen = soap->dime.buflen;
  1468. soap->dime.buflen = 0;
  1469. soap->dime.chunksize = 0;
  1470. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long) soap->dime.size & 3));
  1471. for (i = -(long) soap->dime.size & 3; i > 0; i--) {
  1472. soap->bufidx++;
  1473. if (soap->bufidx >= soap->buflen)
  1474. if (soap_recv_raw(soap))
  1475. return EOF;
  1476. }
  1477. if (!(soap->dime.flags & SOAP_DIME_CF))
  1478. return SOAP_OK;
  1479. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next SOAP in DIME chunk\n"));
  1480. s = (char *) tmp;
  1481. for (i = 12; i > 0; i--) {
  1482. *s++ = soap->buf[soap->bufidx++];
  1483. if (soap->bufidx >= soap->buflen)
  1484. if (soap_recv_raw(soap))
  1485. return EOF;
  1486. }
  1487. if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION)
  1488. return soap->error = SOAP_DIME_MISMATCH;
  1489. soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0);
  1490. soap->dime.size =
  1491. ((size_t) tmp[8] << 24) | ((size_t) tmp[9] << 16) | ((size_t) tmp[10] << 8) | ((size_t) tmp[11]);
  1492. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get SOAP in DIME chunk (%u bytes)\n", (unsigned int) soap->dime.size));
  1493. soap->dime.chunksize = soap->dime.size;
  1494. if (soap->buflen - soap->bufidx >= soap->dime.size) {
  1495. if ((soap->dime.flags & SOAP_DIME_ME)) {
  1496. soap->mode &= ~SOAP_ENC_DIME;
  1497. } else {
  1498. soap->dime.buflen = soap->buflen;
  1499. soap->buflen = soap->bufidx + soap->dime.chunksize;
  1500. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME (%u bytes buffered)\n",
  1501. (unsigned int) soap->buflen));
  1502. }
  1503. } else {
  1504. soap->dime.chunksize -= soap->buflen - soap->bufidx;
  1505. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME (%u bytes in chunk left)\n",
  1506. (unsigned int) soap->dime.chunksize));
  1507. }
  1508. return SOAP_OK;
  1509. }
  1510. if (soap->dime.chunksize) {
  1511. if (soap_recv_raw(soap))
  1512. return EOF;
  1513. if (soap->buflen - soap->bufidx >= soap->dime.chunksize) {
  1514. if ((soap->dime.flags & SOAP_DIME_ME)) {
  1515. soap->dime.chunksize = 0;
  1516. soap->mode &= ~SOAP_ENC_DIME;
  1517. } else {
  1518. soap->dime.buflen = soap->buflen;
  1519. soap->buflen = soap->bufidx + soap->dime.chunksize;
  1520. soap->dime.chunksize = 0;
  1521. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME (%u bytes buffered)\n",
  1522. (unsigned int) soap->buflen));
  1523. }
  1524. } else {
  1525. soap->dime.chunksize -= soap->buflen - soap->bufidx;
  1526. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME (%u bytes in chunk left)\n",
  1527. (unsigned int) soap->dime.chunksize));
  1528. }
  1529. return SOAP_OK;
  1530. }
  1531. }
  1532. if (soap->ffilterrecv) {
  1533. int err;
  1534. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Filter recverror = %d bufidx = %lu buflen = %lu\n", soap->recverror,
  1535. (unsigned long) soap->bufidx, (unsigned long) soap->buflen));
  1536. if (soap->recverror) {
  1537. soap->bufidx = soap->buflen = 0;
  1538. } else {
  1539. soap->bufidx = soap->buflen = 0;
  1540. err = soap->ffilterrecv(soap, soap->buf, &soap->buflen, sizeof(soap->buf));
  1541. if (err) {
  1542. if (err == SOAP_EOF)
  1543. return SOAP_EOF;
  1544. return soap->error = err;
  1545. }
  1546. if (soap->buflen) {
  1547. DBGLOG(TEST,
  1548. SOAP_MESSAGE(fdebug, "Filtered output continued %lu bytes\n", (unsigned long) soap->buflen));
  1549. return SOAP_OK;
  1550. }
  1551. soap->recverror = soap_recv_raw(soap);
  1552. soap->buflen -= soap->bufidx; /* chunked may set bufidx > 0 to skip hex chunk length */
  1553. }
  1554. while (soap->ffilterrecv) {
  1555. err = soap->ffilterrecv(soap, soap->buf + soap->bufidx, &soap->buflen, sizeof(soap->buf) - soap->bufidx);
  1556. if (err) {
  1557. if (err == SOAP_EOF)
  1558. return SOAP_EOF;
  1559. return soap->error = err;
  1560. }
  1561. if (soap->buflen) {
  1562. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Filtered output %lu bytes\n", (unsigned long) soap->buflen));
  1563. soap->buflen += soap->bufidx;
  1564. return SOAP_OK;
  1565. }
  1566. if (soap->recverror) {
  1567. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Returning postponed error %d\n", soap->recverror));
  1568. return soap->recverror;
  1569. }
  1570. soap->recverror = soap_recv_raw(soap);
  1571. soap->buflen -= soap->bufidx; /* chunked may set bufidx > 0 to skip hex chunk length */
  1572. }
  1573. }
  1574. return soap->recverror = soap_recv_raw(soap);
  1575. #else
  1576. return soap_recv_raw(soap);
  1577. #endif
  1578. }
  1579. /******************************************************************************/
  1580. SOAP_FMAC1
  1581. soap_wchar
  1582. SOAP_FMAC2
  1583. soap_getchar(struct soap *soap) {
  1584. soap_wchar c;
  1585. c = soap->ahead;
  1586. if (c) {
  1587. if ((int) c != EOF)
  1588. soap->ahead = 0;
  1589. return c;
  1590. }
  1591. return soap_get1(soap);
  1592. }
  1593. /******************************************************************************/
  1594. SOAP_FMAC1
  1595. const struct soap_code_map *
  1596. SOAP_FMAC2
  1597. soap_code(const struct soap_code_map *code_map, const char *str) {
  1598. if (code_map && str) {
  1599. while (code_map->string) {
  1600. if (!strcmp(str, code_map->string)) /* case sensitive */
  1601. return code_map;
  1602. code_map++;
  1603. }
  1604. }
  1605. return NULL;
  1606. }
  1607. /******************************************************************************/
  1608. SOAP_FMAC1
  1609. LONG64
  1610. SOAP_FMAC2
  1611. soap_code_int(const struct soap_code_map *code_map, const char *str, LONG64 other) {
  1612. if (code_map) {
  1613. while (code_map->string) {
  1614. if (!soap_tag_cmp(str, code_map->string)) /* case insensitive */
  1615. return code_map->code;
  1616. code_map++;
  1617. }
  1618. }
  1619. return other;
  1620. }
  1621. /******************************************************************************/
  1622. SOAP_FMAC1
  1623. const char *
  1624. SOAP_FMAC2
  1625. soap_code_str(const struct soap_code_map *code_map, long code) {
  1626. if (!code_map)
  1627. return NULL;
  1628. while (code_map->code != code && code_map->string)
  1629. code_map++;
  1630. return code_map->string;
  1631. }
  1632. /******************************************************************************/
  1633. SOAP_FMAC1
  1634. LONG64
  1635. SOAP_FMAC2
  1636. soap_code_bits(const struct soap_code_map *code_map, const char *str) {
  1637. LONG64 bits = 0;
  1638. if (code_map) {
  1639. while (str && *str) {
  1640. const struct soap_code_map *p;
  1641. for (p = code_map; p->string; p++) {
  1642. size_t n = strlen(p->string);
  1643. if (!strncmp(p->string, str, n) && soap_coblank((soap_wchar) str[n])) {
  1644. bits |= p->code;
  1645. str += n;
  1646. while (*str > 0 && *str <= 32)
  1647. str++;
  1648. break;
  1649. }
  1650. }
  1651. if (!p->string)
  1652. return 0;
  1653. }
  1654. }
  1655. return bits;
  1656. }
  1657. /******************************************************************************/
  1658. SOAP_FMAC1
  1659. const char *
  1660. SOAP_FMAC2
  1661. soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long code) {
  1662. char *t = soap->tmpbuf;
  1663. if (code_map) {
  1664. while (code_map->string) {
  1665. if ((code_map->code & code)) {
  1666. const char *s = code_map->string;
  1667. if (t != soap->tmpbuf)
  1668. *t++ = ' ';
  1669. while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
  1670. *t++ = *s++;
  1671. if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
  1672. break;
  1673. }
  1674. code_map++;
  1675. }
  1676. }
  1677. *t = '\0';
  1678. return soap->tmpbuf;
  1679. }
  1680. /******************************************************************************/
  1681. SOAP_FMAC1
  1682. int
  1683. SOAP_FMAC2
  1684. soap_binary_search_string(const char **a, int n, const char *s) {
  1685. int min = 0, max = n - 1;
  1686. while (min <= max) {
  1687. int mid = (min + max) / 2;
  1688. int r = strcmp(s, a[mid]);
  1689. if (r < 0)
  1690. max = mid - 1;
  1691. else if (r > 0)
  1692. min = mid + 1;
  1693. else
  1694. return mid;
  1695. }
  1696. return -1;
  1697. }
  1698. /******************************************************************************/
  1699. static soap_wchar
  1700. soap_char(struct soap *soap) {
  1701. char tmp[8];
  1702. int i;
  1703. soap_wchar c;
  1704. char *s = tmp;
  1705. for (i = 0; i < (int) sizeof(tmp) - 1; i++) {
  1706. c = soap_get1(soap);
  1707. if (c == ';' || (int) c == EOF)
  1708. break;
  1709. *s++ = (char) c;
  1710. }
  1711. *s = '\0';
  1712. if (*tmp == '#') {
  1713. if (tmp[1] == 'x' || tmp[1] == 'X')
  1714. return (soap_wchar) soap_strtol(tmp + 2, NULL, 16);
  1715. return (soap_wchar) soap_strtol(tmp + 1, NULL, 10);
  1716. }
  1717. if (!strcmp(tmp, "lt"))
  1718. return '<';
  1719. if (!strcmp(tmp, "gt"))
  1720. return '>';
  1721. if (!strcmp(tmp, "amp"))
  1722. return '&';
  1723. if (!strcmp(tmp, "quot"))
  1724. return '"';
  1725. if (!strcmp(tmp, "apos"))
  1726. return '\'';
  1727. #ifndef WITH_LEAN
  1728. return (soap_wchar) soap_code_int(html_entity_codes, tmp, (LONG64) SOAP_UNKNOWN_CHAR);
  1729. #else
  1730. return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */
  1731. #endif
  1732. }
  1733. /******************************************************************************/
  1734. #ifdef WITH_LEAN
  1735. soap_wchar
  1736. soap_get0(struct soap *soap)
  1737. {
  1738. if (soap->bufidx >= soap->buflen && soap_recv(soap))
  1739. return EOF;
  1740. return (unsigned char)soap->buf[soap->bufidx];
  1741. }
  1742. #endif
  1743. /******************************************************************************/
  1744. #ifdef WITH_LEAN
  1745. soap_wchar
  1746. soap_get1(struct soap *soap)
  1747. {
  1748. if (soap->bufidx >= soap->buflen && soap_recv(soap))
  1749. return EOF;
  1750. return (unsigned char)soap->buf[soap->bufidx++];
  1751. }
  1752. #endif
  1753. /******************************************************************************/
  1754. SOAP_FMAC1
  1755. soap_wchar
  1756. SOAP_FMAC2
  1757. soap_get(struct soap *soap) {
  1758. soap_wchar c;
  1759. c = soap->ahead;
  1760. if (c) {
  1761. if ((int) c != EOF)
  1762. soap->ahead = 0;
  1763. } else {
  1764. c = soap_get1(soap);
  1765. }
  1766. while ((int) c != EOF) {
  1767. if (soap->cdata) {
  1768. if (c == ']') {
  1769. c = soap_get1(soap);
  1770. if (c == ']') {
  1771. c = soap_get0(soap);
  1772. if (c == '>') {
  1773. soap->cdata = 0;
  1774. c = soap_get1(soap);
  1775. c = soap_get1(soap);
  1776. } else {
  1777. soap_unget(soap, ']');
  1778. return ']';
  1779. }
  1780. } else {
  1781. soap_revget1(soap);
  1782. return ']';
  1783. }
  1784. } else {
  1785. return c;
  1786. }
  1787. }
  1788. switch (c) {
  1789. case '<':
  1790. do {
  1791. c = soap_get1(soap);
  1792. } while (soap_coblank(c));
  1793. if (c == '!' || c == '?' || c == '%') {
  1794. int k = 1;
  1795. if (c == '!') {
  1796. c = soap_get1(soap);
  1797. if (c == '[') {
  1798. do {
  1799. c = soap_get1(soap);
  1800. } while ((int) c != EOF && c != '[');
  1801. if ((int) c == EOF)
  1802. break;
  1803. soap->cdata = 1;
  1804. c = soap_get1(soap);
  1805. continue;
  1806. }
  1807. if (c == '-' && (c = soap_get1(soap)) == '-') {
  1808. do {
  1809. c = soap_get1(soap);
  1810. if (c == '-' && (c = soap_get1(soap)) == '-')
  1811. break;
  1812. } while ((int) c != EOF);
  1813. }
  1814. } else if (c == '?') {
  1815. c = soap_getpi(soap);
  1816. }
  1817. while ((int) c != EOF) {
  1818. if (c == '<') {
  1819. k++;
  1820. } else if (c == '>') {
  1821. if (--k <= 0)
  1822. break;
  1823. }
  1824. c = soap_get1(soap);
  1825. }
  1826. if ((int) c == EOF)
  1827. break;
  1828. c = soap_get1(soap);
  1829. continue;
  1830. }
  1831. if (c == '/')
  1832. return SOAP_TT;
  1833. soap_revget1(soap);
  1834. return SOAP_LT;
  1835. case '>':
  1836. return SOAP_GT;
  1837. case '"':
  1838. return SOAP_QT;
  1839. case '\'':
  1840. return SOAP_AP;
  1841. case '&':
  1842. return soap_char(soap) | 0x80000000;
  1843. }
  1844. break;
  1845. }
  1846. return c;
  1847. }
  1848. /******************************************************************************/
  1849. static soap_wchar
  1850. soap_getpi(struct soap *soap) {
  1851. char buf[64];
  1852. char *s = buf;
  1853. size_t i = sizeof(buf);
  1854. soap_wchar c;
  1855. while ((int) (c = soap_getchar(soap)) != EOF && c != '?') {
  1856. if (i > 1) {
  1857. if (soap_coblank(c))
  1858. c = ' ';
  1859. *s++ = (char) c;
  1860. i--;
  1861. }
  1862. }
  1863. *s = '\0';
  1864. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <?%s?>\n", buf));
  1865. if (!strncmp(buf, "xml ", 4)) {
  1866. s = strstr(buf, " encoding=");
  1867. if (s && s[10]) {
  1868. if (!soap_tag_cmp(s + 11, "iso-8859-1*")
  1869. || !soap_tag_cmp(s + 11, "latin1*")) {
  1870. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n"));
  1871. soap->mode |= SOAP_ENC_LATIN;
  1872. } else if (!soap_tag_cmp(s + 11, "utf-8*")) {
  1873. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n"));
  1874. soap->mode &= ~SOAP_ENC_LATIN;
  1875. }
  1876. }
  1877. }
  1878. if ((int) c != EOF)
  1879. c = soap_getchar(soap);
  1880. return c;
  1881. }
  1882. /******************************************************************************/
  1883. #ifndef WITH_LEANER
  1884. SOAP_FMAC1
  1885. int
  1886. SOAP_FMAC2
  1887. soap_move(struct soap *soap, ULONG64 n) {
  1888. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving "
  1889. SOAP_ULONG_FORMAT
  1890. " bytes forward\n", n));
  1891. for (; n; n--)
  1892. if ((int) soap_getchar(soap) == EOF)
  1893. return SOAP_EOF;
  1894. return SOAP_OK;
  1895. }
  1896. #endif
  1897. /******************************************************************************/
  1898. #ifndef WITH_LEANER
  1899. SOAP_FMAC1
  1900. ULONG64
  1901. SOAP_FMAC2
  1902. soap_tell(struct soap *soap) {
  1903. return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0);
  1904. }
  1905. #endif
  1906. /******************************************************************************/
  1907. SOAP_FMAC1
  1908. int
  1909. SOAP_FMAC2
  1910. soap_pututf8(struct soap *soap, unsigned long c) {
  1911. char tmp[24];
  1912. if ((c < 0x7F && c > 0x1F)) {
  1913. *tmp = (char) c;
  1914. return soap_send_raw(soap, tmp, 1);
  1915. }
  1916. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  1917. if (!(c == 0x09 || c == 0x0A || c == 0x0D || (c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF)))
  1918. c = SOAP_UNKNOWN_UNICODE_CHAR;
  1919. #endif
  1920. #ifndef WITH_LEAN
  1921. if (c > 0x9F) {
  1922. char *t = tmp;
  1923. if (c < 0x0800) {
  1924. *t++ = (char) (0xC0 | ((c >> 6) & 0x1F));
  1925. } else {
  1926. if (c < 0x010000) {
  1927. *t++ = (char) (0xE0 | ((c >> 12) & 0x0F));
  1928. } else {
  1929. if (c < 0x200000) {
  1930. *t++ = (char) (0xF0 | ((c >> 18) & 0x07));
  1931. } else {
  1932. if (c < 0x04000000) {
  1933. *t++ = (char) (0xF8 | ((c >> 24) & 0x03));
  1934. } else {
  1935. *t++ = (char) (0xFC | ((c >> 30) & 0x01));
  1936. *t++ = (char) (0x80 | ((c >> 24) & 0x3F));
  1937. }
  1938. *t++ = (char) (0x80 | ((c >> 18) & 0x3F));
  1939. }
  1940. *t++ = (char) (0x80 | ((c >> 12) & 0x3F));
  1941. }
  1942. *t++ = (char) (0x80 | ((c >> 6) & 0x3F));
  1943. }
  1944. *t++ = (char) (0x80 | (c & 0x3F));
  1945. *t = '\0';
  1946. } else
  1947. #endif
  1948. (SOAP_SNPRINTF(tmp, sizeof(tmp), 20), "&#x%lX;", c);
  1949. return soap_send(soap, tmp);
  1950. }
  1951. /******************************************************************************/
  1952. SOAP_FMAC1
  1953. soap_wchar
  1954. SOAP_FMAC2
  1955. soap_getutf8(struct soap *soap) {
  1956. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  1957. soap_wchar c, c1, c2, c3;
  1958. #else
  1959. soap_wchar c, c1, c2, c3, c4;
  1960. #endif
  1961. c = soap->ahead;
  1962. if (c >= 0x80)
  1963. soap->ahead = 0;
  1964. else
  1965. c = (soap_wchar) soap_get(soap);
  1966. if (c < 0x80 || c > 0xFF || (soap->mode & SOAP_ENC_LATIN))
  1967. return c;
  1968. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  1969. c1 = (soap_wchar)soap_get1(soap);
  1970. if (c <= 0xC1 || (c1 & 0xC0) != 0x80)
  1971. {
  1972. soap_revget1(soap);
  1973. return SOAP_UNKNOWN_UNICODE_CHAR;
  1974. }
  1975. c1 &= 0x3F;
  1976. if (c < 0xE0)
  1977. return (((c & 0x1F) << 6) | c1);
  1978. c2 = (soap_wchar)soap_get1(soap);
  1979. if ((c == 0xE0 && c1 < 0x20) || (c2 & 0xC0) != 0x80)
  1980. {
  1981. soap_revget1(soap);
  1982. return SOAP_UNKNOWN_UNICODE_CHAR;
  1983. }
  1984. c2 &= 0x3F;
  1985. if (c < 0xF0)
  1986. return (((c & 0x0F) << 12) | (c1 << 6) | c2);
  1987. c3 = (soap_wchar)soap_get1(soap);
  1988. if ((c == 0xF0 && c1 < 0x10) || (c == 0xF4 && c1 >= 0x10) || c >= 0xF5 || (c3 & 0xC0) != 0x80)
  1989. {
  1990. soap_revget1(soap);
  1991. return SOAP_UNKNOWN_UNICODE_CHAR;
  1992. }
  1993. return (((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | (c3 & 0x3F));
  1994. #else
  1995. c1 = (soap_wchar) soap_get1(soap);
  1996. if (c < 0xC0 || (c1 & 0xC0) != 0x80) {
  1997. soap_revget1(soap);
  1998. /* doesn't look like this is UTF-8, try continue as if ISO-8859-1 */
  1999. return c;
  2000. }
  2001. c1 &= 0x3F;
  2002. if (c < 0xE0)
  2003. return ((soap_wchar) (c & 0x1F) << 6) | c1;
  2004. c2 = (soap_wchar) soap_get1(soap) & 0x3F;
  2005. if (c < 0xF0)
  2006. return ((soap_wchar) (c & 0x0F) << 12) | (c1 << 6) | c2;
  2007. c3 = (soap_wchar) soap_get1(soap) & 0x3F;
  2008. if (c < 0xF8)
  2009. return ((soap_wchar) (c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
  2010. c4 = (soap_wchar) soap_get1(soap) & 0x3F;
  2011. if (c < 0xFC)
  2012. return ((soap_wchar) (c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
  2013. return ((soap_wchar) (c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) |
  2014. (soap_wchar) (soap_get1(soap) & 0x3F);
  2015. #endif
  2016. }
  2017. /******************************************************************************/
  2018. SOAP_FMAC1
  2019. size_t
  2020. SOAP_FMAC2
  2021. soap_utf8len(const char *s) {
  2022. size_t l = 0;
  2023. while (*s)
  2024. if ((*s++ & 0xC0) != 0x80)
  2025. l++;
  2026. return l;
  2027. }
  2028. /******************************************************************************/
  2029. SOAP_FMAC1
  2030. int
  2031. SOAP_FMAC2
  2032. soap_puthex(struct soap *soap, const unsigned char *s, int n) {
  2033. char d[2 * SOAP_BINARY_BUFLEN], *p = d;
  2034. #ifdef WITH_DOM
  2035. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  2036. {
  2037. soap->dom->text = soap_s2hex(soap, s, NULL, n);
  2038. if (!soap->dom->text)
  2039. return soap->error;
  2040. return SOAP_OK;
  2041. }
  2042. #endif
  2043. for (; n > 0; n--) {
  2044. int m = *s++;
  2045. p[0] = (char) ((m >> 4) + (m > 159 ? '7' : '0'));
  2046. m &= 0x0F;
  2047. p[1] = (char) (m + (m > 9 ? '7' : '0'));
  2048. p += 2;
  2049. if (p - d == sizeof(d)) {
  2050. if (soap_send_raw(soap, d, sizeof(d)))
  2051. return soap->error;
  2052. p = d;
  2053. }
  2054. }
  2055. if (p != d && soap_send_raw(soap, d, p - d))
  2056. return soap->error;
  2057. return SOAP_OK;
  2058. }
  2059. /******************************************************************************/
  2060. SOAP_FMAC1
  2061. unsigned char *
  2062. SOAP_FMAC2
  2063. soap_gethex(struct soap *soap, int *n) {
  2064. size_t l = 0;
  2065. #ifdef WITH_DOM
  2066. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  2067. {
  2068. soap->dom->text = soap_string_in(soap, 0, -1, -1, NULL);
  2069. return (unsigned char*)soap_hex2s(soap, soap->dom->text, NULL, 0, n);
  2070. }
  2071. #endif
  2072. #ifdef WITH_FAST
  2073. soap->labidx = 0;
  2074. for (;;) {
  2075. char *s;
  2076. size_t i, k;
  2077. if (soap_append_lab(soap, NULL, 0))
  2078. return NULL;
  2079. s = soap->labbuf + soap->labidx;
  2080. k = soap->lablen - soap->labidx;
  2081. soap->labidx = soap->lablen;
  2082. for (i = 0; i < k; i++) {
  2083. char d1, d2;
  2084. soap_wchar c;
  2085. c = soap_get(soap);
  2086. if (soap_isxdigit(c)) {
  2087. d1 = (char) c;
  2088. c = soap_get(soap);
  2089. if (soap_isxdigit(c)) {
  2090. d2 = (char) c;
  2091. } else {
  2092. soap->error = SOAP_TYPE;
  2093. return NULL;
  2094. }
  2095. } else {
  2096. unsigned char *p = NULL;
  2097. l = soap->lablen + i - k;
  2098. soap_unget(soap, c);
  2099. if (n)
  2100. *n = (int) l;
  2101. if (soap->maxlength > 0 && l > (size_t) soap->maxlength) {
  2102. soap->error = SOAP_LENGTH;
  2103. } else {
  2104. p = (unsigned char *) soap_malloc(soap, l);
  2105. if (p)
  2106. (void) soap_memcpy((void *) p, l, (const void *) soap->labbuf, l);
  2107. }
  2108. return p;
  2109. }
  2110. *s++ = (char) (((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'));
  2111. }
  2112. l = soap->lablen;
  2113. if (soap->maxlength > 0 && l > (size_t) soap->maxlength) {
  2114. soap->error = SOAP_LENGTH;
  2115. return NULL;
  2116. }
  2117. }
  2118. #else
  2119. if (soap_alloc_block(soap) == NULL)
  2120. return NULL;
  2121. for (;;)
  2122. {
  2123. int i;
  2124. char *s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN);
  2125. if (!s)
  2126. {
  2127. soap_end_block(soap, NULL);
  2128. return NULL;
  2129. }
  2130. for (i = 0; i < SOAP_BLKLEN; i++)
  2131. {
  2132. char d1, d2;
  2133. soap_wchar c = soap_get(soap);
  2134. if (soap_isxdigit(c))
  2135. {
  2136. d1 = (char)c;
  2137. c = soap_get(soap);
  2138. if (soap_isxdigit(c))
  2139. d2 = (char)c;
  2140. else
  2141. {
  2142. soap_end_block(soap, NULL);
  2143. soap->error = SOAP_TYPE;
  2144. return NULL;
  2145. }
  2146. }
  2147. else
  2148. {
  2149. unsigned char *p;
  2150. soap_unget(soap, c);
  2151. if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
  2152. {
  2153. soap->error = SOAP_LENGTH;
  2154. soap_end_block(soap, NULL);
  2155. return NULL;
  2156. }
  2157. if (n)
  2158. *n = (int)soap_size_block(soap, NULL, i);
  2159. p = (unsigned char*)soap_save_block(soap, NULL, NULL, 0);
  2160. return p;
  2161. }
  2162. *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
  2163. l++;
  2164. }
  2165. if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
  2166. {
  2167. soap->error = SOAP_LENGTH;
  2168. soap_end_block(soap, NULL);
  2169. return NULL;
  2170. }
  2171. }
  2172. #endif
  2173. }
  2174. /******************************************************************************/
  2175. SOAP_FMAC1
  2176. int
  2177. SOAP_FMAC2
  2178. soap_putbase64(struct soap *soap, const unsigned char *s, int n) {
  2179. char d[4 * SOAP_BINARY_BUFLEN], *p = d;
  2180. if (!s)
  2181. return SOAP_OK;
  2182. #ifdef WITH_DOM
  2183. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  2184. {
  2185. soap->dom->text = soap_s2base64(soap, s, NULL, n);
  2186. if (!soap->dom->text)
  2187. return soap->error;
  2188. return SOAP_OK;
  2189. }
  2190. #endif
  2191. for (; n > 2; n -= 3, s += 3) {
  2192. p[0] = soap_base64o[(s[0] & 0xFC) >> 2];
  2193. p[1] = soap_base64o[((s[0] & 0x03) << 4) | ((s[1] & 0xF0) >> 4)];
  2194. p[2] = soap_base64o[((s[1] & 0x0F) << 2) | ((s[2] & 0xC0) >> 6)];
  2195. p[3] = soap_base64o[s[2] & 0x3F];
  2196. p += 4;
  2197. if (p - d == sizeof(d)) {
  2198. if (soap_send_raw(soap, d, sizeof(d)))
  2199. return soap->error;
  2200. p = d;
  2201. }
  2202. }
  2203. if (n == 2) {
  2204. p[0] = soap_base64o[(s[0] & 0xFC) >> 2];
  2205. p[1] = soap_base64o[((s[0] & 0x03) << 4) | ((s[1] & 0xF0) >> 4)];
  2206. p[2] = soap_base64o[(s[1] & 0x0F) << 2];
  2207. p[3] = '=';
  2208. p += 4;
  2209. } else if (n == 1) {
  2210. p[0] = soap_base64o[(s[0] & 0xFC) >> 2];
  2211. p[1] = soap_base64o[(s[0] & 0x03) << 4];
  2212. p[2] = '=';
  2213. p[3] = '=';
  2214. p += 4;
  2215. }
  2216. if (p != d && soap_send_raw(soap, d, p - d))
  2217. return soap->error;
  2218. return SOAP_OK;
  2219. }
  2220. /******************************************************************************/
  2221. SOAP_FMAC1
  2222. unsigned char *
  2223. SOAP_FMAC2
  2224. soap_getbase64(struct soap *soap, int *n, int malloc_flag) {
  2225. size_t l = 0;
  2226. (void) malloc_flag;
  2227. #ifdef WITH_DOM
  2228. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  2229. {
  2230. soap->dom->text = soap_string_in(soap, 0, -1, -1, NULL);
  2231. return (unsigned char*)soap_base642s(soap, soap->dom->text, NULL, 0, n);
  2232. }
  2233. #endif
  2234. #ifdef WITH_FAST
  2235. soap->labidx = 0;
  2236. for (;;) {
  2237. size_t i, k;
  2238. char *s;
  2239. if (soap_append_lab(soap, NULL, 2))
  2240. return NULL;
  2241. s = soap->labbuf + soap->labidx;
  2242. k = soap->lablen - soap->labidx;
  2243. soap->labidx = 3 * (soap->lablen / 3);
  2244. if (k > 2) {
  2245. for (i = 0; i < k - 2; i += 3) {
  2246. unsigned long m = 0;
  2247. int j = 0;
  2248. do {
  2249. soap_wchar c = soap_get(soap);
  2250. if (c < SOAP_AP)
  2251. c &= 0x7FFFFFFF;
  2252. if (c == '=' || c < 0) {
  2253. unsigned char *p = NULL;
  2254. switch (j) {
  2255. case 2:
  2256. *s++ = (char) ((m >> 4) & 0xFF);
  2257. i++;
  2258. break;
  2259. case 3:
  2260. *s++ = (char) ((m >> 10) & 0xFF);
  2261. *s++ = (char) ((m >> 2) & 0xFF);
  2262. i += 2;
  2263. }
  2264. l = soap->lablen + i - k;
  2265. if (n)
  2266. *n = (int) l;
  2267. if (soap->maxlength > 0 && l > (size_t) soap->maxlength)
  2268. soap->error = SOAP_LENGTH;
  2269. else {
  2270. p = (unsigned char *) soap_malloc(soap, l);
  2271. if (p)
  2272. (void) soap_memcpy((void *) p, l, (const void *) soap->labbuf, l);
  2273. }
  2274. if (c >= 0) {
  2275. while ((int) ((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
  2276. continue;
  2277. }
  2278. soap_unget(soap, c);
  2279. return p;
  2280. }
  2281. c -= '+';
  2282. if (c >= 0 && c <= 79) {
  2283. int b = soap_base64i[c];
  2284. if (b >= 64) {
  2285. soap->error = SOAP_TYPE;
  2286. return NULL;
  2287. }
  2288. m = (m << 6) + b;
  2289. j++;
  2290. } else if (!soap_coblank(c + '+')) {
  2291. soap->error = SOAP_TYPE;
  2292. return NULL;
  2293. }
  2294. } while (j < 4);
  2295. *s++ = (char) ((m >> 16) & 0xFF);
  2296. *s++ = (char) ((m >> 8) & 0xFF);
  2297. *s++ = (char) (m & 0xFF);
  2298. }
  2299. l = soap->lablen;
  2300. if (soap->maxlength > 0 && l > (size_t) soap->maxlength) {
  2301. soap->error = SOAP_LENGTH;
  2302. return NULL;
  2303. }
  2304. }
  2305. }
  2306. #else
  2307. if (soap_alloc_block(soap) == NULL)
  2308. return NULL;
  2309. for (;;)
  2310. {
  2311. int i;
  2312. char *s = (char*)soap_push_block(soap, NULL, 3 * SOAP_BLKLEN); /* must be multiple of 3 */
  2313. if (!s)
  2314. {
  2315. soap_end_block(soap, NULL);
  2316. return NULL;
  2317. }
  2318. for (i = 0; i < SOAP_BLKLEN; i++)
  2319. {
  2320. unsigned long m = 0;
  2321. int j = 0;
  2322. do
  2323. {
  2324. soap_wchar c = soap_get(soap);
  2325. if (c < SOAP_AP)
  2326. c &= 0x7FFFFFFF;
  2327. if (c == '=' || c < 0)
  2328. {
  2329. unsigned char *p;
  2330. i *= 3;
  2331. switch (j)
  2332. {
  2333. case 2:
  2334. *s++ = (char)((m >> 4) & 0xFF);
  2335. i++;
  2336. l++;
  2337. break;
  2338. case 3:
  2339. *s++ = (char)((m >> 10) & 0xFF);
  2340. *s++ = (char)((m >> 2) & 0xFF);
  2341. l += 2;
  2342. i += 2;
  2343. }
  2344. if (n)
  2345. *n = (int)soap_size_block(soap, NULL, i);
  2346. if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
  2347. {
  2348. soap->error = SOAP_LENGTH;
  2349. soap_end_block(soap, NULL);
  2350. return NULL;
  2351. }
  2352. p = (unsigned char*)soap_save_block(soap, NULL, NULL, 0);
  2353. if (c >= 0)
  2354. {
  2355. while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
  2356. continue;
  2357. }
  2358. soap_unget(soap, c);
  2359. return p;
  2360. }
  2361. c -= '+';
  2362. if (c >= 0 && c <= 79)
  2363. {
  2364. int b = soap_base64i[c];
  2365. if (b >= 64)
  2366. {
  2367. soap->error = SOAP_TYPE;
  2368. return NULL;
  2369. }
  2370. m = (m << 6) + b;
  2371. j++;
  2372. }
  2373. else if (!soap_coblank(c + '+'))
  2374. {
  2375. soap->error = SOAP_TYPE;
  2376. return NULL;
  2377. }
  2378. } while (j < 4);
  2379. *s++ = (char)((m >> 16) & 0xFF);
  2380. *s++ = (char)((m >> 8) & 0xFF);
  2381. *s++ = (char)(m & 0xFF);
  2382. l += 3;
  2383. }
  2384. if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
  2385. {
  2386. soap->error = SOAP_LENGTH;
  2387. soap_end_block(soap, NULL);
  2388. return NULL;
  2389. }
  2390. }
  2391. #endif
  2392. }
  2393. /******************************************************************************/
  2394. #ifndef WITH_LEANER
  2395. SOAP_FMAC1
  2396. int
  2397. SOAP_FMAC2
  2398. soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) {
  2399. /* Check MTOM xop:Include element (within hex/base64Binary) */
  2400. /* TODO: this code to be obsoleted with new import/xop.h conventions */
  2401. short body = soap->body; /* should save type too? */
  2402. if (!soap_peek_element(soap)) {
  2403. if (!soap_element_begin_in(soap, ":Include", 0, NULL)) {
  2404. if (soap_attachment_forward(soap, ptr, size, id, type, options)
  2405. || (soap->body && soap_element_end_in(soap, ":Include")))
  2406. return soap->error;
  2407. } else if (soap->error == SOAP_TAG_MISMATCH)
  2408. soap_retry(soap);
  2409. else
  2410. return soap->error;
  2411. }
  2412. soap->body = body;
  2413. return SOAP_OK;
  2414. }
  2415. #endif
  2416. /******************************************************************************/
  2417. #ifndef WITH_LEANER
  2418. SOAP_FMAC1
  2419. int
  2420. SOAP_FMAC2
  2421. soap_attachment_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) {
  2422. struct soap_xlist *xp;
  2423. *ptr = NULL;
  2424. *size = 0;
  2425. *id = NULL;
  2426. *type = NULL;
  2427. *options = NULL;
  2428. if (!*soap->href)
  2429. return SOAP_OK;
  2430. *id = soap_strdup(soap, soap->href);
  2431. xp = (struct soap_xlist *) SOAP_MALLOC(soap, sizeof(struct soap_xlist));
  2432. if (!xp)
  2433. return soap->error = SOAP_EOM;
  2434. xp->next = soap->xlist;
  2435. xp->ptr = ptr;
  2436. xp->size = size;
  2437. xp->id = *id;
  2438. xp->type = type;
  2439. xp->options = options;
  2440. soap->xlist = xp;
  2441. return SOAP_OK;
  2442. }
  2443. #endif
  2444. /******************************************************************************/
  2445. SOAP_FMAC1
  2446. void *
  2447. SOAP_FMAC2
  2448. soap_memdup(struct soap *soap, const void *s, size_t n) {
  2449. void *t = NULL;
  2450. if (s) {
  2451. t = soap_malloc(soap, n);
  2452. if (t)
  2453. (void) soap_memcpy(t, n, s, n);
  2454. }
  2455. return t;
  2456. }
  2457. /******************************************************************************/
  2458. SOAP_FMAC1
  2459. char *
  2460. SOAP_FMAC2
  2461. soap_strdup(struct soap *soap, const char *s) {
  2462. char *t = NULL;
  2463. if (s) {
  2464. size_t n = strlen(s) + 1;
  2465. if (n > 0) {
  2466. t = (char *) soap_malloc(soap, n);
  2467. if (t) {
  2468. (void) soap_memcpy((void *) t, n, (const void *) s, n);
  2469. t[n - 1] = '\0';
  2470. }
  2471. }
  2472. }
  2473. return t;
  2474. }
  2475. /******************************************************************************/
  2476. SOAP_FMAC1
  2477. wchar_t *
  2478. SOAP_FMAC2
  2479. soap_wstrdup(struct soap *soap, const wchar_t *s) {
  2480. wchar_t *t = NULL;
  2481. if (s) {
  2482. size_t n = 0, m;
  2483. while (s[n])
  2484. n++;
  2485. n++;
  2486. m = sizeof(wchar_t) * n;
  2487. if (n > 0) {
  2488. t = (wchar_t *) soap_malloc(soap, m);
  2489. if (t) {
  2490. (void) soap_memcpy((void *) t, m, (const void *) s, m);
  2491. t[n - 1] = L'\0';
  2492. }
  2493. }
  2494. }
  2495. return t;
  2496. }
  2497. /******************************************************************************/
  2498. SOAP_FMAC1
  2499. char *
  2500. SOAP_FMAC2
  2501. soap_strtrim(struct soap *soap, char *s) {
  2502. (void) soap;
  2503. if (s) {
  2504. char *t;
  2505. while ((*s >= 9 && *s <= 13) || *s == 32)
  2506. s++;
  2507. t = s;
  2508. while (*t)
  2509. t++;
  2510. while (--t > s && ((*t >= 9 && *t <= 13) || *t == 32))
  2511. continue;
  2512. t[1] = '\0';
  2513. }
  2514. return s;
  2515. }
  2516. /******************************************************************************/
  2517. SOAP_FMAC1
  2518. wchar_t *
  2519. SOAP_FMAC2
  2520. soap_wstrtrim(struct soap *soap, wchar_t *s) {
  2521. (void) soap;
  2522. if (s) {
  2523. wchar_t *t;
  2524. while ((*s >= 9 && *s <= 13) || *s == 32)
  2525. s++;
  2526. t = s;
  2527. while (*t)
  2528. t++;
  2529. while (--t > s && ((*t >= 9 && *t <= 13) || *t == 32))
  2530. continue;
  2531. t[1] = L'\0';
  2532. }
  2533. return s;
  2534. }
  2535. /******************************************************************************/
  2536. SOAP_FMAC1
  2537. struct soap_blist *
  2538. SOAP_FMAC2
  2539. soap_alloc_block(struct soap *soap) {
  2540. struct soap_blist *p;
  2541. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", (void *) soap->blist));
  2542. p = (struct soap_blist *) SOAP_MALLOC(soap, sizeof(struct soap_blist));
  2543. if (!p) {
  2544. soap->error = SOAP_EOM;
  2545. return NULL;
  2546. }
  2547. p->next = soap->blist;
  2548. p->head = NULL;
  2549. p->size = 0;
  2550. p->item = 0;
  2551. soap->blist = p;
  2552. return p;
  2553. }
  2554. /******************************************************************************/
  2555. SOAP_FMAC1
  2556. void *
  2557. SOAP_FMAC2
  2558. soap_push_block(struct soap *soap, struct soap_blist *b, size_t n) {
  2559. struct soap_bhead *p;
  2560. if (!b)
  2561. b = soap->blist;
  2562. if (!b
  2563. || b->size + n < b->size
  2564. || sizeof(struct soap_bhead) + n < n
  2565. || (SOAP_MAXALLOCSIZE > 0 && sizeof(struct soap_bhead) + n > SOAP_MAXALLOCSIZE)) {
  2566. soap->error = SOAP_EOM;
  2567. return NULL;
  2568. }
  2569. p = (struct soap_bhead *) SOAP_MALLOC(soap, sizeof(struct soap_bhead) + n);
  2570. if (!p) {
  2571. soap->error = SOAP_EOM;
  2572. return NULL;
  2573. }
  2574. p->next = b->head;
  2575. b->head = p;
  2576. p->size = n;
  2577. b->size += n;
  2578. DBGLOG(TEST,
  2579. SOAP_MESSAGE(fdebug, "Push block %p of %u bytes on %lu previous blocks (%lu bytes total)\n", (void *) p,
  2580. (unsigned int) n, (unsigned long) b->item, (unsigned long) b->size));
  2581. b->item++;
  2582. return (void *) (p + 1); /* skip block header and point to n allocated bytes */
  2583. }
  2584. /******************************************************************************/
  2585. SOAP_FMAC1
  2586. void *
  2587. SOAP_FMAC2
  2588. soap_push_block_max(struct soap *soap, struct soap_blist *b, size_t n) {
  2589. if (b && b->item >= soap->maxoccurs) /* restrict block array length */
  2590. {
  2591. soap->error = SOAP_OCCURS;
  2592. return NULL;
  2593. }
  2594. return soap_push_block(soap, b, n);
  2595. }
  2596. /******************************************************************************/
  2597. SOAP_FMAC1
  2598. void
  2599. SOAP_FMAC2
  2600. soap_pop_block(struct soap *soap, struct soap_blist *b) {
  2601. struct soap_bhead *p;
  2602. if (!b)
  2603. b = soap->blist;
  2604. if (!b || !b->head)
  2605. return;
  2606. p = b->head;
  2607. b->size -= p->size;
  2608. b->head = p->next;
  2609. b->item--;
  2610. DBGLOG(TEST,
  2611. SOAP_MESSAGE(fdebug, "Pop block %p (%lu items of %lu bytes total)\n", (void *) p, (unsigned long) b->item,
  2612. (unsigned long) b->size));
  2613. SOAP_FREE(soap, p);
  2614. }
  2615. /******************************************************************************/
  2616. SOAP_FMAC1
  2617. void
  2618. SOAP_FMAC2
  2619. soap_update_pointers(struct soap *soap, const char *dst, const char *src, size_t len) {
  2620. const void *start = src, *end = src + len;
  2621. #ifndef WITH_LEANER
  2622. struct soap_xlist *xp;
  2623. #endif
  2624. #ifndef WITH_NOIDREF
  2625. if ((soap->version && !(soap->imode & SOAP_XML_TREE)) || (soap->mode & SOAP_XML_GRAPH)) {
  2626. int i;
  2627. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update pointers %p (%lu bytes) -> %p\n", (void *) src, (unsigned long) len,
  2628. (void *) dst));
  2629. for (i = 0; i < SOAP_IDHASH; i++) {
  2630. struct soap_ilist *ip;
  2631. for (ip = soap->iht[i]; ip; ip = ip->next) {
  2632. struct soap_flist *fp;
  2633. void *p, **q;
  2634. if (ip->shaky) {
  2635. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update shaky id='%s'\n", ip->id));
  2636. if (ip->ptr && ip->ptr >= start && ip->ptr < end) {
  2637. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update ptr %p -> %p\n", ip->ptr,
  2638. (void *) ((const char *) ip->ptr + (dst - src))));
  2639. ip->ptr = (void *) ((const char *) ip->ptr + (dst - src));
  2640. }
  2641. for (q = &ip->link; q; q = (void **) p) {
  2642. p = *q;
  2643. if (p && p >= start && p < end) {
  2644. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p -> %p\n", ip->id, p,
  2645. (void *) ((const char *) p + (dst - src))));
  2646. *q = (void *) ((const char *) p + (dst - src));
  2647. }
  2648. }
  2649. for (q = &ip->copy; q; q = (void **) p) {
  2650. p = *q;
  2651. if (p && p >= start && p < end) {
  2652. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p -> %p\n", ip->id, p,
  2653. (void *) ((const char *) p + (dst - src))));
  2654. *q = (void *) ((const char *) p + (dst - src));
  2655. }
  2656. }
  2657. for (fp = ip->flist; fp; fp = fp->next) {
  2658. if (fp->ptr >= start && fp->ptr < end) {
  2659. DBGLOG(TEST,
  2660. SOAP_MESSAGE(fdebug, "Copy list update id='%s' target type=%d %p -> %p\n", ip->id,
  2661. fp->type, fp->ptr, (void *) ((char *) fp->ptr + (dst - src))));
  2662. fp->ptr = (void *) ((const char *) fp->ptr + (dst - src));
  2663. }
  2664. }
  2665. if (ip->smart && ip->smart >= start && ip->smart < end) {
  2666. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Smart shared pointer update %p -> %p\n", ip->smart,
  2667. (void *) ((const char *) ip->smart + (dst - src))));
  2668. ip->smart = (void *) ((const char *) ip->smart + (dst - src));
  2669. }
  2670. }
  2671. }
  2672. }
  2673. }
  2674. #else
  2675. (void)soap; (void)start; (void)end; (void)dst; (void)src;
  2676. #endif
  2677. #ifndef WITH_LEANER
  2678. for (xp = soap->xlist; xp; xp = xp->next) {
  2679. if (xp->ptr && (void *) xp->ptr >= start && (void *) xp->ptr < end) {
  2680. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update attachment id='%s' %p -> %p\n", xp->id ? xp->id : SOAP_STR_EOS,
  2681. (void *) xp->ptr, (void *) ((char *) xp->ptr + (dst - src))));
  2682. xp->ptr = (unsigned char **) ((char *) xp->ptr + (dst - src));
  2683. xp->size = (int *) ((char *) xp->size + (dst - src));
  2684. xp->type = (char **) ((char *) xp->type + (dst - src));
  2685. xp->options = (char **) ((char *) xp->options + (dst - src));
  2686. }
  2687. }
  2688. #endif
  2689. }
  2690. /******************************************************************************/
  2691. #ifndef WITH_NOIDREF
  2692. static int
  2693. soap_has_copies(struct soap *soap, const char *start, const char *end) {
  2694. int i;
  2695. struct soap_ilist *ip = NULL;
  2696. struct soap_flist *fp = NULL;
  2697. const char *p;
  2698. for (i = 0; i < SOAP_IDHASH; i++) {
  2699. for (ip = soap->iht[i]; ip; ip = ip->next) {
  2700. for (p = (const char *) ip->copy; p; p = *(const char **) p)
  2701. if (p >= start && p < end)
  2702. return SOAP_ERR;
  2703. for (fp = ip->flist; fp; fp = fp->next)
  2704. if (fp->type == ip->type && (const char *) fp->ptr >= start && (const char *) fp->ptr < end)
  2705. return SOAP_ERR;
  2706. }
  2707. }
  2708. return SOAP_OK;
  2709. }
  2710. #endif
  2711. /******************************************************************************/
  2712. #ifndef WITH_NOIDREF
  2713. SOAP_FMAC1
  2714. int
  2715. SOAP_FMAC2
  2716. soap_resolve(struct soap *soap) {
  2717. int i;
  2718. short flag;
  2719. const char *id;
  2720. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded refs\n"));
  2721. for (i = 0; i < SOAP_IDHASH; i++) {
  2722. struct soap_ilist *ip;
  2723. for (ip = soap->iht[i]; ip; ip = ip->next) {
  2724. if (ip->ptr) {
  2725. void **q;
  2726. struct soap_flist *fp, **fpp = &ip->flist;
  2727. if (ip->spine)
  2728. ip->spine[0] = ip->ptr;
  2729. q = (void **) ip->link;
  2730. ip->link = NULL;
  2731. DBGLOG(TEST, if (q)
  2732. SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s' type=%d\n", ip->id, ip->type));
  2733. while (q) {
  2734. void *p = *q;
  2735. *q = ip->ptr;
  2736. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... link %p -> %p\n", (void *) q, ip->ptr));
  2737. q = (void **) p;
  2738. }
  2739. while ((fp = *fpp)) {
  2740. if (fp->level > 0 && fp->finsert) {
  2741. DBGLOG(TEST,
  2742. SOAP_MESSAGE(fdebug, "... insert type=%d link %p -> %p\n", fp->type, fp->ptr, ip->ptr));
  2743. if (ip->spine && fp->level <= SOAP_MAXPTRS)
  2744. fp->finsert(soap, ip->type, fp->type, fp->ptr, fp->index, &ip->spine[fp->level - 1],
  2745. &ip->smart);
  2746. else if (fp->level == 1)
  2747. fp->finsert(soap, ip->type, fp->type, fp->ptr, fp->index, &ip->ptr, &ip->smart);
  2748. else if (fp->level <= SOAP_MAXPTRS) {
  2749. int i;
  2750. ip->spine = (void **) soap_malloc(soap, SOAP_MAXPTRS * sizeof(void *));
  2751. if (!ip->spine)
  2752. return soap->error = SOAP_EOM;
  2753. ip->spine[0] = ip->ptr;
  2754. for (i = 1; i < SOAP_MAXPTRS; i++)
  2755. ip->spine[i] = &ip->spine[i - 1];
  2756. fp->finsert(soap, ip->type, fp->type, fp->ptr, fp->index, &ip->spine[fp->level - 1],
  2757. &ip->smart);
  2758. }
  2759. *fpp = fp->next;
  2760. SOAP_FREE(soap, fp);
  2761. } else
  2762. fpp = &fp->next;
  2763. }
  2764. } else if (*ip->id == '#') {
  2765. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing id='%s'\n", ip->id));
  2766. soap_strcpy(soap->id, sizeof(soap->id), ip->id + 1);
  2767. return soap->error = SOAP_MISSING_ID;
  2768. }
  2769. }
  2770. }
  2771. do {
  2772. flag = 0;
  2773. id = NULL;
  2774. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n"));
  2775. for (i = 0; i < SOAP_IDHASH; i++) {
  2776. struct soap_ilist *ip;
  2777. for (ip = soap->iht[i]; ip; ip = ip->next) {
  2778. if (ip->copy || ip->flist) {
  2779. if (ip->ptr && !soap_has_copies(soap, (const char *) ip->ptr, (const char *) ip->ptr + ip->size)) {
  2780. struct soap_flist *fp;
  2781. DBGLOG(TEST,
  2782. SOAP_MESSAGE(fdebug, "Resolving id='%s' type=%d ptr=%p size=%lu ...\n", ip->id, ip->type,
  2783. ip->ptr, (unsigned long) ip->size));
  2784. if (ip->copy) {
  2785. void *p, **q = (void **) ip->copy;
  2786. DBGLOG(TEST,
  2787. if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id));
  2788. ip->copy = NULL;
  2789. do {
  2790. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, (void *) q,
  2791. (unsigned int) ip->size));
  2792. p = *q;
  2793. (void) soap_memcpy((void *) q, ip->size, (const void *) ip->ptr, ip->size);
  2794. q = (void **) p;
  2795. } while (q);
  2796. flag = 1;
  2797. }
  2798. while ((fp = ip->flist)) {
  2799. DBGLOG(TEST, SOAP_MESSAGE(fdebug,
  2800. "Resolving forwarded data type=%d target type=%d location=%p level=%u id='%s'\n",
  2801. ip->type, fp->type, ip->ptr, fp->level, ip->id));
  2802. if (fp->level == 0) {
  2803. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%lu bytes)\n", ip->ptr, fp->ptr,
  2804. (unsigned long) ip->size));
  2805. if (fp->finsert)
  2806. fp->finsert(soap, ip->type, fp->type, fp->ptr, fp->index, ip->ptr, &ip->smart);
  2807. else
  2808. (void) soap_memcpy((void *) fp->ptr, ip->size, (const void *) ip->ptr, ip->size);
  2809. }
  2810. ip->flist = fp->next;
  2811. SOAP_FREE(soap, fp);
  2812. flag = 1;
  2813. }
  2814. } else if (*ip->id == '#')
  2815. id = ip->id;
  2816. }
  2817. }
  2818. }
  2819. } while (flag);
  2820. if (id) {
  2821. DBGLOG(TEST, SOAP_MESSAGE(fdebug,
  2822. "Resolution error: forwarded data for id='%s' could not be propagated, please report this problem to the gSOAP developers\n",
  2823. id));
  2824. return soap_id_nullify(soap, id);
  2825. }
  2826. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n"));
  2827. return SOAP_OK;
  2828. }
  2829. #endif
  2830. /******************************************************************************/
  2831. SOAP_FMAC1
  2832. size_t
  2833. SOAP_FMAC2
  2834. soap_size_block(struct soap *soap, struct soap_blist *b, size_t n) {
  2835. if (!b)
  2836. b = soap->blist;
  2837. if (b->head) {
  2838. b->size -= b->head->size - n;
  2839. b->head->size = n;
  2840. }
  2841. return b->size;
  2842. }
  2843. /******************************************************************************/
  2844. SOAP_FMAC1
  2845. char *
  2846. SOAP_FMAC2
  2847. soap_first_block(struct soap *soap, struct soap_blist *b) {
  2848. struct soap_bhead *p, *q, *r;
  2849. if (!b)
  2850. b = soap->blist;
  2851. p = b->head;
  2852. if (!p)
  2853. return NULL;
  2854. r = NULL;
  2855. do {
  2856. q = p->next;
  2857. p->next = r;
  2858. r = p;
  2859. p = q;
  2860. } while (p);
  2861. b->head = r;
  2862. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block %p\n", (void *) (r + 1)));
  2863. return (char *) (r + 1);
  2864. }
  2865. /******************************************************************************/
  2866. SOAP_FMAC1
  2867. char *
  2868. SOAP_FMAC2
  2869. soap_next_block(struct soap *soap, struct soap_blist *b) {
  2870. struct soap_bhead *p;
  2871. if (!b)
  2872. b = soap->blist;
  2873. p = b->head;
  2874. if (p) {
  2875. b->head = p->next;
  2876. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block %p, deleting current block\n",
  2877. (void *) (b->head ? b->head + 1 : NULL)));
  2878. SOAP_FREE(soap, p);
  2879. if (b->head)
  2880. return (char *) (b->head + 1);
  2881. }
  2882. return NULL;
  2883. }
  2884. /******************************************************************************/
  2885. SOAP_FMAC1
  2886. size_t
  2887. SOAP_FMAC2
  2888. soap_block_size(struct soap *soap, struct soap_blist *b) {
  2889. if (!b)
  2890. b = soap->blist;
  2891. return b->head->size;
  2892. }
  2893. /******************************************************************************/
  2894. SOAP_FMAC1
  2895. void
  2896. SOAP_FMAC2
  2897. soap_end_block(struct soap *soap, struct soap_blist *b) {
  2898. struct soap_bhead *p, *q;
  2899. if (!b)
  2900. b = soap->blist;
  2901. if (b) {
  2902. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n"));
  2903. for (p = b->head; p; p = q) {
  2904. q = p->next;
  2905. SOAP_FREE(soap, p);
  2906. }
  2907. if (soap->blist == b)
  2908. soap->blist = b->next;
  2909. else {
  2910. struct soap_blist *bp;
  2911. for (bp = soap->blist; bp; bp = bp->next) {
  2912. if (bp->next == b) {
  2913. bp->next = b->next;
  2914. break;
  2915. }
  2916. }
  2917. }
  2918. SOAP_FREE(soap, b);
  2919. }
  2920. DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restored previous block sequence\n"));
  2921. #ifndef WITH_NOIDREF
  2922. if (!soap->blist && ((soap->version && !(soap->imode & SOAP_XML_TREE)) || (soap->mode & SOAP_XML_GRAPH))) {
  2923. int i;
  2924. struct soap_ilist *ip = NULL;
  2925. for (i = 0; i < SOAP_IDHASH; i++)
  2926. for (ip = soap->iht[i]; ip; ip = ip->next)
  2927. ip->shaky = 0;
  2928. }
  2929. #endif
  2930. }
  2931. /******************************************************************************/
  2932. SOAP_FMAC1
  2933. char *
  2934. SOAP_FMAC2
  2935. soap_save_block(struct soap *soap, struct soap_blist *b, char *p, int flag) {
  2936. size_t n;
  2937. char *q, *s;
  2938. if (!b)
  2939. b = soap->blist;
  2940. if (b->size) {
  2941. if (!p)
  2942. p = (char *) soap_malloc(soap, b->size);
  2943. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all %lu blocks in contiguous memory space of %u bytes (%p->%p)\n",
  2944. (unsigned long) b->item, (unsigned int) b->size, (void *) b->head, (void *) p));
  2945. if (p) {
  2946. s = p;
  2947. for (q = soap_first_block(soap, b); q; q = soap_next_block(soap, b)) {
  2948. n = soap_block_size(soap, b);
  2949. DBGLOG(TEST,
  2950. SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int) n, (void *) q, (void *) s));
  2951. if (flag)
  2952. soap_update_pointers(soap, s, q, n);
  2953. (void) soap_memcpy((void *) s, n, (const void *) q, n);
  2954. s += n;
  2955. }
  2956. } else
  2957. soap->error = SOAP_EOM;
  2958. }
  2959. soap_end_block(soap, b);
  2960. return p;
  2961. }
  2962. /******************************************************************************/
  2963. SOAP_FMAC1
  2964. char *
  2965. SOAP_FMAC2
  2966. soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim) {
  2967. int i;
  2968. const char *t = ",%d";
  2969. if (!type)
  2970. return NULL;
  2971. if (soap->version == 2)
  2972. t = " %d";
  2973. if (soap->version != 2 && offset) {
  2974. (SOAP_SNPRINTF(soap->type, sizeof(soap->type) - 1, strlen(type) + 20), "%s[%d", type, size[0] + offset[0]);
  2975. for (i = 1; i < dim; i++) {
  2976. size_t l = strlen(soap->type);
  2977. (SOAP_SNPRINTF(soap->type + l, sizeof(soap->type) - l - 1, 20), t, size[i] + offset[i]);
  2978. }
  2979. } else {
  2980. (SOAP_SNPRINTF(soap->type, sizeof(soap->type) - 1, strlen(type) + 20), "%s[%d", type, size[0]);
  2981. for (i = 1; i < dim; i++) {
  2982. size_t l = strlen(soap->type);
  2983. (SOAP_SNPRINTF(soap->type + l, sizeof(soap->type) - l - 1, 20), t, size[i]);
  2984. }
  2985. }
  2986. soap_strcat(soap->type, sizeof(soap->type), "]");
  2987. return soap->type;
  2988. }
  2989. /******************************************************************************/
  2990. SOAP_FMAC1
  2991. char *
  2992. SOAP_FMAC2
  2993. soap_putoffsets(struct soap *soap, const int *offset, int dim) {
  2994. int i;
  2995. soap->arrayOffset[0] = '\0';
  2996. if (soap->version == 1) {
  2997. (SOAP_SNPRINTF(soap->arrayOffset, sizeof(soap->arrayOffset) - 1, 20), "[%d", offset[0]);
  2998. for (i = 1; i < dim; i++) {
  2999. size_t l = strlen(soap->arrayOffset);
  3000. (SOAP_SNPRINTF(soap->arrayOffset + l, sizeof(soap->arrayOffset) - l - 1, 20), ",%d", offset[i]);
  3001. }
  3002. soap_strcat(soap->arrayOffset, sizeof(soap->arrayOffset), "]");
  3003. }
  3004. return soap->arrayOffset;
  3005. }
  3006. /******************************************************************************/
  3007. SOAP_FMAC1
  3008. size_t
  3009. SOAP_FMAC2
  3010. soap_size(const int *size, int dim) {
  3011. int i;
  3012. size_t n = 0;
  3013. if (size[0] <= 0)
  3014. return 0;
  3015. n = (size_t) size[0];
  3016. for (i = 1; i < dim; i++) {
  3017. if (size[i] <= 0)
  3018. return 0;
  3019. n *= (size_t) size[i];
  3020. }
  3021. return (size_t) n;
  3022. }
  3023. /******************************************************************************/
  3024. SOAP_FMAC1
  3025. size_t
  3026. SOAP_FMAC2
  3027. soap_getsizes(const char *attr, int *size, int dim) {
  3028. size_t i, k, n;
  3029. if (!*attr)
  3030. return 0;
  3031. i = strlen(attr);
  3032. n = 1;
  3033. do {
  3034. for (; i > 0; i--)
  3035. if (attr[i - 1] == '[' || attr[i - 1] == ',' || attr[i - 1] == ' ')
  3036. break;
  3037. n *= k = (size_t) soap_strtoul(attr + i, NULL, 10);
  3038. size[--dim] = (int) k;
  3039. if (n > SOAP_MAXARRAYSIZE)
  3040. return 0;
  3041. } while (dim > 0 && --i > 0 && attr[i] != '[');
  3042. return n;
  3043. }
  3044. /******************************************************************************/
  3045. SOAP_FMAC1
  3046. int
  3047. SOAP_FMAC2
  3048. soap_getoffsets(const char *attr, const int *size, int *offset, int dim) {
  3049. int i, j = 0;
  3050. if (offset) {
  3051. for (i = 0; i < dim && attr && *attr; i++) {
  3052. attr++;
  3053. j *= size[i];
  3054. j += offset[i] = (int) soap_strtol(attr, NULL, 10);
  3055. attr = strchr(attr, ',');
  3056. }
  3057. } else {
  3058. for (i = 0; i < dim && attr && *attr; i++) {
  3059. attr++;
  3060. j *= size[i];
  3061. j += (int) soap_strtol(attr, NULL, 10);
  3062. attr = strchr(attr, ',');
  3063. }
  3064. }
  3065. return j;
  3066. }
  3067. /******************************************************************************/
  3068. SOAP_FMAC1
  3069. int
  3070. SOAP_FMAC2
  3071. soap_getposition(const char *attr, int *pos) {
  3072. int i, n;
  3073. if (!*attr)
  3074. return -1;
  3075. n = 0;
  3076. i = 1;
  3077. do {
  3078. pos[n++] = (int) soap_strtol(attr + i, NULL, 10);
  3079. while (attr[i] && attr[i] != ',' && attr[i] != ']')
  3080. i++;
  3081. if (attr[i] == ',')
  3082. i++;
  3083. } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']');
  3084. return n;
  3085. }
  3086. /******************************************************************************/
  3087. SOAP_FMAC1
  3088. struct soap_nlist *
  3089. SOAP_FMAC2
  3090. soap_push_namespace(struct soap *soap, const char *id, const char *ns) {
  3091. struct soap_nlist *np = NULL;
  3092. struct Namespace *p;
  3093. short i = -1;
  3094. size_t n, k;
  3095. n = strlen(id);
  3096. k = strlen(ns) + 1;
  3097. p = soap->local_namespaces;
  3098. if (p) {
  3099. for (i = 0; p->id; p++, i++) {
  3100. if (p->ns && !strcmp(ns, p->ns))
  3101. break;
  3102. if (p->out) {
  3103. if (!strcmp(ns, p->out))
  3104. break;
  3105. } else if (p->in) {
  3106. if (!soap_tag_cmp(ns, p->in)) {
  3107. if (SOAP_MAXALLOCSIZE <= 0 || k <= SOAP_MAXALLOCSIZE)
  3108. p->out = (char *) SOAP_MALLOC(soap, k);
  3109. if (p->out)
  3110. soap_strcpy(p->out, k, ns);
  3111. break;
  3112. }
  3113. }
  3114. }
  3115. if (!p->id)
  3116. i = -1;
  3117. }
  3118. if (i >= 0)
  3119. k = 0;
  3120. if (sizeof(struct soap_nlist) + n + k > n &&
  3121. (SOAP_MAXALLOCSIZE <= 0 || sizeof(struct soap_nlist) + n + k <= SOAP_MAXALLOCSIZE))
  3122. np = (struct soap_nlist *) SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k);
  3123. if (!np) {
  3124. soap->error = SOAP_EOM;
  3125. return NULL;
  3126. }
  3127. np->next = soap->nlist;
  3128. soap->nlist = np;
  3129. np->level = soap->level;
  3130. np->index = i;
  3131. soap_strcpy((char *) np->id, n + 1, id);
  3132. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s'='%s'\n", soap->level, id, ns));
  3133. if (i < 0) {
  3134. np->ns = np->id + n + 1;
  3135. soap_strcpy((char *) np->ns, k, ns);
  3136. DBGLOG(TEST, SOAP_MESSAGE(fdebug,
  3137. "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n",
  3138. ns));
  3139. } else {
  3140. np->ns = NULL;
  3141. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id));
  3142. }
  3143. return np;
  3144. }
  3145. /******************************************************************************/
  3146. SOAP_FMAC1
  3147. void
  3148. SOAP_FMAC2
  3149. soap_pop_namespace(struct soap *soap) {
  3150. struct soap_nlist *np, *nq;
  3151. for (np = soap->nlist; np && np->level >= soap->level; np = nq) {
  3152. nq = np->next;
  3153. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop namespace binding (level=%u) '%s' level=%u\n", soap->level, np->id,
  3154. np->level));
  3155. SOAP_FREE(soap, np);
  3156. }
  3157. soap->nlist = np;
  3158. }
  3159. /******************************************************************************/
  3160. SOAP_FMAC1
  3161. int
  3162. SOAP_FMAC2
  3163. soap_match_namespace(struct soap *soap, const char *id1, const char *id2, size_t n1, size_t n2) {
  3164. struct soap_nlist *np = soap->nlist;
  3165. const char *s;
  3166. // std::cerr<<"Sassan Debug1: "<<np->ns<<std::endl;
  3167. while (np && (strncmp(np->id, id1, n1) || np->id[n1]))
  3168. np = np->next;
  3169. // std::cerr<<"Debug soap_match_namespace: "<<np<<" soap_match_namespace np->id: "<<np->id<<" id1: "<<id1 <<" n1: "<<n1<<" n2 "<<n2<<" id2 "<<id2<<" s "<<std::endl;
  3170. if (np) {
  3171. if (!(soap->mode & SOAP_XML_IGNORENS) && (n2 > 0 || !np->ns || *np->ns)) {
  3172. if (np->index < 0
  3173. || ((s = soap->local_namespaces[np->index].id) && (strncmp(s, id2, n2) || (s[n2] && s[n2] != '_'))))
  3174. return SOAP_NAMESPACE;
  3175. }
  3176. return SOAP_OK;
  3177. }
  3178. if (n1 == 0)
  3179. return n2 == 0 || (soap->mode & SOAP_XML_IGNORENS) ? SOAP_OK : SOAP_NAMESPACE;
  3180. if ((n1 == 3 && n1 == n2 && !strncmp(id1, "xml", 3) && !strncmp(id1, id2, 3))
  3181. || (soap->mode & SOAP_XML_IGNORENS))
  3182. return SOAP_OK;
  3183. return soap->error = SOAP_SYNTAX_ERROR;
  3184. }
  3185. /******************************************************************************/
  3186. SOAP_FMAC1
  3187. const char *
  3188. SOAP_FMAC2
  3189. soap_current_namespace_tag(struct soap *soap, const char *tag) {
  3190. struct soap_nlist *np;
  3191. const char *s;
  3192. if (!tag || !strncmp(tag, "xml", 3))
  3193. return NULL;
  3194. np = soap->nlist;
  3195. s = strchr(tag, ':');
  3196. if (!s) {
  3197. while (np && *np->id) /* find default namespace, if present */
  3198. np = np->next;
  3199. } else {
  3200. while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag]))
  3201. np = np->next;
  3202. if (!np)
  3203. soap->error = SOAP_NAMESPACE;
  3204. }
  3205. if (np) {
  3206. if (np->index >= 0)
  3207. return soap->namespaces[np->index].ns;
  3208. if (np->ns) {
  3209. s = np->ns;
  3210. if (*s)
  3211. return soap_strdup(soap, s);
  3212. do
  3213. np = np->next;
  3214. while (np && *np->id); /* find if there is any other default namespace */
  3215. if (np)
  3216. return soap_strdup(soap, s);
  3217. }
  3218. }
  3219. return NULL;
  3220. }
  3221. /******************************************************************************/
  3222. SOAP_FMAC1
  3223. const char *
  3224. SOAP_FMAC2
  3225. soap_current_namespace_att(struct soap *soap, const char *tag) {
  3226. struct soap_nlist *np;
  3227. const char *s;
  3228. if (!tag || !strncmp(tag, "xml", 3))
  3229. return NULL;
  3230. s = strchr(tag, ':');
  3231. if (!s)
  3232. return NULL;
  3233. np = soap->nlist;
  3234. while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag]))
  3235. np = np->next;
  3236. if (!np)
  3237. soap->error = SOAP_NAMESPACE;
  3238. if (np) {
  3239. if (np->index >= 0)
  3240. return soap->namespaces[np->index].ns;
  3241. if (np->ns && *np->ns)
  3242. return soap_strdup(soap, np->ns);
  3243. }
  3244. return NULL;
  3245. }
  3246. /******************************************************************************/
  3247. SOAP_FMAC1
  3248. int
  3249. SOAP_FMAC2
  3250. soap_tag_cmp(const char *s, const char *t) {
  3251. for (;;) {
  3252. int c1 = *s;
  3253. int c2 = *t;
  3254. if (!c1 || c1 == '"')
  3255. break;
  3256. if (c2 != '-') {
  3257. if (c1 != c2) {
  3258. if (c1 >= 'A' && c1 <= 'Z')
  3259. c1 += 'a' - 'A';
  3260. if (c2 >= 'A' && c2 <= 'Z')
  3261. c2 += 'a' - 'A';
  3262. }
  3263. if (c1 != c2) {
  3264. if (c2 != '*')
  3265. return 1;
  3266. c2 = *++t;
  3267. if (!c2)
  3268. return 0;
  3269. if (c2 >= 'A' && c2 <= 'Z')
  3270. c2 += 'a' - 'A';
  3271. for (;;) {
  3272. c1 = *s;
  3273. if (!c1 || c1 == '"')
  3274. break;
  3275. if (c1 >= 'A' && c1 <= 'Z')
  3276. c1 += 'a' - 'A';
  3277. if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1))
  3278. return 0;
  3279. s++;
  3280. }
  3281. break;
  3282. }
  3283. }
  3284. s++;
  3285. t++;
  3286. }
  3287. if (*t == '*' && !t[1])
  3288. return 0;
  3289. return *t;
  3290. }
  3291. /******************************************************************************/
  3292. SOAP_FMAC1
  3293. int
  3294. SOAP_FMAC2
  3295. soap_match_tag(struct soap *soap, const char *tag1, const char *tag2) {
  3296. const char *s, *t;
  3297. int err;
  3298. if (!tag1 || !tag2 || !*tag2)
  3299. return SOAP_OK;
  3300. s = strchr(tag1, ':');
  3301. t = strchr(tag2, ':');
  3302. if (t) {
  3303. if (s) {
  3304. if (t[1] && SOAP_STRCMP(s + 1, t + 1))
  3305. return SOAP_TAG_MISMATCH;
  3306. if (t != tag2 && !(soap->mode & SOAP_XML_IGNORENS)) {
  3307. // err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2);
  3308. err = SOAP_OK;
  3309. // std::cerr<<"soap_match_namespace err: "<<err<<std::endl;
  3310. if (err) {
  3311. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sassan Debug '%s' and '%s' r\n", tag1, tag2));
  3312. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
  3313. if (err == SOAP_NAMESPACE)
  3314. return SOAP_TAG_MISMATCH;
  3315. return err;
  3316. }
  3317. }
  3318. } else if (!t[1]) {
  3319. if ((soap->mode & SOAP_XML_IGNORENS) || soap_match_namespace(soap, tag1, tag2, 0, t - tag2))
  3320. return SOAP_TAG_MISMATCH;
  3321. } else if (SOAP_STRCMP(tag1, t + 1)) {
  3322. return SOAP_TAG_MISMATCH;
  3323. } else if (t != tag2) {
  3324. err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2);
  3325. if (err) {
  3326. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
  3327. if (err == SOAP_NAMESPACE)
  3328. return SOAP_TAG_MISMATCH;
  3329. return err;
  3330. }
  3331. }
  3332. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2));
  3333. return SOAP_OK;
  3334. }
  3335. if (s) {
  3336. if (!(soap->mode & SOAP_XML_IGNORENS) || SOAP_STRCMP(s + 1, tag2)) /* always fails (except when ignoring ns) */
  3337. return SOAP_TAG_MISMATCH;
  3338. } else if (SOAP_STRCMP(tag1, tag2)
  3339. #ifndef WITH_NOEMPTYNAMESPACES
  3340. || ((soap->mode & SOAP_XML_STRICT) && !(soap->mode & SOAP_XML_IGNORENS) &&
  3341. soap_match_namespace(soap, tag1, tag2, 0,
  3342. 0)) /* strict checking: default namespace must be null namespace */
  3343. #endif
  3344. ) {
  3345. return SOAP_TAG_MISMATCH;
  3346. }
  3347. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2));
  3348. return SOAP_OK;
  3349. }
  3350. /******************************************************************************/
  3351. SOAP_FMAC1
  3352. int
  3353. SOAP_FMAC2
  3354. soap_match_att(struct soap *soap, const char *tag1, const char *tag2) {
  3355. const char *s, *t;
  3356. int err;
  3357. if (!tag1 || !tag2 || !*tag2)
  3358. return SOAP_OK;
  3359. s = strchr(tag1, ':');
  3360. t = strchr(tag2, ':');
  3361. if (t) {
  3362. if (s) {
  3363. if (t[1] && SOAP_STRCMP(s + 1, t + 1))
  3364. return SOAP_TAG_MISMATCH;
  3365. if (t != tag2 && !(soap->mode & SOAP_XML_IGNORENS)) {
  3366. err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2);
  3367. if (err) {
  3368. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Atts '%s' and '%s' match but namespaces differ\n", tag1, tag2));
  3369. if (err == SOAP_NAMESPACE)
  3370. return SOAP_TAG_MISMATCH;
  3371. return err;
  3372. }
  3373. }
  3374. } else if (!t[1] || t != tag2 || SOAP_STRCMP(tag1, t + 1))
  3375. return SOAP_TAG_MISMATCH;
  3376. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Atts and (default) namespaces match: '%s' '%s'\n", tag1, tag2));
  3377. return SOAP_OK;
  3378. }
  3379. if (s) {
  3380. if (!(soap->mode & SOAP_XML_IGNORENS) || SOAP_STRCMP(s + 1, tag2)) /* always fails (except when ignoring ns) */
  3381. return SOAP_TAG_MISMATCH;
  3382. } else if (SOAP_STRCMP(tag1, tag2))
  3383. return SOAP_TAG_MISMATCH;
  3384. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Atts match: '%s' '%s'\n", tag1, tag2));
  3385. return SOAP_OK;
  3386. }
  3387. /******************************************************************************/
  3388. SOAP_FMAC1
  3389. int
  3390. SOAP_FMAC2
  3391. soap_match_array(struct soap *soap, const char *type) {
  3392. if (type && *soap->arrayType) {
  3393. if (soap->version == 1 || !strchr(type, '[')) {
  3394. if (soap_match_tag(soap, soap->arrayType, type)
  3395. && soap_match_tag(soap, soap->arrayType, "xsd:anyType")
  3396. && soap_match_tag(soap, soap->arrayType, "xsd:ur-type")) {
  3397. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SOAP array type mismatch: '%s' '%s'\n", soap->arrayType, type));
  3398. return SOAP_TAG_MISMATCH;
  3399. }
  3400. }
  3401. }
  3402. return SOAP_OK;
  3403. }
  3404. /******************************************************************************\
  3405. *
  3406. * SSL/TLS
  3407. *
  3408. \******************************************************************************/
  3409. #ifdef WITH_OPENSSL
  3410. SOAP_FMAC1
  3411. int
  3412. SOAP_FMAC2
  3413. soap_rand()
  3414. {
  3415. int r;
  3416. if (!soap_ssl_init_done)
  3417. soap_ssl_init();
  3418. #if OPENSSL_VERSION_NUMBER < 0x10100000L
  3419. RAND_pseudo_bytes((unsigned char*)&r, sizeof(int));
  3420. #else
  3421. RAND_bytes((unsigned char*)&r, sizeof(int));
  3422. #endif
  3423. return r;
  3424. }
  3425. #endif
  3426. /******************************************************************************/
  3427. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_SYSTEMSSL)
  3428. SOAP_FMAC1
  3429. int
  3430. SOAP_FMAC2
  3431. #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
  3432. soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *keyid, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid)
  3433. #else
  3434. soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid)
  3435. #endif
  3436. {
  3437. int err;
  3438. soap->keyfile = keyfile;
  3439. #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
  3440. soap->keyid = keyid; /* vxWorks compatible */
  3441. #endif
  3442. soap->password = password;
  3443. soap->cafile = cafile;
  3444. soap->capath = capath;
  3445. #ifdef WITH_OPENSSL
  3446. soap->dhfile = dhfile;
  3447. soap->randfile = randfile;
  3448. if (!soap->fsslverify)
  3449. soap->fsslverify = ssl_verify_callback;
  3450. #endif
  3451. soap->ssl_flags = flags | (dhfile == NULL ? SOAP_SSL_RSA : 0);
  3452. #ifdef WITH_GNUTLS
  3453. (void)randfile; (void)sid;
  3454. if (dhfile)
  3455. {
  3456. char *s;
  3457. int n = (int)soap_strtoul(dhfile, &s, 10);
  3458. if (!soap->dh_params)
  3459. gnutls_dh_params_init(&soap->dh_params);
  3460. /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
  3461. if (n >= 512 && s && *s == '\0')
  3462. gnutls_dh_params_generate2(soap->dh_params, (unsigned int)n);
  3463. else
  3464. {
  3465. unsigned int dparams_len;
  3466. unsigned char dparams_buf[1024];
  3467. FILE *fd = fopen(dhfile, "r");
  3468. if (!fd)
  3469. return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR);
  3470. dparams_len = (unsigned int)fread(dparams_buf, 1, sizeof(dparams_buf), fd);
  3471. fclose(fd);
  3472. gnutls_datum_t dparams = {
  3473. dparams_buf, dparams_len };
  3474. if (gnutls_dh_params_import_pkcs3(soap->dh_params, &dparams, GNUTLS_X509_FMT_PEM))
  3475. return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR);
  3476. }
  3477. }
  3478. else
  3479. {
  3480. #if GNUTLS_VERSION_NUMBER < 0x030300
  3481. if (!soap->rsa_params)
  3482. gnutls_rsa_params_init(&soap->rsa_params);
  3483. gnutls_rsa_params_generate2(soap->rsa_params, SOAP_SSL_RSA_BITS);
  3484. #endif
  3485. }
  3486. if (soap->session)
  3487. {
  3488. gnutls_deinit(soap->session);
  3489. soap->session = NULL;
  3490. }
  3491. if (soap->xcred)
  3492. {
  3493. gnutls_certificate_free_credentials(soap->xcred);
  3494. soap->xcred = NULL;
  3495. }
  3496. #endif
  3497. #ifdef WITH_SYSTEMSSL
  3498. (void)randfile; (void)sid;
  3499. if (soap->ctx)
  3500. gsk_environment_close(&soap->ctx);
  3501. #endif
  3502. err = soap->fsslauth(soap);
  3503. #ifdef WITH_OPENSSL
  3504. if (!err)
  3505. {
  3506. if (sid)
  3507. SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, (unsigned int)strlen(sid));
  3508. else
  3509. SSL_CTX_set_session_cache_mode(soap->ctx, SSL_SESS_CACHE_OFF);
  3510. }
  3511. #endif
  3512. return err;
  3513. }
  3514. #endif
  3515. /******************************************************************************/
  3516. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_SYSTEMSSL)
  3517. SOAP_FMAC1
  3518. int
  3519. SOAP_FMAC2
  3520. #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
  3521. soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *keyid, const char *password, const char *cafile, const char *capath, const char *randfile)
  3522. #else
  3523. soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *randfile)
  3524. #endif
  3525. {
  3526. soap->keyfile = keyfile;
  3527. #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
  3528. soap->keyid = keyid; /* vxWorks compatible */
  3529. #endif
  3530. soap->password = password;
  3531. soap->cafile = cafile;
  3532. soap->capath = capath;
  3533. soap->ssl_flags = SOAP_SSL_CLIENT | flags;
  3534. #ifdef WITH_OPENSSL
  3535. soap->dhfile = NULL;
  3536. soap->randfile = randfile;
  3537. if (!soap->fsslverify)
  3538. soap->fsslverify = (flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) == 0 ? ssl_verify_callback : ssl_verify_callback_allow_expired_certificate;
  3539. #endif
  3540. #ifdef WITH_GNUTLS
  3541. (void)randfile;
  3542. if (soap->session)
  3543. {
  3544. gnutls_deinit(soap->session);
  3545. soap->session = NULL;
  3546. }
  3547. if (soap->xcred)
  3548. {
  3549. gnutls_certificate_free_credentials(soap->xcred);
  3550. soap->xcred = NULL;
  3551. }
  3552. #endif
  3553. #ifdef WITH_SYSTEMSSL
  3554. (void)randfile;
  3555. if (soap->ctx)
  3556. gsk_environment_close(&soap->ctx);
  3557. #endif
  3558. return soap->fsslauth(soap);
  3559. }
  3560. #endif
  3561. /******************************************************************************/
  3562. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
  3563. SOAP_FMAC1
  3564. int
  3565. SOAP_FMAC2
  3566. soap_ssl_crl(struct soap *soap, const char *crlfile)
  3567. {
  3568. #ifdef WITH_OPENSSL
  3569. if (crlfile && soap->ctx)
  3570. {
  3571. #if OPENSSL_VERSION_NUMBER > 0x00907000L
  3572. X509_STORE *store = SSL_CTX_get_cert_store(soap->ctx);
  3573. if (*crlfile)
  3574. {
  3575. int ret;
  3576. X509_LOOKUP *lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
  3577. if (!lookup)
  3578. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't create X509_LOOKUP object", SOAP_SSL_ERROR);
  3579. ret = X509_load_crl_file(lookup, crlfile, X509_FILETYPE_PEM);
  3580. if (ret <= 0)
  3581. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CRL PEM file", SOAP_SSL_ERROR);
  3582. }
  3583. X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
  3584. #endif
  3585. }
  3586. else
  3587. soap->crlfile = crlfile; /* activate later when store is available */
  3588. #endif
  3589. #ifdef WITH_GNUTLS
  3590. if (crlfile && soap->xcred)
  3591. {
  3592. if (*crlfile)
  3593. if (gnutls_certificate_set_x509_crl_file(soap->xcred, crlfile, GNUTLS_X509_FMT_PEM) < 0)
  3594. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CRL PEM file", SOAP_SSL_ERROR);
  3595. }
  3596. else
  3597. {
  3598. soap->crlfile = crlfile; /* activate later when xcred is available */
  3599. }
  3600. #endif
  3601. return SOAP_OK;
  3602. }
  3603. #endif
  3604. /******************************************************************************/
  3605. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
  3606. SOAP_FMAC1
  3607. void
  3608. SOAP_FMAC2
  3609. soap_ssl_init()
  3610. {
  3611. /* Note: for multi-threaded applications, the main program should call soap_ssl_init() before any threads are started */
  3612. if (!soap_ssl_init_done)
  3613. {
  3614. soap_ssl_init_done = 1;
  3615. #ifdef WITH_OPENSSL
  3616. SSL_library_init();
  3617. OpenSSL_add_all_algorithms(); /* we keep ciphers and digests for the program's lifetime */
  3618. #ifndef WITH_LEAN
  3619. SSL_load_error_strings();
  3620. #endif
  3621. #if !defined(WIN32) && !defined(CYGWIN) && !defined(__MINGW32__) && !defined(__MINGW64__)
  3622. if (!RAND_load_file("/dev/urandom", 1024))
  3623. #else
  3624. if (1)
  3625. #endif
  3626. {
  3627. /* if /dev/urandom does not exist we need to do at least some pertubations to seed the OpenSSL PRNG */
  3628. char buf[1024];
  3629. RAND_seed(buf, sizeof(buf));
  3630. #ifdef HAVE_RANDOM
  3631. srandom((unsigned long)time(NULL));
  3632. #else
  3633. srand((unsigned int)time(NULL));
  3634. #endif
  3635. do
  3636. {
  3637. #ifdef HAVE_RANDOM
  3638. long r = random(); /* we actually do no use random() anywhere, except to help seed the OpenSSL PRNG */
  3639. RAND_seed(&r, sizeof(long));
  3640. #else
  3641. int r = rand(); /* we actually do no use rand() anywhere, except to help seed the OpenSSL PRNG */
  3642. RAND_seed(&r, sizeof(int));
  3643. #endif
  3644. } while (!RAND_status());
  3645. }
  3646. #endif
  3647. #ifdef WITH_GNUTLS
  3648. # if GNUTLS_VERSION_NUMBER < 0x020b00
  3649. # if defined(HAVE_PTHREAD_H)
  3650. gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
  3651. # elif defined(HAVE_PTH_H)
  3652. gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
  3653. # endif
  3654. gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0);
  3655. gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
  3656. gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); /* libgcrypt init done */
  3657. # endif
  3658. # if GNUTLS_VERSION_NUMBER < 0x030300
  3659. gnutls_global_init();
  3660. # endif
  3661. #endif
  3662. }
  3663. }
  3664. #endif
  3665. /******************************************************************************/
  3666. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
  3667. SOAP_FMAC1
  3668. void
  3669. SOAP_FMAC2
  3670. soap_ssl_noinit()
  3671. {
  3672. /* Call this first to bypass SSL init is SSL is already initialized elsewhere */
  3673. soap_ssl_init_done = 1;
  3674. }
  3675. #endif
  3676. /******************************************************************************/
  3677. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
  3678. SOAP_FMAC1
  3679. const char *
  3680. SOAP_FMAC2
  3681. soap_ssl_error(struct soap *soap, int ret, int err)
  3682. {
  3683. #ifdef WITH_OPENSSL
  3684. const char *msg = soap_code_str(h_ssl_error_codes, err);
  3685. if (!msg)
  3686. return ERR_error_string(err, soap->msgbuf);
  3687. (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(msg) + 1), "%s\n", msg);
  3688. if (ERR_peek_error())
  3689. {
  3690. unsigned long r;
  3691. while ((r = ERR_get_error()))
  3692. {
  3693. size_t l = strlen(soap->msgbuf);
  3694. ERR_error_string_n(r, soap->msgbuf + l, sizeof(soap->msgbuf) - l);
  3695. l = strlen(soap->msgbuf);
  3696. if (l + 1 < sizeof(soap->msgbuf))
  3697. {
  3698. soap->msgbuf[l++] = '\n';
  3699. soap->msgbuf[l] = '\0';
  3700. }
  3701. if (ERR_GET_REASON(r) == SSL_R_CERTIFICATE_VERIFY_FAILED && l < sizeof(soap->msgbuf))
  3702. {
  3703. const char *s = X509_verify_cert_error_string(SSL_get_verify_result(soap->ssl));
  3704. (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, strlen(s)), "%s", s);
  3705. }
  3706. }
  3707. }
  3708. else
  3709. {
  3710. size_t l = strlen(soap->msgbuf);
  3711. switch (ret)
  3712. {
  3713. case 0:
  3714. soap_strcpy(soap->msgbuf + l, sizeof(soap->msgbuf) - l, "EOF was observed that violates the SSL/TLS protocol. The client probably provided invalid authentication information.");
  3715. break;
  3716. case -1:
  3717. {
  3718. const char *s = strerror(soap_errno);
  3719. (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, strlen(s) + 42), "Error observed by underlying SSL/TLS BIO: %s", s);
  3720. }
  3721. break;
  3722. }
  3723. }
  3724. ERR_clear_error();
  3725. return soap->msgbuf;
  3726. #endif
  3727. #ifdef WITH_GNUTLS
  3728. (void)soap;
  3729. (void)err;
  3730. return gnutls_strerror(ret);
  3731. #endif
  3732. }
  3733. #endif
  3734. /******************************************************************************/
  3735. #ifdef WITH_SYSTEMSSL
  3736. static int
  3737. ssl_recv(int sk, void *s, int n, char *user)
  3738. {
  3739. (void)user;
  3740. return recv(sk, s, n, 0);
  3741. }
  3742. #endif
  3743. /******************************************************************************/
  3744. #ifdef WITH_SYSTEMSSL
  3745. static int
  3746. ssl_send(int sk, void *s, int n, char *user)
  3747. {
  3748. (void)user;
  3749. return send(sk, s, n, 0);
  3750. }
  3751. #endif
  3752. /******************************************************************************/
  3753. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_SYSTEMSSL)
  3754. static int
  3755. ssl_auth_init(struct soap *soap)
  3756. {
  3757. #ifdef WITH_OPENSSL
  3758. #if OPENSSL_VERSION_NUMBER >= 0x10101000L
  3759. int minv = 0, maxv = 0;
  3760. #endif
  3761. long flags = SSL_OP_ALL;
  3762. int mode;
  3763. #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
  3764. EVP_PKEY* pkey; /* vxWorks compatible */
  3765. #endif
  3766. if (!soap_ssl_init_done)
  3767. soap_ssl_init();
  3768. ERR_clear_error();
  3769. if (!soap->ctx)
  3770. {
  3771. #if OPENSSL_VERSION_NUMBER >= 0x10100000L
  3772. /* TLS_method: a TLS/SSL connection established may understand the SSLv3, TLSv1, TLSv1.1 and TLSv1.2 protocols. */
  3773. soap->ctx = SSL_CTX_new(TLS_method());
  3774. #else
  3775. /* SSLv23_method: a TLS/SSL connection established may understand the SSLv3, TLSv1, TLSv1.1 and TLSv1.2 protocols. */
  3776. soap->ctx = SSL_CTX_new(SSLv23_method());
  3777. #endif
  3778. if (!soap->ctx)
  3779. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't setup context", SOAP_SSL_ERROR);
  3780. /* The following alters the behavior of SSL read/write: */
  3781. #if 0
  3782. SSL_CTX_set_mode(soap->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY);
  3783. #endif
  3784. }
  3785. if (soap->randfile)
  3786. {
  3787. if (!RAND_load_file(soap->randfile, -1))
  3788. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't load randomness", SOAP_SSL_ERROR);
  3789. }
  3790. if (soap->cafile || soap->capath)
  3791. {
  3792. if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath))
  3793. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA PEM file", SOAP_SSL_ERROR);
  3794. if (soap->cafile && (soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
  3795. SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile));
  3796. }
  3797. if (!(soap->ssl_flags & SOAP_SSL_NO_DEFAULT_CA_PATH))
  3798. {
  3799. if (!SSL_CTX_set_default_verify_paths(soap->ctx))
  3800. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read default CA PEM file and/or directory", SOAP_SSL_ERROR);
  3801. }
  3802. if (soap->crlfile)
  3803. {
  3804. if (soap_ssl_crl(soap, soap->crlfile))
  3805. return soap->error;
  3806. }
  3807. /* This code assumes a typical scenario with key and cert in one PEM file, see alternative code below */
  3808. #if 1
  3809. if (soap->keyfile)
  3810. {
  3811. if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
  3812. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't find or read certificate in private key PEM file", SOAP_SSL_ERROR);
  3813. if (soap->password)
  3814. {
  3815. SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
  3816. SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
  3817. }
  3818. #ifndef WM_SECURE_KEY_STORAGE
  3819. if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
  3820. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read private key PEM file", SOAP_SSL_ERROR);
  3821. #endif
  3822. }
  3823. #else
  3824. /* Suggested alternative approach to check the key file for cert only when cafile==NULL */
  3825. if (soap->password)
  3826. {
  3827. SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
  3828. SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
  3829. }
  3830. if (!soap->cafile)
  3831. {
  3832. if (soap->keyfile)
  3833. {
  3834. if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
  3835. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't find or read certificate in private key PEM file", SOAP_SSL_ERROR);
  3836. if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
  3837. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read private key PEM file", SOAP_SSL_ERROR);
  3838. }
  3839. }
  3840. else /* use cafile for (server) cert and keyfile for (server) key */
  3841. {
  3842. if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile))
  3843. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA PEM file", SOAP_SSL_ERROR);
  3844. if (soap->keyfile)
  3845. if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
  3846. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read private key PEM file", SOAP_SSL_ERROR);
  3847. }
  3848. #endif
  3849. #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
  3850. /* vxWorks compatible */
  3851. pkey = ipcom_key_db_pkey_get(soap->keyid);
  3852. if (!pkey)
  3853. return soap_set_receiver_error(soap, "SSL error", "Can't find key", SOAP_SSL_ERROR);
  3854. if (!SSL_CTX_use_PrivateKey(soap->ctx, pkey))
  3855. return soap_set_receiver_error(soap, "SSL error", "Can't read key", SOAP_SSL_ERROR);
  3856. #endif
  3857. if ((soap->ssl_flags & SOAP_SSL_RSA))
  3858. {
  3859. #if OPENSSL_VERSION_NUMBER >= 0x10002000L
  3860. if (SSL_CTX_need_tmp_RSA(soap->ctx))
  3861. {
  3862. unsigned long e = RSA_F4;
  3863. BIGNUM *bne = BN_new();
  3864. RSA *rsa = RSA_new();
  3865. if (!bne || !rsa || !BN_set_word(bne, e) || !RSA_generate_key_ex(rsa, SOAP_SSL_RSA_BITS, bne, NULL) || !SSL_CTX_set_tmp_rsa(soap->ctx, rsa))
  3866. {
  3867. if (bne)
  3868. BN_free(bne);
  3869. if (rsa)
  3870. RSA_free(rsa);
  3871. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't generate RSA key", SOAP_SSL_ERROR);
  3872. }
  3873. BN_free(bne);
  3874. RSA_free(rsa);
  3875. }
  3876. #else
  3877. RSA *rsa = RSA_generate_key(SOAP_SSL_RSA_BITS, RSA_F4, NULL, NULL);
  3878. if (!rsa || !SSL_CTX_set_tmp_rsa(soap->ctx, rsa))
  3879. {
  3880. if (rsa)
  3881. RSA_free(rsa);
  3882. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't generate RSA key", SOAP_SSL_ERROR);
  3883. }
  3884. RSA_free(rsa);
  3885. #endif
  3886. }
  3887. else if (soap->dhfile)
  3888. {
  3889. DH *dh = NULL;
  3890. char *s;
  3891. int n = (int)soap_strtoul(soap->dhfile, &s, 10);
  3892. /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
  3893. if (n >= 512 && s && *s == '\0')
  3894. {
  3895. #if OPENSSL_VERSION_NUMBER >= 0x10002000L
  3896. dh = DH_new();
  3897. if (!DH_generate_parameters_ex(dh, n, 2/*or 5*/, NULL))
  3898. {
  3899. DH_free(dh);
  3900. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't generate DH parameters", SOAP_SSL_ERROR);
  3901. }
  3902. #elif defined(VXWORKS)
  3903. dh = DH_new();
  3904. DH_generate_parameters_ex(dh, n, 2/*or 5*/, NULL);
  3905. #else
  3906. dh = DH_generate_parameters(n, 2/*or 5*/, NULL, NULL);
  3907. #endif
  3908. }
  3909. else
  3910. {
  3911. BIO *bio;
  3912. bio = BIO_new_file(soap->dhfile, "r");
  3913. if (!bio)
  3914. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read DH PEM file", SOAP_SSL_ERROR);
  3915. dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
  3916. BIO_free(bio);
  3917. }
  3918. if (!dh || DH_check(dh, &n) != 1 || SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0)
  3919. {
  3920. if (dh)
  3921. DH_free(dh);
  3922. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set DH parameters", SOAP_SSL_ERROR);
  3923. }
  3924. DH_free(dh);
  3925. }
  3926. /* enable all TSLv1 protocols and disable SSLv3 by default if no SSL/TLS flags are set */
  3927. if (!(soap->ssl_flags & SOAP_SSLv3_TLSv1))
  3928. soap->ssl_flags = SOAP_TLSv1;
  3929. #if OPENSSL_VERSION_NUMBER >= 0x10101000L
  3930. if ((soap->ssl_flags & SOAP_SSLv3))
  3931. minv = SSL3_VERSION;
  3932. else if ((soap->ssl_flags & SOAP_TLSv1_0))
  3933. minv = TLS1_VERSION;
  3934. else if ((soap->ssl_flags & SOAP_TLSv1_1))
  3935. minv = TLS1_1_VERSION;
  3936. else if ((soap->ssl_flags & SOAP_TLSv1_2))
  3937. minv = TLS1_2_VERSION;
  3938. else if ((soap->ssl_flags & SOAP_TLSv1_3))
  3939. minv = TLS1_3_VERSION;
  3940. if ((soap->ssl_flags & SOAP_TLSv1_3) && OpenSSL_version_num() >= 0x10101000L)
  3941. maxv = TLS1_3_VERSION;
  3942. else if ((soap->ssl_flags & SOAP_TLSv1_2))
  3943. maxv = TLS1_2_VERSION;
  3944. else if ((soap->ssl_flags & SOAP_TLSv1_1))
  3945. maxv = TLS1_1_VERSION;
  3946. else if ((soap->ssl_flags & SOAP_TLSv1_0))
  3947. maxv = TLS1_VERSION;
  3948. else
  3949. maxv = SSL3_VERSION;
  3950. if (!SSL_CTX_set_min_proto_version(soap->ctx, minv)
  3951. || !SSL_CTX_set_max_proto_version(soap->ctx, maxv))
  3952. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set protocol version", SOAP_SSL_ERROR);
  3953. #else
  3954. /* disable SSL v2 by default and enable specific protos */
  3955. flags = SSL_OP_NO_SSLv2;
  3956. if (!(soap->ssl_flags & SOAP_SSLv3))
  3957. flags |= SSL_OP_NO_SSLv3;
  3958. #if OPENSSL_VERSION_NUMBER >= 0x10001000L
  3959. if (!(soap->ssl_flags & SOAP_TLSv1_0))
  3960. flags |= SSL_OP_NO_TLSv1;
  3961. if (!(soap->ssl_flags & SOAP_TLSv1_1))
  3962. flags |= SSL_OP_NO_TLSv1_1;
  3963. if (!(soap->ssl_flags & SOAP_TLSv1_2))
  3964. flags |= SSL_OP_NO_TLSv1_2;
  3965. #endif
  3966. #endif
  3967. #ifdef SSL_OP_NO_TICKET
  3968. /* TLS extension is enabled by default in OPENSSL v0.9.8k disable it by */
  3969. flags |= SSL_OP_NO_TICKET;
  3970. #endif
  3971. SSL_CTX_set_options(soap->ctx, flags);
  3972. if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
  3973. mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
  3974. else if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
  3975. mode = SSL_VERIFY_PEER;
  3976. else
  3977. mode = SSL_VERIFY_NONE;
  3978. SSL_CTX_set_verify(soap->ctx, mode, soap->fsslverify);
  3979. #if OPENSSL_VERSION_NUMBER < 0x00905100L
  3980. SSL_CTX_set_verify_depth(soap->ctx, 1);
  3981. #else
  3982. SSL_CTX_set_verify_depth(soap->ctx, 9);
  3983. #endif
  3984. #endif
  3985. #ifdef WITH_GNUTLS
  3986. int ret;
  3987. char priority[80];
  3988. soap_strcpy(priority, sizeof(priority), "PERFORMANCE");
  3989. if (!soap_ssl_init_done)
  3990. soap_ssl_init();
  3991. if (!soap->xcred)
  3992. {
  3993. if (gnutls_certificate_allocate_credentials(&soap->xcred) != GNUTLS_E_SUCCESS)
  3994. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't allocate credentials or trust", SOAP_SSL_ERROR);
  3995. #if GNUTLS_VERSION_NUMBER >= 0x030300
  3996. gnutls_certificate_set_x509_system_trust(soap->xcred);
  3997. #endif
  3998. if (soap->cafile)
  3999. {
  4000. if (gnutls_certificate_set_x509_trust_file(soap->xcred, soap->cafile, GNUTLS_X509_FMT_PEM) < 0)
  4001. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA PEM file", SOAP_SSL_ERROR);
  4002. }
  4003. if (soap->crlfile)
  4004. {
  4005. if (soap_ssl_crl(soap, soap->crlfile))
  4006. return soap->error;
  4007. }
  4008. if (soap->keyfile)
  4009. {
  4010. if (gnutls_certificate_set_x509_key_file2(soap->xcred, soap->keyfile, soap->keyfile, GNUTLS_X509_FMT_PEM, soap->password, GNUTLS_PKCS_PKCS12_3DES | GNUTLS_PKCS_PKCS12_ARCFOUR | GNUTLS_PKCS_PKCS12_RC2_40 | GNUTLS_PKCS_PBES2_AES_128 | GNUTLS_PKCS_PBES2_AES_192 | GNUTLS_PKCS_PBES2_AES_256 | GNUTLS_PKCS_PBES2_DES) < 0) /* Assumes that key and cert(s) are concatenated in the keyfile and the key is encrypted with one of these algorithms */
  4011. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read private key PEM file", SOAP_SSL_ERROR);
  4012. }
  4013. }
  4014. if ((soap->ssl_flags & SOAP_SSL_CLIENT))
  4015. {
  4016. gnutls_init(&soap->session, GNUTLS_CLIENT);
  4017. if (soap->cafile || soap->crlfile || soap->keyfile)
  4018. {
  4019. ret = gnutls_priority_set_direct(soap->session, "PERFORMANCE", NULL);
  4020. if (ret != GNUTLS_E_SUCCESS)
  4021. return soap_set_receiver_error(soap, soap_ssl_error(soap, ret, 0), "SSL/TLS set priority error", SOAP_SSL_ERROR);
  4022. gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred);
  4023. }
  4024. else
  4025. {
  4026. if (!soap->acred)
  4027. gnutls_anon_allocate_client_credentials(&soap->acred);
  4028. ret = gnutls_priority_set_direct(soap->session, "PERFORMANCE:+ANON-DH:!ARCFOUR-128", NULL);
  4029. if (ret != GNUTLS_E_SUCCESS)
  4030. return soap_set_receiver_error(soap, soap_ssl_error(soap, ret, 0), "SSL/TLS set priority error", SOAP_SSL_ERROR);
  4031. gnutls_credentials_set(soap->session, GNUTLS_CRD_ANON, soap->acred);
  4032. }
  4033. }
  4034. else if (!soap->keyfile)
  4035. {
  4036. return soap_set_receiver_error(soap, "SSL/TLS error", "No key file: anonymous server authentication not supported in this release", SOAP_SSL_ERROR);
  4037. }
  4038. else
  4039. {
  4040. #if GNUTLS_VERSION_NUMBER < 0x030300
  4041. int protocol_priority[] = { 0, 0, 0, 0, 0 };
  4042. int *protocol = protocol_priority;
  4043. if ((soap->ssl_flags & SOAP_SSL_RSA) && soap->rsa_params)
  4044. gnutls_certificate_set_rsa_export_params(soap->xcred, soap->rsa_params);
  4045. #endif
  4046. if (!(soap->ssl_flags & SOAP_SSL_RSA) && soap->dh_params)
  4047. gnutls_certificate_set_dh_params(soap->xcred, soap->dh_params);
  4048. if (!soap->cache)
  4049. gnutls_priority_init(&soap->cache, "NORMAL", NULL);
  4050. gnutls_init(&soap->session, GNUTLS_SERVER);
  4051. gnutls_priority_set(soap->session, soap->cache);
  4052. gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred);
  4053. if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
  4054. gnutls_certificate_server_set_request(soap->session, GNUTLS_CERT_REQUEST);
  4055. gnutls_session_enable_compatibility_mode(soap->session);
  4056. /* enable all TSLv1 protocols and disable SSLv3 by default if no SSL/TLS flags are set */
  4057. if (!(soap->ssl_flags & SOAP_SSLv3_TLSv1))
  4058. soap->ssl_flags = SOAP_TLSv1;
  4059. #if GNUTLS_VERSION_NUMBER < 0x030300
  4060. if ((soap->ssl_flags & SOAP_SSLv3))
  4061. *protocol++ = GNUTLS_SSL3;
  4062. if ((soap->ssl_flags & SOAP_TLSv1_0))
  4063. *protocol++ = GNUTLS_TLS1_0;
  4064. if ((soap->ssl_flags & SOAP_TLSv1_1))
  4065. *protocol++ = GNUTLS_TLS1_1;
  4066. if ((soap->ssl_flags & SOAP_TLSv1_2))
  4067. *protocol++ = GNUTLS_TLS1_2;
  4068. if (gnutls_protocol_set_priority(soap->session, protocol_priority) != GNUTLS_E_SUCCESS)
  4069. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set protocol", SOAP_SSL_ERROR);
  4070. #else
  4071. soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "NORMAL:+VERS-ALL");
  4072. if (!(soap->ssl_flags & SOAP_TLSv1_0))
  4073. soap_strcat(soap->tmpbuf, sizeof(soap->tmpbuf), ":-VERS-TLS1.0");
  4074. if (!(soap->ssl_flags & SOAP_TLSv1_1))
  4075. soap_strcat(soap->tmpbuf, sizeof(soap->tmpbuf), ":-VERS-TLS1.1");
  4076. if (!(soap->ssl_flags & SOAP_TLSv1_2))
  4077. soap_strcat(soap->tmpbuf, sizeof(soap->tmpbuf), ":-VERS-TLS1.2");
  4078. if (gnutls_priority_set_direct(soap->session, soap->tmpbuf, NULL) != GNUTLS_E_SUCCESS)
  4079. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set protocol priority", SOAP_SSL_ERROR);
  4080. #endif
  4081. }
  4082. #endif
  4083. #ifdef WITH_SYSTEMSSL
  4084. if (!soap->ctx)
  4085. {
  4086. int err;
  4087. err = gsk_environment_open(&soap->ctx);
  4088. if (err == GSK_OK)
  4089. err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_SSLV2, GSK_PROTOCOL_SSLV2_OFF);
  4090. /* enable all TSLv1 protocols and disable SSLv3 by default if no SSL/TLS flags are set */
  4091. if (!(soap->ssl_flags & SOAP_SSLv3_TLSv1))
  4092. soap->ssl_flags = SOAP_TLSv1;
  4093. if (err == GSK_OK)
  4094. {
  4095. if ((soap->ssl_flags & SOAP_SSLv3))
  4096. err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_SSLV3, GSK_PROTOCOL_SSLV3_ON);
  4097. else
  4098. err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_SSLV3, GSK_PROTOCOL_SSLV3_OFF);
  4099. }
  4100. if (err == GSK_OK)
  4101. {
  4102. if ((soap->ssl_flags & SOAP_TLSv1_0))
  4103. err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_ON);
  4104. else
  4105. err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_OFF);
  4106. }
  4107. if (err == GSK_OK)
  4108. {
  4109. if ((soap->ssl_flags & SOAP_TLSv1_1))
  4110. err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_1_ON);
  4111. else
  4112. err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_1_OFF);
  4113. }
  4114. if (err == GSK_OK)
  4115. {
  4116. if ((soap->ssl_flags & SOAP_TLSv1_2))
  4117. err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_2_ON);
  4118. else
  4119. err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_2_OFF);
  4120. }
  4121. if (err == GSK_OK)
  4122. err = gsk_attribute_set_buffer(soap->ctx, GSK_KEYRING_FILE, soap->keyfile, 0); /* keyfile is a keyring .kdb file */
  4123. if (err == GSK_OK)
  4124. err = gsk_attribute_set_buffer(soap->ctx, GSK_KEYRING_PW, soap->password, 0); /* locked by password */
  4125. if (err == GSK_OK)
  4126. err = gsk_environment_init(soap->ctx);
  4127. if (err != GSK_OK)
  4128. return soap_set_receiver_error(soap, gsk_strerror(err), "SYSTEM SSL error in ssl_auth_init()", SOAP_SSL_ERROR);
  4129. }
  4130. #endif
  4131. return SOAP_OK;
  4132. }
  4133. #endif
  4134. /******************************************************************************/
  4135. #ifdef WITH_OPENSSL
  4136. static int
  4137. ssl_password(char *buf, int num, int rwflag, void *userdata)
  4138. {
  4139. (void)rwflag;
  4140. if (!buf || !userdata)
  4141. return 0;
  4142. soap_strcpy(buf, (size_t)num, (char*)userdata);
  4143. return (int)strlen(buf);
  4144. }
  4145. #endif
  4146. /******************************************************************************/
  4147. #ifdef WITH_OPENSSL
  4148. static int
  4149. ssl_verify_callback(int ok, X509_STORE_CTX *store)
  4150. {
  4151. (void)store;
  4152. #ifdef SOAP_DEBUG
  4153. if (!ok)
  4154. {
  4155. char buf[1024];
  4156. int err = X509_STORE_CTX_get_error(store);
  4157. X509 *cert = X509_STORE_CTX_get_current_cert(store);
  4158. fprintf(stderr, "\nDEBUG mode TLS/SSL warnings:\nSSL verify error %d or warning with certificate at depth %d: %s\n", err, X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(err));
  4159. X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf)-1);
  4160. fprintf(stderr, " certificate issuer: %s\n", buf);
  4161. X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)-1);
  4162. fprintf(stderr, " certificate subject: %s\n", buf);
  4163. /* accept self-signed certificates and certificates out of date */
  4164. switch (err)
  4165. {
  4166. case X509_V_ERR_CERT_NOT_YET_VALID:
  4167. case X509_V_ERR_CERT_HAS_EXPIRED:
  4168. case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
  4169. case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
  4170. case X509_V_ERR_UNABLE_TO_GET_CRL:
  4171. case X509_V_ERR_CRL_NOT_YET_VALID:
  4172. case X509_V_ERR_CRL_HAS_EXPIRED:
  4173. X509_STORE_CTX_set_error(store, X509_V_OK);
  4174. ok = 1;
  4175. fprintf(stderr, "Initialize soap_ssl_client_context with SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE to allow this verification error to pass without DEBUG mode enabled\n");
  4176. }
  4177. }
  4178. #endif
  4179. /* Note: return 1 to try to continue, but unsafe progress will be terminated by OpenSSL */
  4180. return ok;
  4181. }
  4182. #endif
  4183. /******************************************************************************/
  4184. #ifdef WITH_OPENSSL
  4185. static int
  4186. ssl_verify_callback_allow_expired_certificate(int ok, X509_STORE_CTX *store)
  4187. {
  4188. ok = ssl_verify_callback(ok, store);
  4189. if (!ok)
  4190. {
  4191. /* accept self signed certificates, expired certificates, and certficiates w/o CRL */
  4192. switch (X509_STORE_CTX_get_error(store))
  4193. {
  4194. case X509_V_ERR_CERT_NOT_YET_VALID:
  4195. case X509_V_ERR_CERT_HAS_EXPIRED:
  4196. case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
  4197. case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
  4198. case X509_V_ERR_UNABLE_TO_GET_CRL:
  4199. case X509_V_ERR_CRL_NOT_YET_VALID:
  4200. case X509_V_ERR_CRL_HAS_EXPIRED:
  4201. X509_STORE_CTX_set_error(store, X509_V_OK);
  4202. ok = 1;
  4203. }
  4204. }
  4205. /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
  4206. return ok;
  4207. }
  4208. #endif
  4209. /******************************************************************************/
  4210. #ifdef WITH_GNUTLS
  4211. static const char *
  4212. ssl_verify(struct soap *soap, const char *host)
  4213. {
  4214. unsigned int status;
  4215. const char *err = NULL;
  4216. int r = gnutls_certificate_verify_peers2(soap->session, &status);
  4217. if (r < 0)
  4218. err = "Certificate verify error";
  4219. else if ((status & GNUTLS_CERT_INVALID))
  4220. err = "The certificate is not trusted";
  4221. else if ((status & GNUTLS_CERT_SIGNER_NOT_FOUND))
  4222. err = "The certificate hasn't got a known issuer";
  4223. else if ((status & GNUTLS_CERT_REVOKED))
  4224. err = "The certificate has been revoked";
  4225. else if (gnutls_certificate_type_get(soap->session) == GNUTLS_CRT_X509)
  4226. {
  4227. gnutls_x509_crt_t cert;
  4228. const gnutls_datum_t *cert_list;
  4229. unsigned int cert_list_size;
  4230. if (gnutls_x509_crt_init(&cert) < 0)
  4231. err = "Could not get X509 certificates";
  4232. else if ((cert_list = gnutls_certificate_get_peers(soap->session, &cert_list_size)) == NULL)
  4233. err = "Could not get X509 certificates";
  4234. else if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
  4235. err = "Error parsing X509 certificate";
  4236. else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_expiration_time(cert) < time(NULL))
  4237. err = "The certificate has expired";
  4238. else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_activation_time(cert) > time(NULL))
  4239. err = "The certificate is not yet activated";
  4240. else if (host && !(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK))
  4241. {
  4242. if (!gnutls_x509_crt_check_hostname(cert, host))
  4243. err = "Certificate host name mismatch";
  4244. }
  4245. gnutls_x509_crt_deinit(cert);
  4246. }
  4247. return err;
  4248. }
  4249. #endif
  4250. /******************************************************************************/
  4251. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
  4252. #ifndef WITH_NOIO
  4253. SOAP_FMAC1
  4254. int
  4255. SOAP_FMAC2
  4256. soap_ssl_accept(struct soap *soap)
  4257. {
  4258. SOAP_SOCKET sk = soap->socket;
  4259. #ifdef WITH_OPENSSL
  4260. BIO *bio;
  4261. int err = SSL_ERROR_NONE;
  4262. int retries, r, s;
  4263. ERR_clear_error();
  4264. if (!soap_valid_socket(sk))
  4265. return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
  4266. soap->ssl_flags &= ~SOAP_SSL_CLIENT;
  4267. if (!soap->ctx && (soap->error = soap->fsslauth(soap)) != SOAP_OK)
  4268. return soap_closesock(soap);
  4269. if (!soap->ssl)
  4270. {
  4271. soap->ssl = SSL_new(soap->ctx);
  4272. if (!soap->ssl)
  4273. {
  4274. soap_closesock(soap);
  4275. return soap_set_receiver_error(soap, "SSL/TLS error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
  4276. }
  4277. }
  4278. else
  4279. {
  4280. SSL_clear(soap->ssl);
  4281. }
  4282. bio = BIO_new_socket((int)sk, BIO_NOCLOSE);
  4283. SSL_set_bio(soap->ssl, bio, bio);
  4284. /* Default timeout: 10 sec retries, 100 times 0.1 sec */
  4285. retries = 100;
  4286. if (soap->recv_timeout || soap->send_timeout)
  4287. {
  4288. int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout;
  4289. if (t > 0)
  4290. retries = 10 * t;
  4291. else if (t > -100000)
  4292. retries = 1;
  4293. else
  4294. retries = t/-100000;
  4295. }
  4296. SOAP_SOCKNONBLOCK(sk)
  4297. while ((r = SSL_accept(soap->ssl)) <= 0)
  4298. {
  4299. err = SSL_get_error(soap->ssl, r);
  4300. if (err == SSL_ERROR_WANT_ACCEPT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
  4301. {
  4302. if (err == SSL_ERROR_WANT_READ)
  4303. s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
  4304. else
  4305. s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
  4306. if (s < 0)
  4307. break;
  4308. }
  4309. else
  4310. {
  4311. soap->errnum = soap_socket_errno(sk);
  4312. break;
  4313. }
  4314. if (retries-- <= 0)
  4315. break;
  4316. }
  4317. if (!soap->recv_timeout && !soap->send_timeout)
  4318. SOAP_SOCKBLOCK(sk)
  4319. if (r <= 0)
  4320. {
  4321. soap_set_receiver_error(soap, soap_ssl_error(soap, r, err), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
  4322. return soap_closesock(soap);
  4323. }
  4324. if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
  4325. {
  4326. X509 *peer;
  4327. int err;
  4328. if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
  4329. {
  4330. soap_closesock(soap);
  4331. return soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in soap_ssl_accept()", SOAP_SSL_ERROR);
  4332. }
  4333. peer = SSL_get_peer_certificate(soap->ssl);
  4334. if (!peer)
  4335. {
  4336. soap_closesock(soap);
  4337. return soap_set_sender_error(soap, "SSL/TLS error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR);
  4338. }
  4339. X509_free(peer);
  4340. }
  4341. #endif
  4342. #ifdef WITH_GNUTLS
  4343. int retries, r, s;
  4344. if (!soap_valid_socket(sk))
  4345. return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
  4346. soap->ssl_flags &= ~SOAP_SSL_CLIENT;
  4347. if (!soap->session && (soap->error = soap->fsslauth(soap)) != SOAP_OK)
  4348. return soap_closesock(soap);
  4349. gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)sk);
  4350. /* default timeout: 10 sec retries, 100 times 0.1 sec */
  4351. retries = 100;
  4352. if (soap->recv_timeout || soap->send_timeout)
  4353. {
  4354. int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout;
  4355. if (t > 0)
  4356. retries = 10 * t;
  4357. else if (t > -100000)
  4358. retries = 1;
  4359. else
  4360. retries = t/-100000;
  4361. }
  4362. SOAP_SOCKNONBLOCK(sk)
  4363. while ((r = gnutls_handshake(soap->session)))
  4364. {
  4365. /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */
  4366. if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED)
  4367. {
  4368. if (!gnutls_record_get_direction(soap->session))
  4369. s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
  4370. else
  4371. s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
  4372. if (s < 0)
  4373. break;
  4374. }
  4375. else
  4376. {
  4377. soap->errnum = soap_socket_errno(sk);
  4378. break;
  4379. }
  4380. if (retries-- <= 0)
  4381. break;
  4382. }
  4383. if (!soap->recv_timeout && !soap->send_timeout)
  4384. SOAP_SOCKBLOCK(sk)
  4385. if (r)
  4386. {
  4387. soap_set_receiver_error(soap, soap_ssl_error(soap, r, 0), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
  4388. return soap_closesock(soap);
  4389. }
  4390. if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
  4391. {
  4392. const char *err = ssl_verify(soap, NULL);
  4393. if (err)
  4394. {
  4395. soap_closesock(soap);
  4396. return soap_set_receiver_error(soap, "SSL/TLS error", err, SOAP_SSL_ERROR);
  4397. }
  4398. }
  4399. #endif
  4400. #ifdef WITH_SYSTEMSSL
  4401. gsk_iocallback local_io = { ssl_recv, ssl_send, NULL, NULL, NULL, NULL };
  4402. int retries, r, s;
  4403. if (!soap_valid_socket(sk))
  4404. return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
  4405. soap->ssl_flags &= ~SOAP_SSL_CLIENT;
  4406. /* default timeout: 10 sec retries, 100 times 0.1 sec */
  4407. retries = 100;
  4408. if (soap->recv_timeout || soap->send_timeout)
  4409. {
  4410. int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout;
  4411. if (t > 0)
  4412. retries = 10 * t;
  4413. else if (t > -100000)
  4414. retries = 1;
  4415. else
  4416. retries = t/-100000;
  4417. }
  4418. SOAP_SOCKNONBLOCK(sk)
  4419. r = gsk_secure_socket_open(soap->ctx, &soap->ssl);
  4420. if (r == GSK_OK)
  4421. r = gsk_attribute_set_numeric_value(soap->ssl, GSK_FD, sk);
  4422. if (r == GSK_OK)
  4423. r = gsk_attribute_set_buffer(soap->ssl, GSK_KEYRING_LABEL, soap->cafile, 0);
  4424. if (r == GSK_OK)
  4425. r = gsk_attribute_set_enum(soap->ssl, GSK_SESSION_TYPE, GSK_SERVER_SESSION);
  4426. if (r == GSK_OK)
  4427. r = gsk_attribute_set_buffer(soap->ssl, GSK_V3_CIPHER_SPECS_EXPANDED, "0035002F000A", 0);
  4428. if (r == GSK_OK)
  4429. r = gsk_attribute_set_enum(soap->ssl, GSK_V3_CIPHERS, GSK_V3_CIPHERS_CHAR4);
  4430. if (r == GSK_OK)
  4431. r = gsk_attribute_set_callback(soap->ssl, GSK_IO_CALLBACK, &local_io);
  4432. if (r != GSK_OK)
  4433. return soap_set_receiver_error(soap, gsk_strerror(r), "SYSTEM SSL error in soap_ssl_accept()", SOAP_SSL_ERROR);
  4434. while ((r = gsk_secure_socket_init(soap->ssl)) != GSK_OK)
  4435. {
  4436. if (r == GSK_WOULD_BLOCK_READ || r == GSK_WOULD_BLOCK_WRITE)
  4437. {
  4438. if (r == GSK_WOULD_BLOCK_READ)
  4439. s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
  4440. else
  4441. s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
  4442. if (s < 0)
  4443. break;
  4444. }
  4445. else
  4446. {
  4447. soap->errnum = soap_socket_errno(sk);
  4448. break;
  4449. }
  4450. if (retries-- <= 0)
  4451. break;
  4452. }
  4453. if (!soap->recv_timeout && !soap->send_timeout)
  4454. SOAP_SOCKBLOCK(sk)
  4455. if (r != GSK_OK)
  4456. {
  4457. soap_set_receiver_error(soap, gsk_strerror(r), "gsk_secure_socket_init() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
  4458. return soap_closesock(soap);
  4459. }
  4460. #endif
  4461. soap->imode |= SOAP_ENC_SSL;
  4462. soap->omode |= SOAP_ENC_SSL;
  4463. return SOAP_OK;
  4464. }
  4465. #endif
  4466. #endif
  4467. /******************************************************************************\
  4468. *
  4469. * TCP/UDP [SSL/TLS] IPv4 and IPv6
  4470. *
  4471. \******************************************************************************/
  4472. #ifndef WITH_NOIO
  4473. static int
  4474. tcp_init(struct soap *soap) {
  4475. soap->errmode = 1;
  4476. #ifdef WIN32
  4477. if (tcp_done)
  4478. return 0;
  4479. else
  4480. {
  4481. WSADATA w;
  4482. if (WSAStartup(MAKEWORD(1, 1), &w))
  4483. return -1;
  4484. tcp_done = 1;
  4485. }
  4486. #endif
  4487. return 0;
  4488. }
  4489. #endif
  4490. /******************************************************************************/
  4491. #ifndef WITH_NOIO
  4492. static const char *
  4493. tcp_error(struct soap *soap) {
  4494. const char *msg = NULL;
  4495. switch (soap->errmode) {
  4496. case 0:
  4497. msg = soap_strerror(soap);
  4498. break;
  4499. case 1:
  4500. msg = "WSAStartup failed";
  4501. break;
  4502. case 2: {
  4503. #ifndef WITH_LEAN
  4504. msg = soap_code_str(h_error_codes, soap->errnum);
  4505. if (!msg)
  4506. #endif
  4507. {
  4508. (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), 37), "TCP/UDP IP error %d", soap->errnum);
  4509. msg = soap->msgbuf;
  4510. }
  4511. }
  4512. }
  4513. return msg;
  4514. }
  4515. #endif
  4516. /******************************************************************************/
  4517. #if !defined(WITH_IPV6) || defined(WITH_COOKIES)
  4518. #ifndef WITH_NOIO
  4519. static int
  4520. tcp_gethostbyname(struct soap *soap, const char *addr, struct hostent *hostent, struct in_addr *inaddr) {
  4521. #if defined(__GLIBC__) && (!_GNU_SOURCE && !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE) && defined(HAVE_GETHOSTBYNAME_R)) || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__ANDROID__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__)))
  4522. int r;
  4523. char *tmpbuf = soap->tmpbuf;
  4524. size_t tmplen = sizeof(soap->tmpbuf);
  4525. #elif (defined(_AIX43) || defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R)
  4526. struct hostent_data ht_data;
  4527. #elif defined(HAVE_GETHOSTBYNAME_R)
  4528. char *tmpbuf = soap->tmpbuf;
  4529. size_t tmplen = sizeof(soap->tmpbuf);
  4530. #endif
  4531. #ifdef VXWORKS
  4532. int hostint; /* vxWorks compatible */
  4533. #endif
  4534. if (inaddr) {
  4535. soap_int32 iadd = -1;
  4536. #ifdef AS400
  4537. iadd = inet_addr((void*)addr);
  4538. #else
  4539. iadd = inet_addr((char *) addr);
  4540. #endif
  4541. if (iadd != -1) {
  4542. if (soap_memcpy((void *) inaddr, sizeof(struct in_addr), (const void *) &iadd, sizeof(iadd)))
  4543. return soap->error = SOAP_EOM;
  4544. return SOAP_OK;
  4545. }
  4546. }
  4547. #if defined(__GLIBC__) && (!_GNU_SOURCE && !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE) && defined(HAVE_GETHOSTBYNAME_R)) || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__ANDROID__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__)))
  4548. while ((r = gethostbyname_r(addr, hostent, tmpbuf, tmplen, &hostent, &soap->errnum)) < 0) {
  4549. if (tmpbuf != soap->tmpbuf)
  4550. SOAP_FREE(soap, tmpbuf);
  4551. if (r != SOAP_ERANGE) {
  4552. hostent = NULL;
  4553. break;
  4554. }
  4555. tmplen *= 2;
  4556. tmpbuf = (char *) SOAP_MALLOC(soap, tmplen);
  4557. if (!tmpbuf)
  4558. break;
  4559. }
  4560. #elif (defined(_AIX43) || defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R)
  4561. memset((void*)&ht_data, 0, sizeof(ht_data));
  4562. if (gethostbyname_r(addr, hostent, &ht_data) < 0)
  4563. {
  4564. hostent = NULL;
  4565. soap->errnum = h_errno;
  4566. }
  4567. #elif defined(HAVE_GETHOSTBYNAME_R)
  4568. hostent = gethostbyname_r(addr, hostent, tmpbuf, tmplen, &soap->errnum);
  4569. #elif defined(VXWORKS)
  4570. /* vxWorks compatible */
  4571. /* If the DNS resolver library resolvLib has been configured in the vxWorks
  4572. * image, a query for the host IP address is sent to the DNS server, if the
  4573. * name was not found in the local host table. */
  4574. hostint = hostGetByName((char*)addr);
  4575. if (hostint == ERROR)
  4576. {
  4577. hostent = NULL;
  4578. soap->errnum = soap_errno;
  4579. }
  4580. #else
  4581. #ifdef AS400
  4582. hostent = gethostbyname((void*)addr);
  4583. #else
  4584. hostent = gethostbyname((char*)addr);
  4585. #endif
  4586. if (!hostent)
  4587. soap->errnum = h_errno;
  4588. #endif
  4589. if (!hostent) {
  4590. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n"));
  4591. return SOAP_ERR;
  4592. }
  4593. if (inaddr) {
  4594. #ifdef VXWORKS
  4595. inaddr->s_addr = hostint; /* vxWorks compatible */
  4596. #else
  4597. if (soap_memcpy((void *) inaddr, sizeof(struct in_addr), (const void *) hostent->h_addr,
  4598. (size_t) hostent->h_length)) {
  4599. #if defined(__GLIBC__) && (!_GNU_SOURCE && !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE) && defined(HAVE_GETHOSTBYNAME_R)) || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__ANDROID__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(__GNU__) || defined(__GNUC__))) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__)))
  4600. if (tmpbuf && tmpbuf != soap->tmpbuf)
  4601. SOAP_FREE(soap, tmpbuf);
  4602. #endif
  4603. return soap->error = SOAP_EOM;
  4604. }
  4605. #endif
  4606. }
  4607. #if defined(__GLIBC__) && (!_GNU_SOURCE && !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE) && defined(HAVE_GETHOSTBYNAME_R)) || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__ANDROID__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(__GNU__) || defined(__GNUC__))) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__)))
  4608. if (tmpbuf && tmpbuf != soap->tmpbuf)
  4609. SOAP_FREE(soap, tmpbuf);
  4610. #endif
  4611. return SOAP_OK;
  4612. }
  4613. #endif
  4614. #endif
  4615. /******************************************************************************/
  4616. #if !defined(WITH_IPV6)
  4617. #ifndef WITH_NOIO
  4618. static int
  4619. tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr) {
  4620. struct hostent hostent;
  4621. return tcp_gethostbyname(soap, addr, &hostent, inaddr);
  4622. }
  4623. #endif
  4624. #endif
  4625. /******************************************************************************/
  4626. #ifndef WITH_NOIO
  4627. static SOAP_SOCKET
  4628. tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port) {
  4629. #ifdef WITH_IPV6
  4630. struct addrinfo hints, *res, *ressave;
  4631. #endif
  4632. SOAP_SOCKET sk;
  4633. int err = 0;
  4634. #ifndef WITH_LEAN
  4635. int set = 1;
  4636. #endif
  4637. #if !defined(WITH_LEAN) || defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_SYSTEMSSL)
  4638. int retries;
  4639. #endif
  4640. soap->errnum = 0;
  4641. soap->errmode = 0;
  4642. if (soap_valid_socket(soap->socket)) {
  4643. if ((soap->omode & SOAP_IO_UDP) && soap->socket == soap->master) {
  4644. #ifdef IP_MULTICAST_TTL
  4645. #ifndef WITH_IPV6
  4646. soap->errmode = 2;
  4647. if (soap->fresolve(soap, host, &soap->peer.in.sin_addr)) {
  4648. soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()",
  4649. SOAP_TCP_ERROR);
  4650. soap->fclosesocket(soap, soap->socket);
  4651. return soap->socket = SOAP_INVALID_SOCKET;
  4652. }
  4653. soap->peer.in.sin_port = htons((short) port);
  4654. soap->errmode = 0;
  4655. #else
  4656. if (getaddrinfo(host, soap_int2s(soap, port), &hints, &res) || !res)
  4657. {
  4658. soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR);
  4659. soap->fclosesocket(soap, soap->socket);
  4660. return soap->socket = SOAP_INVALID_SOCKET;
  4661. }
  4662. if (soap_memcpy((void*)&soap->peer.storage, sizeof(soap->peer.storage), (const void*)res->ai_addr, res->ai_addrlen))
  4663. {
  4664. soap->error = SOAP_EOM;
  4665. soap->fclosesocket(soap, soap->socket);
  4666. freeaddrinfo(res);
  4667. return soap->socket = SOAP_INVALID_SOCKET;
  4668. }
  4669. soap->peerlen = res->ai_addrlen;
  4670. freeaddrinfo(res);
  4671. #endif
  4672. if (soap->ipv4_multicast_ttl) {
  4673. unsigned char ttl = soap->ipv4_multicast_ttl;
  4674. if (setsockopt(soap->socket, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &ttl, sizeof(ttl))) {
  4675. soap->errnum = soap_socket_errno(soap->socket);
  4676. soap_set_receiver_error(soap, tcp_error(soap),
  4677. "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR);
  4678. soap->fclosesocket(soap, soap->socket);
  4679. return soap->socket = SOAP_INVALID_SOCKET;
  4680. }
  4681. }
  4682. if (soap->ipv4_multicast_if && !soap->ipv6_multicast_if) {
  4683. if (setsockopt(soap->socket, IPPROTO_IP, IP_MULTICAST_IF, (char *) soap->ipv4_multicast_if,
  4684. sizeof(struct in_addr)))
  4685. #ifndef WINDOWS
  4686. {
  4687. soap->errnum = soap_socket_errno(soap->socket);
  4688. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()",
  4689. SOAP_TCP_ERROR);
  4690. soap->fclosesocket(soap, soap->socket);
  4691. return soap->socket = SOAP_INVALID_SOCKET;
  4692. }
  4693. #else
  4694. #ifndef IP_MULTICAST_IF
  4695. #define IP_MULTICAST_IF 2
  4696. #endif
  4697. if (setsockopt(soap->socket, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
  4698. {
  4699. soap->errnum = soap_socket_errno(soap->socket);
  4700. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
  4701. soap->fclosesocket(soap, soap->socket);
  4702. return soap->socket = SOAP_INVALID_SOCKET;
  4703. }
  4704. #endif
  4705. }
  4706. #endif
  4707. return soap->socket;
  4708. }
  4709. soap->fclosesocket(soap, soap->socket);
  4710. soap->socket = SOAP_INVALID_SOCKET;
  4711. }
  4712. if (tcp_init(soap)) {
  4713. soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR);
  4714. return SOAP_INVALID_SOCKET;
  4715. }
  4716. soap->errmode = 0;
  4717. #ifdef WITH_IPV6
  4718. memset((void*)&hints, 0, sizeof(hints));
  4719. hints.ai_family = PF_UNSPEC;
  4720. #ifndef WITH_LEAN
  4721. if ((soap->omode & SOAP_IO_UDP))
  4722. hints.ai_socktype = SOCK_DGRAM;
  4723. else
  4724. #endif
  4725. hints.ai_socktype = SOCK_STREAM;
  4726. soap->errmode = 2;
  4727. if (soap->proxy_host)
  4728. err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res);
  4729. else
  4730. err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res);
  4731. if (err || !res)
  4732. {
  4733. soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR);
  4734. return SOAP_INVALID_SOCKET;
  4735. }
  4736. ressave = res;
  4737. again:
  4738. sk = soap->socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
  4739. soap->error = SOAP_OK;
  4740. soap->errmode = 0;
  4741. #else
  4742. #ifndef WITH_LEAN
  4743. again:
  4744. #endif
  4745. #ifndef WITH_LEAN
  4746. if ((soap->omode & SOAP_IO_UDP))
  4747. sk = soap->socket = socket(AF_INET, SOCK_DGRAM, 0);
  4748. else
  4749. #endif
  4750. sk = soap->socket = socket(AF_INET, SOCK_STREAM, 0);
  4751. #endif
  4752. if (!soap_valid_socket(sk)) {
  4753. #ifdef WITH_IPV6
  4754. if (res->ai_next)
  4755. {
  4756. res = res->ai_next;
  4757. goto again;
  4758. }
  4759. #endif
  4760. soap->errnum = soap_socket_errno(sk);
  4761. soap_set_receiver_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR);
  4762. #ifdef WITH_IPV6
  4763. freeaddrinfo(ressave);
  4764. #endif
  4765. return SOAP_INVALID_SOCKET;
  4766. }
  4767. #ifdef WITH_SOCKET_CLOSE_ON_EXIT
  4768. #ifdef WIN32
  4769. #ifndef UNDER_CE
  4770. SetHandleInformation((HANDLE)sk, HANDLE_FLAG_INHERIT, 0);
  4771. #endif
  4772. #else
  4773. fcntl(sk, F_SETFD, 1);
  4774. #endif
  4775. #endif
  4776. #ifndef WITH_LEAN
  4777. if ((soap->connect_flags & SO_LINGER)) {
  4778. struct linger linger;
  4779. memset((void *) &linger, 0, sizeof(linger));
  4780. linger.l_onoff = 1;
  4781. linger.l_linger = soap->linger_time;
  4782. if (setsockopt(sk, SOL_SOCKET, SO_LINGER, (char *) &linger, sizeof(struct linger))) {
  4783. soap->errnum = soap_socket_errno(sk);
  4784. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()",
  4785. SOAP_TCP_ERROR);
  4786. soap->fclosesocket(soap, sk);
  4787. #ifdef WITH_IPV6
  4788. freeaddrinfo(ressave);
  4789. #endif
  4790. return soap->socket = SOAP_INVALID_SOCKET;
  4791. }
  4792. }
  4793. if ((soap->connect_flags & ~SO_LINGER) &&
  4794. setsockopt(sk, SOL_SOCKET, soap->connect_flags & ~SO_LINGER, (char *) &set, sizeof(int))) {
  4795. soap->errnum = soap_socket_errno(sk);
  4796. #ifdef WITH_IPV6
  4797. freeaddrinfo(ressave);
  4798. #endif
  4799. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR);
  4800. soap->fclosesocket(soap, sk);
  4801. return soap->socket = SOAP_INVALID_SOCKET;
  4802. }
  4803. #ifndef UNDER_CE
  4804. if ((soap->keep_alive || soap->tcp_keep_alive) &&
  4805. setsockopt(sk, SOL_SOCKET, SO_KEEPALIVE, (char *) &set, sizeof(int))) {
  4806. soap->errnum = soap_socket_errno(sk);
  4807. #ifdef WITH_IPV6
  4808. freeaddrinfo(ressave);
  4809. #endif
  4810. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()",
  4811. SOAP_TCP_ERROR);
  4812. soap->fclosesocket(soap, sk);
  4813. return soap->socket = SOAP_INVALID_SOCKET;
  4814. }
  4815. if (soap->sndbuf > 0 && setsockopt(sk, SOL_SOCKET, SO_SNDBUF, (char *) &soap->sndbuf, sizeof(int))) {
  4816. soap->errnum = soap_socket_errno(sk);
  4817. #ifdef WITH_IPV6
  4818. freeaddrinfo(ressave);
  4819. #endif
  4820. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR);
  4821. soap->fclosesocket(soap, sk);
  4822. return soap->socket = SOAP_INVALID_SOCKET;
  4823. }
  4824. if (soap->rcvbuf > 0 && setsockopt(sk, SOL_SOCKET, SO_RCVBUF, (char *) &soap->rcvbuf, sizeof(int))) {
  4825. soap->errnum = soap_socket_errno(sk);
  4826. #ifdef WITH_IPV6
  4827. freeaddrinfo(ressave);
  4828. #endif
  4829. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR);
  4830. soap->fclosesocket(soap, sk);
  4831. return soap->socket = SOAP_INVALID_SOCKET;
  4832. }
  4833. #ifdef TCP_KEEPIDLE
  4834. if (soap->tcp_keep_idle &&
  4835. setsockopt(sk, IPPROTO_TCP, TCP_KEEPIDLE, (char *) &(soap->tcp_keep_idle), sizeof(int))) {
  4836. soap->errnum = soap_socket_errno(sk);
  4837. #ifdef WITH_IPV6
  4838. freeaddrinfo(ressave);
  4839. #endif
  4840. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_KEEPIDLE failed in tcp_connect()",
  4841. SOAP_TCP_ERROR);
  4842. soap->fclosesocket(soap, sk);
  4843. return soap->socket = SOAP_INVALID_SOCKET;
  4844. }
  4845. #endif
  4846. #ifdef TCP_KEEPINTVL
  4847. if (soap->tcp_keep_intvl &&
  4848. setsockopt(sk, IPPROTO_TCP, TCP_KEEPINTVL, (char *) &(soap->tcp_keep_intvl), sizeof(int))) {
  4849. soap->errnum = soap_socket_errno(sk);
  4850. #ifdef WITH_IPV6
  4851. freeaddrinfo(ressave);
  4852. #endif
  4853. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_KEEPINTVL failed in tcp_connect()",
  4854. SOAP_TCP_ERROR);
  4855. soap->fclosesocket(soap, sk);
  4856. return soap->socket = SOAP_INVALID_SOCKET;
  4857. }
  4858. #endif
  4859. #ifdef TCP_KEEPCNT
  4860. if (soap->tcp_keep_cnt && setsockopt(sk, IPPROTO_TCP, TCP_KEEPCNT, (char *) &(soap->tcp_keep_cnt), sizeof(int))) {
  4861. soap->errnum = soap_socket_errno(sk);
  4862. #ifdef WITH_IPV6
  4863. freeaddrinfo(ressave);
  4864. #endif
  4865. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_KEEPCNT failed in tcp_connect()",
  4866. SOAP_TCP_ERROR);
  4867. soap->fclosesocket(soap, sk);
  4868. return soap->socket = SOAP_INVALID_SOCKET;
  4869. }
  4870. #endif
  4871. #ifdef TCP_NODELAY
  4872. if (!(soap->omode & SOAP_IO_UDP) && setsockopt(sk, IPPROTO_TCP, TCP_NODELAY, (char *) &set, sizeof(int))) {
  4873. soap->errnum = soap_socket_errno(sk);
  4874. #ifdef WITH_IPV6
  4875. freeaddrinfo(ressave);
  4876. #endif
  4877. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()",
  4878. SOAP_TCP_ERROR);
  4879. soap->fclosesocket(soap, sk);
  4880. return soap->socket = SOAP_INVALID_SOCKET;
  4881. }
  4882. #endif
  4883. #ifdef WITH_IPV6
  4884. if ((soap->omode & SOAP_IO_UDP) && soap->ipv6_multicast_if)
  4885. {
  4886. struct sockaddr_in6 *in6addr = (struct sockaddr_in6*)res->ai_addr;
  4887. in6addr->sin6_scope_id = soap->ipv6_multicast_if;
  4888. }
  4889. #endif
  4890. #endif
  4891. #ifdef IP_MULTICAST_TTL
  4892. if ((soap->omode & SOAP_IO_UDP)) {
  4893. if (soap->ipv4_multicast_ttl) {
  4894. unsigned char ttl = soap->ipv4_multicast_ttl;
  4895. if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &ttl, sizeof(ttl))) {
  4896. soap->errnum = soap_socket_errno(sk);
  4897. #ifdef WITH_IPV6
  4898. freeaddrinfo(ressave);
  4899. #endif
  4900. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()",
  4901. SOAP_TCP_ERROR);
  4902. soap->fclosesocket(soap, sk);
  4903. return soap->socket = SOAP_INVALID_SOCKET;
  4904. }
  4905. }
  4906. if ((soap->omode & SOAP_IO_UDP) && soap->ipv4_multicast_if && !soap->ipv6_multicast_if) {
  4907. if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_IF, (char *) soap->ipv4_multicast_if, sizeof(struct in_addr)))
  4908. #ifndef WINDOWS
  4909. {
  4910. soap->errnum = soap_socket_errno(sk);
  4911. #ifdef WITH_IPV6
  4912. freeaddrinfo(ressave);
  4913. #endif
  4914. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()",
  4915. SOAP_TCP_ERROR);
  4916. soap->fclosesocket(soap, sk);
  4917. return soap->socket = SOAP_INVALID_SOCKET;
  4918. }
  4919. #else
  4920. #ifndef IP_MULTICAST_IF
  4921. #define IP_MULTICAST_IF 2
  4922. #endif
  4923. if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
  4924. {
  4925. soap->errnum = soap_socket_errno(sk);
  4926. #ifdef WITH_IPV6
  4927. freeaddrinfo(ressave);
  4928. #endif
  4929. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
  4930. soap->fclosesocket(soap, sk);
  4931. return soap->socket = SOAP_INVALID_SOCKET;
  4932. }
  4933. #endif
  4934. }
  4935. }
  4936. #endif
  4937. #endif
  4938. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Opening socket=%d to host='%s' port=%d\n", (int) sk, host, port));
  4939. #ifndef WITH_IPV6
  4940. soap->peerlen = sizeof(soap->peer.in);
  4941. memset((void *) &soap->peer.in, 0, sizeof(soap->peer.in));
  4942. soap->peer.in.sin_family = AF_INET;
  4943. if (soap->client_port >= 0) {
  4944. struct sockaddr_in addr;
  4945. memset((void *) &addr, 0, sizeof(addr));
  4946. addr.sin_family = AF_INET;
  4947. addr.sin_port = htons(soap->client_port);
  4948. if (bind(sk, (struct sockaddr *) &addr, sizeof(addr))) {
  4949. soap->errnum = soap_socket_errno(sk);
  4950. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind before connect\n"));
  4951. soap_set_receiver_error(soap, tcp_error(soap), "bind failed in tcp_connect()", SOAP_TCP_ERROR);
  4952. soap->fclosesocket(soap, sk);
  4953. soap->client_port = -1;
  4954. return soap->socket = SOAP_INVALID_SOCKET;
  4955. }
  4956. soap->client_port = -1; /* disable bind before connect, so need to set it again before the next connect */
  4957. }
  4958. #ifndef WIN32
  4959. if (soap->client_interface) {
  4960. if (inet_pton(AF_INET, soap->client_interface, &soap->peer.in.sin_addr) != 1) {
  4961. soap->errnum = soap_socket_errno(sk);
  4962. soap_set_receiver_error(soap, tcp_error(soap), "inet_pton() failed in tcp_connect()", SOAP_TCP_ERROR);
  4963. soap->fclosesocket(soap, sk);
  4964. soap->client_interface = NULL;
  4965. return soap->socket = SOAP_INVALID_SOCKET;
  4966. }
  4967. soap->client_interface = NULL; /* disable client interface, so need to set it again before the next connect */
  4968. }
  4969. #endif
  4970. soap->errmode = 2;
  4971. if (soap->proxy_host) {
  4972. if (soap->fresolve(soap, soap->proxy_host, &soap->peer.in.sin_addr)) {
  4973. soap_set_receiver_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()",
  4974. SOAP_TCP_ERROR);
  4975. soap->fclosesocket(soap, sk);
  4976. return soap->socket = SOAP_INVALID_SOCKET;
  4977. }
  4978. soap->peer.in.sin_port = htons((short) soap->proxy_port);
  4979. } else {
  4980. if (soap->fresolve(soap, host, &soap->peer.in.sin_addr)) {
  4981. soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR);
  4982. soap->fclosesocket(soap, sk);
  4983. return soap->socket = SOAP_INVALID_SOCKET;
  4984. }
  4985. soap->peer.in.sin_port = htons((short) port);
  4986. }
  4987. soap->errmode = 0;
  4988. #ifndef WITH_LEAN
  4989. if ((soap->omode & SOAP_IO_UDP))
  4990. return sk;
  4991. #endif
  4992. #else
  4993. if (soap->client_port >= 0)
  4994. {
  4995. struct sockaddr_in6 addr;
  4996. memset((void*)&addr, 0, sizeof(addr));
  4997. addr.sin6_family = AF_INET6;
  4998. addr.sin6_port = htons(soap->client_port);
  4999. if (bind(sk, (struct sockaddr*)&addr, sizeof(addr)))
  5000. {
  5001. soap->errnum = soap_socket_errno(sk);
  5002. freeaddrinfo(ressave);
  5003. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind before connect\n"));
  5004. soap_set_receiver_error(soap, tcp_error(soap), "bind failed in tcp_connect()", SOAP_TCP_ERROR);
  5005. soap->fclosesocket(soap, sk);
  5006. soap->client_port = -1;
  5007. return soap->socket = SOAP_INVALID_SOCKET;
  5008. }
  5009. soap->client_port = -1; /* disable bind before connect, so need to set t again before the next connect */
  5010. }
  5011. if (soap->client_interface)
  5012. {
  5013. if (inet_pton(AF_INET6, soap->client_interface, res->ai_addr) != 1)
  5014. {
  5015. if (inet_pton(AF_INET, soap->client_interface, res->ai_addr) != 1)
  5016. {
  5017. soap->errnum = soap_socket_errno(sk);
  5018. freeaddrinfo(ressave);
  5019. soap_set_receiver_error(soap, tcp_error(soap), "inet_pton() failed in tcp_connect()", SOAP_TCP_ERROR);
  5020. soap->fclosesocket(soap, sk);
  5021. soap->client_interface = NULL;
  5022. return soap->socket = SOAP_INVALID_SOCKET;
  5023. }
  5024. }
  5025. soap->client_interface = NULL; /* disable client interface, so need to set it again before the next connect */
  5026. }
  5027. #ifndef WITH_LEAN
  5028. if ((soap->omode & SOAP_IO_UDP))
  5029. {
  5030. if (soap_memcpy((void*)&soap->peer.storage, sizeof(soap->peer.storage), (const void*)res->ai_addr, res->ai_addrlen))
  5031. {
  5032. soap->error = SOAP_EOM;
  5033. soap->fclosesocket(soap, sk);
  5034. soap->socket = sk = SOAP_INVALID_SOCKET;
  5035. }
  5036. soap->peerlen = res->ai_addrlen;
  5037. freeaddrinfo(ressave);
  5038. return sk;
  5039. }
  5040. #endif
  5041. #endif
  5042. #ifndef WITH_LEAN
  5043. if (soap->connect_timeout)
  5044. SOAP_SOCKNONBLOCK(sk)
  5045. else
  5046. SOAP_SOCKBLOCK(sk)
  5047. retries = 10;
  5048. #endif
  5049. for (;;) {
  5050. #ifdef WITH_IPV6
  5051. if (connect(sk, res->ai_addr, (int)res->ai_addrlen))
  5052. #else
  5053. if (connect(sk, &soap->peer.addr, sizeof(soap->peer.in)))
  5054. #endif
  5055. {
  5056. err = soap_socket_errno(sk);
  5057. #ifdef WITH_IPV6
  5058. if (err == SOAP_ECONNREFUSED && res->ai_next)
  5059. {
  5060. soap->fclosesocket(soap, sk);
  5061. res = res->ai_next;
  5062. goto again;
  5063. }
  5064. #endif
  5065. #ifndef WITH_LEAN
  5066. if (err == SOAP_EADDRINUSE) {
  5067. soap->fclosesocket(soap, sk);
  5068. if (retries-- > 0)
  5069. goto again;
  5070. } else if (soap->connect_timeout &&
  5071. (err == SOAP_EINPROGRESS || err == SOAP_EAGAIN || err == SOAP_EWOULDBLOCK)) {
  5072. SOAP_SOCKLEN_T k;
  5073. for (;;) {
  5074. int r;
  5075. #ifdef WITH_SELF_PIPE
  5076. r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_PIP, soap->connect_timeout);
  5077. if ((r & SOAP_TCP_SELECT_PIP))
  5078. {
  5079. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection closed by self pipe\n"));
  5080. soap->fclosesocket(soap, sk);
  5081. return soap->socket = SOAP_INVALID_SOCKET;
  5082. }
  5083. #else
  5084. r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND, soap->connect_timeout);
  5085. #endif
  5086. if (r > 0)
  5087. break;
  5088. if (!r) {
  5089. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
  5090. soap_set_receiver_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR);
  5091. soap->fclosesocket(soap, sk);
  5092. #ifdef WITH_IPV6
  5093. if (res->ai_next)
  5094. {
  5095. res = res->ai_next;
  5096. goto again;
  5097. }
  5098. freeaddrinfo(ressave);
  5099. #endif
  5100. return soap->socket = SOAP_INVALID_SOCKET;
  5101. }
  5102. r = soap->errnum = soap_socket_errno(sk);
  5103. if (r != SOAP_EINTR) {
  5104. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
  5105. soap_set_receiver_error(soap, tcp_error(soap), "connect failed in tcp_connect()",
  5106. SOAP_TCP_ERROR);
  5107. soap->fclosesocket(soap, sk);
  5108. #ifdef WITH_IPV6
  5109. if (res->ai_next)
  5110. {
  5111. res = res->ai_next;
  5112. goto again;
  5113. }
  5114. freeaddrinfo(ressave);
  5115. #endif
  5116. return soap->socket = SOAP_INVALID_SOCKET;
  5117. }
  5118. }
  5119. k = (SOAP_SOCKLEN_T) sizeof(soap->errnum);
  5120. if (!getsockopt(sk, SOL_SOCKET, SO_ERROR, (char *) &soap->errnum, &k) &&
  5121. !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
  5122. break;
  5123. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
  5124. if (!soap->errnum)
  5125. soap->errnum = soap_socket_errno(sk);
  5126. soap_set_receiver_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
  5127. soap->fclosesocket(soap, sk);
  5128. #ifdef WITH_IPV6
  5129. if (res->ai_next)
  5130. {
  5131. res = res->ai_next;
  5132. goto again;
  5133. }
  5134. freeaddrinfo(ressave);
  5135. #endif
  5136. return soap->socket = SOAP_INVALID_SOCKET;
  5137. }
  5138. #endif
  5139. #ifdef WITH_IPV6
  5140. if (res->ai_next)
  5141. {
  5142. res = res->ai_next;
  5143. soap->fclosesocket(soap, sk);
  5144. goto again;
  5145. }
  5146. #endif
  5147. if (err && err != SOAP_EINTR) {
  5148. soap->errnum = err;
  5149. #ifdef WITH_IPV6
  5150. freeaddrinfo(ressave);
  5151. #endif
  5152. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
  5153. soap_set_receiver_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
  5154. soap->fclosesocket(soap, sk);
  5155. return soap->socket = SOAP_INVALID_SOCKET;
  5156. }
  5157. } else {
  5158. break;
  5159. }
  5160. }
  5161. #ifdef WITH_IPV6
  5162. soap->peerlen = 0; /* IPv6: already connected so use send() */
  5163. freeaddrinfo(ressave);
  5164. #endif
  5165. soap->imode &= ~SOAP_ENC_SSL;
  5166. soap->omode &= ~SOAP_ENC_SSL;
  5167. if (endpoint && !soap_tag_cmp(endpoint, "https:*")) {
  5168. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_SYSTEMSSL)
  5169. #ifdef WITH_OPENSSL
  5170. BIO *bio;
  5171. #endif
  5172. #ifdef WITH_SYSTEMSSL
  5173. gsk_iocallback local_io = { ssl_recv, ssl_send, NULL, NULL, NULL, NULL };
  5174. #endif
  5175. int r;
  5176. if (soap->proxy_host)
  5177. {
  5178. soap_mode m = soap->mode; /* preserve settings */
  5179. soap_mode om = soap->omode; /* make sure we only parse HTTP */
  5180. ULONG64 n = soap->count; /* save the content length */
  5181. const char *userid, *passwd;
  5182. int status = soap->status; /* save the current status/command */
  5183. int keep_alive = soap->keep_alive; /* save the KA status */
  5184. soap->omode &= ~SOAP_ENC; /* mask IO and ENC */
  5185. soap->omode |= SOAP_IO_BUFFER;
  5186. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to %s proxy server %s for destination endpoint %s\n", soap->proxy_http_version, soap->proxy_host, endpoint));
  5187. #ifdef WITH_NTLM
  5188. if (soap->ntlm_challenge && soap_ntlm_handshake(soap, SOAP_CONNECT, endpoint, host, port))
  5189. {
  5190. soap->fclosesocket(soap, sk);
  5191. return soap->socket = SOAP_INVALID_SOCKET;
  5192. }
  5193. #endif
  5194. if (soap_init_send(soap))
  5195. {
  5196. soap->fclosesocket(soap, sk);
  5197. return soap->socket = SOAP_INVALID_SOCKET;
  5198. }
  5199. soap->status = SOAP_CONNECT;
  5200. if (!soap->keep_alive)
  5201. soap->keep_alive = -1; /* must keep alive */
  5202. soap->error = soap->fpost(soap, endpoint, host, port, NULL, NULL, 0);
  5203. if (soap->error
  5204. || soap_end_send_flush(soap))
  5205. {
  5206. soap->fclosesocket(soap, sk);
  5207. return soap->socket = SOAP_INVALID_SOCKET;
  5208. }
  5209. soap->keep_alive = keep_alive;
  5210. soap->omode = om;
  5211. om = soap->imode;
  5212. soap->imode &= ~SOAP_ENC; /* mask IO and ENC */
  5213. userid = soap->userid; /* preserve */
  5214. passwd = soap->passwd; /* preserve */
  5215. soap->error = soap->fparse(soap);
  5216. if (soap->error)
  5217. {
  5218. soap->fclosesocket(soap, sk);
  5219. return soap->socket = SOAP_INVALID_SOCKET;
  5220. }
  5221. soap->status = status; /* restore */
  5222. soap->userid = userid; /* restore */
  5223. soap->passwd = passwd; /* restore */
  5224. soap->imode = om; /* restore */
  5225. soap->count = n; /* restore */
  5226. if (soap_init_send(soap))
  5227. {
  5228. soap->fclosesocket(soap, sk);
  5229. return soap->socket = SOAP_INVALID_SOCKET;
  5230. }
  5231. if (endpoint)
  5232. soap_strcpy(soap->endpoint, sizeof(soap->endpoint), endpoint); /* restore */
  5233. soap->mode = m;
  5234. }
  5235. #ifdef WITH_OPENSSL
  5236. ERR_clear_error();
  5237. soap->ssl_flags |= SOAP_SSL_CLIENT;
  5238. if (!soap->ctx && (soap->error = soap->fsslauth(soap)) != SOAP_OK)
  5239. {
  5240. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL required, but no ctx set\n"));
  5241. soap->fclosesocket(soap, sk);
  5242. soap->error = SOAP_SSL_ERROR;
  5243. return soap->socket = SOAP_INVALID_SOCKET;
  5244. }
  5245. if (!soap->ssl)
  5246. {
  5247. soap->ssl = SSL_new(soap->ctx);
  5248. if (!soap->ssl)
  5249. {
  5250. soap->fclosesocket(soap, sk);
  5251. soap->error = SOAP_SSL_ERROR;
  5252. return soap->socket = SOAP_INVALID_SOCKET;
  5253. }
  5254. }
  5255. else
  5256. {
  5257. SSL_clear(soap->ssl);
  5258. }
  5259. if (soap->session)
  5260. {
  5261. if (!strcmp(soap->session_host, host) && soap->session_port == port)
  5262. SSL_set_session(soap->ssl, soap->session);
  5263. SSL_SESSION_free(soap->session);
  5264. soap->session = NULL;
  5265. }
  5266. #if OPENSSL_VERSION_NUMBER >= 0x1000000aL
  5267. if (!(soap->ssl_flags & SOAP_SSLv3) && !SSL_set_tlsext_host_name(soap->ssl, host))
  5268. {
  5269. soap_set_receiver_error(soap, "SSL/TLS error", "SNI failed", SOAP_SSL_ERROR);
  5270. soap->fclosesocket(soap, sk);
  5271. return soap->socket = SOAP_INVALID_SOCKET;
  5272. }
  5273. #elif (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && defined(SSL_CTRL_SET_TLSEXT_HOSTNAME)
  5274. if (!SSL_ctrl(soap->ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, (void*)host))
  5275. {
  5276. soap_set_receiver_error(soap, "SSL/TLS error", "SNI failed", SOAP_SSL_ERROR);
  5277. soap->fclosesocket(soap, sk);
  5278. return soap->socket = SOAP_INVALID_SOCKET;
  5279. }
  5280. #endif
  5281. bio = BIO_new_socket((int)sk, BIO_NOCLOSE);
  5282. SSL_set_bio(soap->ssl, bio, bio);
  5283. if (soap->connect_timeout || soap->recv_timeout || soap->send_timeout)
  5284. {
  5285. /* Set SSL connect timeout and set SSL sockets to non-blocking */
  5286. int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout;
  5287. if (soap->connect_timeout > 0 && t < soap->connect_timeout)
  5288. t = soap->connect_timeout;
  5289. if (t > 0)
  5290. retries = 10 * t;
  5291. else if (t > -100000)
  5292. retries = 1;
  5293. else
  5294. retries = t/-100000;
  5295. SOAP_SOCKNONBLOCK(sk)
  5296. }
  5297. else
  5298. {
  5299. /* Set sockets to blocking */
  5300. retries = 1;
  5301. SOAP_SOCKBLOCK(sk)
  5302. }
  5303. err = SSL_ERROR_NONE;
  5304. /* Try connecting until success or timeout */
  5305. do
  5306. {
  5307. if ((r = SSL_connect(soap->ssl)) <= 0)
  5308. {
  5309. err = SSL_get_error(soap->ssl, r);
  5310. if (err == SSL_ERROR_WANT_CONNECT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
  5311. {
  5312. int s;
  5313. if (err == SSL_ERROR_WANT_READ)
  5314. s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
  5315. else
  5316. s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
  5317. if (s < 0)
  5318. break;
  5319. if (s == 0 && retries-- <= 0)
  5320. {
  5321. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL/TLS connect timeout\n"));
  5322. soap_set_receiver_error(soap, "Timeout", "SSL_connect() failed in tcp_connect()", SOAP_TCP_ERROR);
  5323. soap->fclosesocket(soap, sk);
  5324. return soap->socket = SOAP_INVALID_SOCKET;
  5325. }
  5326. }
  5327. else
  5328. {
  5329. soap->errnum = soap_socket_errno(sk);
  5330. break;
  5331. }
  5332. }
  5333. } while (!SSL_is_init_finished(soap->ssl));
  5334. if (r <= 0)
  5335. {
  5336. soap_set_sender_error(soap, soap_ssl_error(soap, r, err), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
  5337. soap->fclosesocket(soap, sk);
  5338. return soap->socket = SOAP_INVALID_SOCKET;
  5339. }
  5340. /* Check server credentials when required */
  5341. if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
  5342. {
  5343. if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
  5344. {
  5345. soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL/TLS certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR);
  5346. soap->fclosesocket(soap, sk);
  5347. return soap->socket = SOAP_INVALID_SOCKET;
  5348. }
  5349. if (!(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK))
  5350. {
  5351. X509_NAME *subj;
  5352. STACK_OF(CONF_VALUE) *val = NULL;
  5353. #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
  5354. GENERAL_NAMES *names = NULL;
  5355. #else
  5356. int ext_count;
  5357. #endif
  5358. int ok = 0;
  5359. X509 *peer = SSL_get_peer_certificate(soap->ssl);
  5360. if (!peer)
  5361. {
  5362. soap_set_sender_error(soap, "SSL/TLS error", "No SSL/TLS certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR);
  5363. soap->fclosesocket(soap, sk);
  5364. return soap->socket = SOAP_INVALID_SOCKET;
  5365. }
  5366. #if OPENSSL_VERSION_NUMBER < 0x0090800fL
  5367. ext_count = X509_get_ext_count(peer);
  5368. if (ext_count > 0)
  5369. {
  5370. int i;
  5371. for (i = 0; i < ext_count; i++)
  5372. {
  5373. X509_EXTENSION *ext = X509_get_ext(peer, i);
  5374. const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
  5375. if (ext_str && !strcmp(ext_str, "subjectAltName"))
  5376. {
  5377. X509V3_EXT_METHOD *meth = (X509V3_EXT_METHOD*)X509V3_EXT_get(ext);
  5378. unsigned char *data;
  5379. if (!meth)
  5380. break;
  5381. data = ext->value->data;
  5382. if (data)
  5383. {
  5384. #if OPENSSL_VERSION_NUMBER > 0x00907000L
  5385. void *ext_data;
  5386. if (meth->it)
  5387. ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it));
  5388. else
  5389. {
  5390. #if OPENSSL_VERSION_NUMBER > 0x0090800fL
  5391. ext_data = meth->d2i(NULL, (const unsigned char **)&data, ext->value->length);
  5392. #else
  5393. ext_data = meth->d2i(NULL, &data, ext->value->length);
  5394. #endif
  5395. }
  5396. if (ext_data)
  5397. val = meth->i2v(meth, ext_data, NULL);
  5398. else
  5399. val = NULL;
  5400. if (meth->it)
  5401. ASN1_item_free((ASN1_VALUE*)ext_data, ASN1_ITEM_ptr(meth->it));
  5402. else
  5403. meth->ext_free(ext_data);
  5404. #else
  5405. void *ext_data = meth->d2i(NULL, &data, ext->value->length);
  5406. if (ext_data)
  5407. val = meth->i2v(meth, ext_data, NULL);
  5408. meth->ext_free(ext_data);
  5409. #endif
  5410. if (val)
  5411. {
  5412. int j;
  5413. for (j = 0; j < sk_CONF_VALUE_num(val); j++)
  5414. {
  5415. CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
  5416. if (nval && (!strcmp(nval->name, "DNS") || !strcmp(nval->name, "IP Address")) && !soap_tag_cmp(host, nval->value))
  5417. {
  5418. ok = 1;
  5419. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate %s %s\n", host, nval->name, nval->value));
  5420. break;
  5421. }
  5422. else
  5423. {
  5424. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s mismatch with certificate %s %s\n", host, nval->name, nval->value));
  5425. }
  5426. }
  5427. sk_CONF_VALUE_pop_free(val, X509V3_conf_free);
  5428. }
  5429. }
  5430. }
  5431. if (ok)
  5432. break;
  5433. }
  5434. }
  5435. #else
  5436. names = (GENERAL_NAMES*)X509_get_ext_d2i(peer, NID_subject_alt_name, NULL, NULL);
  5437. if (names)
  5438. {
  5439. val = i2v_GENERAL_NAMES(NULL, names, val);
  5440. sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
  5441. }
  5442. if (val)
  5443. {
  5444. int j;
  5445. for (j = 0; j < sk_CONF_VALUE_num(val); j++)
  5446. {
  5447. CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
  5448. if (nval && (!strcmp(nval->name, "DNS") || !strcmp(nval->name, "IP Address")) && !soap_tag_cmp(host, nval->value))
  5449. {
  5450. ok = 1;
  5451. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate %s %s\n", host, nval->name, nval->value));
  5452. break;
  5453. }
  5454. else
  5455. {
  5456. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s mismatch with certificate %s %s\n", host, nval->name, nval->value));
  5457. }
  5458. }
  5459. sk_CONF_VALUE_pop_free(val, X509V3_conf_free);
  5460. }
  5461. #endif
  5462. if (!ok && (subj = X509_get_subject_name(peer)) != 0)
  5463. {
  5464. int i = -1;
  5465. do
  5466. {
  5467. ASN1_STRING *name;
  5468. i = X509_NAME_get_index_by_NID(subj, NID_commonName, i);
  5469. if (i == -1)
  5470. break;
  5471. name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i));
  5472. if (name)
  5473. {
  5474. #if OPENSSL_VERSION_NUMBER < 0x10100000L
  5475. const char *tmp = (const char*)ASN1_STRING_data(name);
  5476. #else
  5477. const char *tmp = (const char*)ASN1_STRING_get0_data(name);
  5478. #endif
  5479. if (!soap_tag_cmp(host, tmp))
  5480. {
  5481. ok = 1;
  5482. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate subject %s\n", host, tmp));
  5483. }
  5484. else
  5485. {
  5486. unsigned char *tmp = NULL;
  5487. ASN1_STRING_to_UTF8(&tmp, name);
  5488. if (tmp)
  5489. {
  5490. if (!soap_tag_cmp(host, (const char*)tmp))
  5491. {
  5492. ok = 1;
  5493. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate subject %s\n", host, tmp));
  5494. }
  5495. else if (tmp[0] == '*') /* wildcard domain */
  5496. {
  5497. const char *t = strchr(host, '.');
  5498. if (t && !soap_tag_cmp(t, (const char*)tmp + 1))
  5499. {
  5500. ok = 1;
  5501. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate subject %s\n", host, tmp));
  5502. }
  5503. }
  5504. else
  5505. {
  5506. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s mismatch with certificate %s\n", host, tmp));
  5507. }
  5508. OPENSSL_free(tmp);
  5509. }
  5510. }
  5511. }
  5512. } while (!ok);
  5513. }
  5514. X509_free(peer);
  5515. if (!ok)
  5516. {
  5517. soap_set_sender_error(soap, "SSL/TLS error", "SSL/TLS certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR);
  5518. soap->fclosesocket(soap, sk);
  5519. return soap->socket = SOAP_INVALID_SOCKET;
  5520. }
  5521. }
  5522. }
  5523. #endif
  5524. #ifdef WITH_GNUTLS
  5525. soap->ssl_flags |= SOAP_SSL_CLIENT;
  5526. if (!soap->session && (soap->error = soap->fsslauth(soap)) != SOAP_OK)
  5527. {
  5528. soap->fclosesocket(soap, sk);
  5529. return soap->socket = SOAP_INVALID_SOCKET;
  5530. }
  5531. gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)sk);
  5532. if (soap->connect_timeout || soap->recv_timeout || soap->send_timeout)
  5533. {
  5534. /* Set SSL connect timeout and set SSL sockets to non-blocking */
  5535. int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout;
  5536. if (soap->connect_timeout > 0 && t < soap->connect_timeout)
  5537. t = soap->connect_timeout;
  5538. if (t > 0)
  5539. retries = 10 * t;
  5540. else if (t > -100000)
  5541. retries = 1;
  5542. else
  5543. retries = t/-100000;
  5544. SOAP_SOCKNONBLOCK(sk)
  5545. }
  5546. else
  5547. {
  5548. /* Set sockets to blocking */
  5549. retries = 1;
  5550. SOAP_SOCKBLOCK(sk)
  5551. }
  5552. /* Try connecting until success or timeout */
  5553. while ((r = gnutls_handshake(soap->session)))
  5554. {
  5555. /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */
  5556. if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED)
  5557. {
  5558. int s;
  5559. if (!gnutls_record_get_direction(soap->session))
  5560. s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
  5561. else
  5562. s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
  5563. if (s < 0)
  5564. break;
  5565. if (s == 0 && retries-- <= 0)
  5566. {
  5567. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL/TLS connect timeout\n"));
  5568. soap_set_receiver_error(soap, "Timeout", "SSL_connect() failed in tcp_connect()", SOAP_TCP_ERROR);
  5569. soap->fclosesocket(soap, sk);
  5570. return soap->socket = SOAP_INVALID_SOCKET;
  5571. }
  5572. }
  5573. else
  5574. {
  5575. soap->errnum = soap_socket_errno(sk);
  5576. break;
  5577. }
  5578. }
  5579. if (r)
  5580. {
  5581. soap_set_sender_error(soap, soap_ssl_error(soap, r, 0), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
  5582. soap->fclosesocket(soap, sk);
  5583. return soap->socket = SOAP_INVALID_SOCKET;
  5584. }
  5585. if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
  5586. {
  5587. const char *s = ssl_verify(soap, host);
  5588. if (s)
  5589. {
  5590. soap->fclosesocket(soap, sk);
  5591. soap->error = soap_set_sender_error(soap, "SSL/TLS verify error", s, SOAP_SSL_ERROR);
  5592. return soap->socket = SOAP_INVALID_SOCKET;
  5593. }
  5594. }
  5595. #endif
  5596. #ifdef WITH_SYSTEMSSL
  5597. soap->ssl_flags |= SOAP_SSL_CLIENT;
  5598. if (!soap->ctx && (soap->error = soap->fsslauth(soap)) != SOAP_OK)
  5599. {
  5600. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL required, but no ctx set\n"));
  5601. soap->fclosesocket(soap, sk);
  5602. soap->error = SOAP_SSL_ERROR;
  5603. return soap->socket = SOAP_INVALID_SOCKET;
  5604. }
  5605. if (soap->connect_timeout || soap->recv_timeout || soap->send_timeout)
  5606. {
  5607. /* Set SSL connect timeout and set SSL sockets to non-blocking */
  5608. int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout;
  5609. if (soap->connect_timeout > 0 && t < soap->connect_timeout)
  5610. t = soap->connect_timeout;
  5611. if (t > 0)
  5612. retries = 10 * t;
  5613. else if (t > -100000)
  5614. retries = 1;
  5615. else
  5616. retries = t/-100000;
  5617. SOAP_SOCKNONBLOCK(sk)
  5618. }
  5619. else
  5620. {
  5621. /* Set sockets to blocking */
  5622. retries = 1;
  5623. SOAP_SOCKBLOCK(sk)
  5624. }
  5625. r = gsk_secure_socket_open(soap->ctx, &soap->ssl);
  5626. if (r == GSK_OK)
  5627. r = gsk_attribute_set_numeric_value(soap->ssl, GSK_FD, sk);
  5628. if (r == GSK_OK)
  5629. r = gsk_attribute_set_buffer(soap->ssl, GSK_KEYRING_LABEL, soap->cafile, 0); /* Certificate label */
  5630. if (r == GSK_OK)
  5631. r = gsk_attribute_set_enum(soap->ssl, GSK_SESSION_TYPE, GSK_CLIENT_SESSION);
  5632. if (r == GSK_OK)
  5633. r = gsk_attribute_set_buffer(soap->ssl, GSK_V3_CIPHER_SPECS_EXPANDED, "0035002F000A", 0);
  5634. if (r == GSK_OK)
  5635. r = gsk_attribute_set_enum(soap->ssl, GSK_V3_CIPHERS, GSK_V3_CIPHERS_CHAR4);
  5636. if (r == GSK_OK)
  5637. r = gsk_attribute_set_callback(soap->ssl, GSK_IO_CALLBACK, &local_io);
  5638. if (r != GSK_OK)
  5639. {
  5640. soap_set_receiver_error(soap, gsk_strerror(r), "SYSTEM SSL error in tcp_connect()", SOAP_SSL_ERROR);
  5641. return soap->socket = SOAP_INVALID_SOCKET;
  5642. }
  5643. /* Try connecting until success or timeout */
  5644. while ((r = gsk_secure_socket_init(soap->ssl)) != GSK_OK)
  5645. {
  5646. if (r == GSK_WOULD_BLOCK_READ || r == GSK_WOULD_BLOCK_WRITE)
  5647. {
  5648. int s;
  5649. if (r == GSK_WOULD_BLOCK_READ)
  5650. s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
  5651. else
  5652. s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
  5653. if (s < 0)
  5654. break;
  5655. if (s == 0 && retries-- <= 0)
  5656. {
  5657. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL/TLS connect timeout\n"));
  5658. soap_set_receiver_error(soap, "Timeout", "SSL_connect() failed in tcp_connect()", SOAP_TCP_ERROR);
  5659. soap->fclosesocket(soap, sk);
  5660. return soap->socket = SOAP_INVALID_SOCKET;
  5661. }
  5662. }
  5663. else
  5664. {
  5665. soap->errnum = soap_socket_errno(sk);
  5666. break;
  5667. }
  5668. }
  5669. if (r != GSK_OK)
  5670. {
  5671. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL_connect/select error in tcp_connect\n"));
  5672. soap_set_receiver_error(soap, gsk_strerror(r), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
  5673. soap->fclosesocket(soap, sk);
  5674. return soap->socket = SOAP_INVALID_SOCKET;
  5675. }
  5676. #endif
  5677. soap->imode |= SOAP_ENC_SSL;
  5678. soap->omode |= SOAP_ENC_SSL;
  5679. #else
  5680. soap->fclosesocket(soap, sk);
  5681. soap->error = SOAP_SSL_ERROR;
  5682. return soap->socket = SOAP_INVALID_SOCKET;
  5683. #endif
  5684. }
  5685. if (soap->recv_timeout || soap->send_timeout)
  5686. SOAP_SOCKNONBLOCK(sk)
  5687. else
  5688. SOAP_SOCKBLOCK(sk)
  5689. return sk;
  5690. }
  5691. #endif
  5692. /******************************************************************************/
  5693. #ifndef WITH_NOIO
  5694. static int
  5695. tcp_select(struct soap *soap, SOAP_SOCKET sk, int flags, int timeout) {
  5696. int r;
  5697. struct timeval tv;
  5698. fd_set fd[3], *rfd, *sfd, *efd;
  5699. int retries = 0;
  5700. int eintr = SOAP_MAXEINTR;
  5701. soap->errnum = 0;
  5702. if (!soap_valid_socket(sk)) {
  5703. soap->error = SOAP_EOF;
  5704. return -1;
  5705. }
  5706. #ifndef WIN32
  5707. #if !defined(FD_SETSIZE) || defined(__QNX__) || defined(QNX)
  5708. /* no FD_SETSIZE or select() is not MT safe on some QNX: always poll */
  5709. if (1)
  5710. #else
  5711. /* if fd max set size exceeded, use poll() when available */
  5712. if ((int) sk >= (int) FD_SETSIZE)
  5713. #endif
  5714. #ifdef HAVE_POLL
  5715. {
  5716. #ifdef WITH_SELF_PIPE
  5717. struct pollfd pollfd[2];
  5718. pollfd[1].fd = soap->pipe_fd[0];
  5719. pollfd[1].events = POLLIN;
  5720. #else
  5721. struct pollfd pollfd[1];
  5722. #endif
  5723. pollfd[0].fd = (int) sk;
  5724. pollfd[0].events = 0;
  5725. if ((flags & SOAP_TCP_SELECT_RCV))
  5726. pollfd[0].events |= POLLIN;
  5727. if ((flags & SOAP_TCP_SELECT_SND))
  5728. pollfd[0].events |= POLLOUT;
  5729. if ((flags & SOAP_TCP_SELECT_ERR))
  5730. pollfd[0].events |= POLLERR;
  5731. if (timeout <= 0)
  5732. timeout /= -1000; /* -usec -> ms */
  5733. else {
  5734. retries = timeout - 1;
  5735. timeout = 1000;
  5736. }
  5737. do {
  5738. #ifdef WITH_SELF_PIPE
  5739. r = poll(pollfd, 2, timeout);
  5740. #else
  5741. r = poll(pollfd, 1, timeout);
  5742. #endif
  5743. if (r < 0 && (soap->errnum = soap_socket_errno(sk)) == SOAP_EINTR && eintr > 0) {
  5744. eintr--;
  5745. r = 0;
  5746. } else if (retries-- <= 0) {
  5747. break;
  5748. }
  5749. } while (r == 0);
  5750. if (r > 0) {
  5751. r = 0;
  5752. if ((flags & SOAP_TCP_SELECT_RCV) && (pollfd[0].revents & POLLIN))
  5753. r |= SOAP_TCP_SELECT_RCV;
  5754. if ((flags & SOAP_TCP_SELECT_SND) && (pollfd[0].revents & POLLOUT))
  5755. r |= SOAP_TCP_SELECT_SND;
  5756. if ((flags & SOAP_TCP_SELECT_ERR) && (pollfd[0].revents & POLLERR))
  5757. r |= SOAP_TCP_SELECT_ERR;
  5758. #ifdef WITH_SELF_PIPE
  5759. if ((flags & SOAP_TCP_SELECT_PIP) && (pollfd[1].revents & POLLIN))
  5760. {
  5761. char ch;
  5762. for (;;)
  5763. {
  5764. if (read(soap->pipe_fd[0], &ch, 1) == -1)
  5765. {
  5766. if (soap_socket_errno(soap->pipe_fd[0]) == SOAP_EAGAIN)
  5767. break;
  5768. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Self pipe read error\n"));
  5769. return -1;
  5770. }
  5771. }
  5772. r |= SOAP_TCP_SELECT_PIP;
  5773. }
  5774. #endif
  5775. } else if (r == 0) {
  5776. soap->errnum = 0;
  5777. }
  5778. return r;
  5779. }
  5780. #else
  5781. {
  5782. soap->error = SOAP_FD_EXCEEDED;
  5783. return -1;
  5784. }
  5785. #endif
  5786. #endif
  5787. if (timeout > 0)
  5788. retries = timeout - 1;
  5789. do {
  5790. rfd = sfd = efd = NULL;
  5791. #ifdef WITH_SELF_PIPE
  5792. if ((flags & SOAP_TCP_SELECT_PIP) || (flags & SOAP_TCP_SELECT_RCV))
  5793. {
  5794. rfd = &fd[0];
  5795. FD_ZERO(rfd);
  5796. if ((flags & SOAP_TCP_SELECT_PIP))
  5797. FD_SET(soap->pipe_fd[0], rfd);
  5798. if ((flags & SOAP_TCP_SELECT_RCV))
  5799. FD_SET(sk, rfd);
  5800. }
  5801. #else
  5802. if ((flags & SOAP_TCP_SELECT_RCV)) {
  5803. rfd = &fd[0];
  5804. FD_ZERO(rfd);
  5805. FD_SET(sk, rfd);
  5806. }
  5807. #endif
  5808. if ((flags & SOAP_TCP_SELECT_SND)) {
  5809. sfd = &fd[1];
  5810. FD_ZERO(sfd);
  5811. FD_SET(sk, sfd);
  5812. }
  5813. if ((flags & SOAP_TCP_SELECT_ERR)) {
  5814. efd = &fd[2];
  5815. FD_ZERO(efd);
  5816. FD_SET(sk, efd);
  5817. }
  5818. if (timeout <= 0) {
  5819. tv.tv_sec = -timeout / 1000000;
  5820. tv.tv_usec = -timeout % 1000000;
  5821. } else {
  5822. tv.tv_sec = 1;
  5823. tv.tv_usec = 0;
  5824. }
  5825. #ifdef WITH_SELF_PIPE
  5826. r = select((int)(sk > soap->pipe_fd[0] ? sk : soap->pipe_fd[0]) + 1, rfd, sfd, efd, &tv);
  5827. #else
  5828. r = select((int) sk + 1, rfd, sfd, efd, &tv);
  5829. #endif
  5830. if (r < 0 && (soap->errnum = soap_socket_errno(sk)) == SOAP_EINTR && eintr > 0) {
  5831. eintr--;
  5832. r = 0;
  5833. } else if (retries-- <= 0) {
  5834. break;
  5835. }
  5836. } while (r == 0);
  5837. if (r > 0) {
  5838. r = 0;
  5839. if ((flags & SOAP_TCP_SELECT_RCV) && FD_ISSET(sk, rfd))
  5840. r |= SOAP_TCP_SELECT_RCV;
  5841. if ((flags & SOAP_TCP_SELECT_SND) && FD_ISSET(sk, sfd))
  5842. r |= SOAP_TCP_SELECT_SND;
  5843. if ((flags & SOAP_TCP_SELECT_ERR) && FD_ISSET(sk, efd))
  5844. r |= SOAP_TCP_SELECT_ERR;
  5845. #ifdef WITH_SELF_PIPE
  5846. if ((flags & SOAP_TCP_SELECT_PIP) && FD_ISSET(soap->pipe_fd[0], rfd))
  5847. {
  5848. char ch;
  5849. for (;;)
  5850. {
  5851. if (read(soap->pipe_fd[0], &ch, 1) == -1)
  5852. {
  5853. if (soap_socket_errno(soap->pipe_fd[0]) == SOAP_EAGAIN)
  5854. break;
  5855. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Self pipe read error\n"));
  5856. return -1;
  5857. }
  5858. }
  5859. r |= SOAP_TCP_SELECT_PIP;
  5860. }
  5861. #endif
  5862. } else if (r == 0) {
  5863. soap->errnum = 0;
  5864. }
  5865. return r;
  5866. }
  5867. #endif
  5868. /******************************************************************************/
  5869. #ifndef WITH_NOIO
  5870. static SOAP_SOCKET
  5871. tcp_accept(struct soap *soap, SOAP_SOCKET sk, struct sockaddr *addr, int *len) {
  5872. SOAP_SOCKET s;
  5873. (void) soap;
  5874. s = accept(sk, addr, (SOAP_SOCKLEN_T *) len); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
  5875. #ifdef WITH_SOCKET_CLOSE_ON_EXIT
  5876. #ifdef WIN32
  5877. #ifndef UNDER_CE
  5878. SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, 0);
  5879. #endif
  5880. #else
  5881. fcntl(s, F_SETFD, FD_CLOEXEC);
  5882. #endif
  5883. #endif
  5884. return s;
  5885. }
  5886. #endif
  5887. /******************************************************************************/
  5888. #ifndef WITH_NOIO
  5889. static int
  5890. tcp_disconnect(struct soap *soap) {
  5891. #ifdef WITH_OPENSSL
  5892. if (soap->ssl)
  5893. {
  5894. int r;
  5895. if (soap->session)
  5896. {
  5897. SSL_SESSION_free(soap->session);
  5898. soap->session = NULL;
  5899. }
  5900. if (*soap->host)
  5901. {
  5902. soap->session = SSL_get1_session(soap->ssl);
  5903. if (soap->session)
  5904. {
  5905. soap_strcpy(soap->session_host, sizeof(soap->session_host), soap->host);
  5906. soap->session_port = soap->port;
  5907. }
  5908. }
  5909. r = SSL_shutdown(soap->ssl);
  5910. /* SSL shutdown does not work when reads are pending, non-blocking */
  5911. if (r == 0)
  5912. {
  5913. while (SSL_want_read(soap->ssl))
  5914. {
  5915. if (SSL_read(soap->ssl, NULL, 0)
  5916. || soap_socket_errno(soap->socket) != SOAP_EAGAIN)
  5917. {
  5918. r = SSL_shutdown(soap->ssl);
  5919. break;
  5920. }
  5921. }
  5922. }
  5923. if (r == 0)
  5924. {
  5925. if (soap_valid_socket(soap->socket))
  5926. {
  5927. if (!soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR))
  5928. {
  5929. #if !defined(WITH_LEAN) && !defined(WIN32)
  5930. /*
  5931. wait up to 5 seconds for close_notify to be sent by peer (if peer not
  5932. present, this avoids calling SSL_shutdown() which has a lengthy return
  5933. timeout)
  5934. */
  5935. r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, 5);
  5936. if (r <= 0)
  5937. {
  5938. soap->errnum = 0;
  5939. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection lost...\n"));
  5940. soap->fclosesocket(soap, soap->socket);
  5941. soap->socket = SOAP_INVALID_SOCKET;
  5942. ERR_clear_error();
  5943. SSL_free(soap->ssl);
  5944. soap->ssl = NULL;
  5945. return SOAP_OK;
  5946. }
  5947. #else
  5948. r = SSL_shutdown(soap->ssl);
  5949. if (r <= 0)
  5950. {
  5951. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r)));
  5952. if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
  5953. {
  5954. soap->fclosesocket(soap, soap->socket);
  5955. soap->socket = SOAP_INVALID_SOCKET;
  5956. }
  5957. }
  5958. #endif
  5959. }
  5960. }
  5961. }
  5962. SSL_free(soap->ssl);
  5963. soap->ssl = NULL;
  5964. ERR_clear_error();
  5965. }
  5966. #endif
  5967. #ifdef WITH_GNUTLS
  5968. if (soap->session)
  5969. {
  5970. gnutls_bye(soap->session, GNUTLS_SHUT_RDWR);
  5971. gnutls_deinit(soap->session);
  5972. soap->session = NULL;
  5973. }
  5974. #endif
  5975. #ifdef WITH_SYSTEMSSL
  5976. if (soap->ssl)
  5977. {
  5978. gsk_secure_socket_shutdown(soap->ssl);
  5979. gsk_secure_socket_close(&soap->ssl);
  5980. }
  5981. #endif
  5982. if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP)) {
  5983. soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_RDWR);
  5984. soap->fclosesocket(soap, soap->socket);
  5985. soap->socket = SOAP_INVALID_SOCKET;
  5986. }
  5987. return SOAP_OK;
  5988. }
  5989. #endif
  5990. /******************************************************************************/
  5991. #ifndef WITH_NOIO
  5992. static int
  5993. tcp_closesocket(struct soap *soap, SOAP_SOCKET sk) {
  5994. (void) soap;
  5995. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket=%d\n", (int) sk));
  5996. return soap_closesocket(sk);
  5997. }
  5998. #endif
  5999. /******************************************************************************/
  6000. #ifndef WITH_NOIO
  6001. static int
  6002. tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET sk, int how) {
  6003. (void) soap;
  6004. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket=%d how=%d\n", (int) sk, how));
  6005. return shutdown(sk, how);
  6006. }
  6007. #endif
  6008. /******************************************************************************/
  6009. #ifndef WITH_NOIO
  6010. SOAP_FMAC1
  6011. SOAP_SOCKET
  6012. SOAP_FMAC2
  6013. soap_bind(struct soap *soap, const char *host, int port, int backlog) {
  6014. #if defined(WITH_IPV6)
  6015. struct addrinfo *addrinfo = NULL;
  6016. struct addrinfo hints;
  6017. struct addrinfo res;
  6018. int err;
  6019. int set = 1;
  6020. int unset = 0;
  6021. #elif !defined(WITH_LEAN)
  6022. int set = 1;
  6023. #endif
  6024. if (soap_valid_socket(soap->master)) {
  6025. soap->fclosesocket(soap, soap->master);
  6026. soap->master = SOAP_INVALID_SOCKET;
  6027. }
  6028. soap->socket = SOAP_INVALID_SOCKET;
  6029. soap->errnum = 0;
  6030. soap->errmode = 1;
  6031. if (tcp_init(soap)) {
  6032. soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR);
  6033. return SOAP_INVALID_SOCKET;
  6034. }
  6035. #ifdef WITH_IPV6
  6036. memset((void*)&hints, 0, sizeof(hints));
  6037. hints.ai_family = soap->bind_inet6 ? AF_INET6 : PF_UNSPEC;
  6038. #ifndef WITH_LEAN
  6039. if ((soap->omode & SOAP_IO_UDP))
  6040. hints.ai_socktype = SOCK_DGRAM;
  6041. else
  6042. #endif
  6043. hints.ai_socktype = SOCK_STREAM;
  6044. hints.ai_flags = AI_PASSIVE;
  6045. soap->errmode = 2;
  6046. err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo);
  6047. if (err || !addrinfo)
  6048. {
  6049. soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR);
  6050. if (addrinfo)
  6051. freeaddrinfo(addrinfo);
  6052. return SOAP_INVALID_SOCKET;
  6053. }
  6054. res = *addrinfo;
  6055. if (soap_memcpy((void*)&soap->peer.storage, sizeof(soap->peer.storage), (const void*)addrinfo->ai_addr, addrinfo->ai_addrlen))
  6056. {
  6057. freeaddrinfo(addrinfo);
  6058. soap->error = SOAP_EOM;
  6059. return SOAP_INVALID_SOCKET;
  6060. }
  6061. soap->peerlen = addrinfo->ai_addrlen;
  6062. res.ai_addr = &soap->peer.addr;
  6063. res.ai_addrlen = soap->peerlen;
  6064. freeaddrinfo(addrinfo);
  6065. soap->master = (int)socket(res.ai_family, res.ai_socktype, res.ai_protocol);
  6066. #else
  6067. #ifndef WITH_LEAN
  6068. if ((soap->omode & SOAP_IO_UDP))
  6069. soap->master = (int) socket(AF_INET, SOCK_DGRAM, 0);
  6070. else
  6071. #endif
  6072. soap->master = (int) socket(AF_INET, SOCK_STREAM, 0);
  6073. #endif
  6074. soap->errmode = 0;
  6075. if (!soap_valid_socket(soap->master)) {
  6076. soap->errnum = soap_socket_errno(soap->master);
  6077. soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR);
  6078. return SOAP_INVALID_SOCKET;
  6079. }
  6080. soap->port = port;
  6081. #ifndef WITH_LEAN
  6082. if ((soap->omode & SOAP_IO_UDP))
  6083. soap->socket = soap->master;
  6084. #endif
  6085. #ifdef WITH_SOCKET_CLOSE_ON_EXIT
  6086. #ifdef WIN32
  6087. #ifndef UNDER_CE
  6088. SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0);
  6089. #endif
  6090. #else
  6091. fcntl(soap->master, F_SETFD, 1);
  6092. #endif
  6093. #endif
  6094. #ifndef WITH_LEAN
  6095. if (soap->bind_flags && setsockopt(soap->master, SOL_SOCKET, soap->bind_flags, (char *) &set, sizeof(int))) {
  6096. soap->errnum = soap_socket_errno(soap->master);
  6097. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR);
  6098. return SOAP_INVALID_SOCKET;
  6099. }
  6100. #ifndef UNDER_CE
  6101. if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && (!((soap->imode | soap->omode) & SOAP_IO_UDP)) &&
  6102. setsockopt(soap->master, SOL_SOCKET, SO_KEEPALIVE, (char *) &set, sizeof(int))) {
  6103. soap->errnum = soap_socket_errno(soap->master);
  6104. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR);
  6105. return SOAP_INVALID_SOCKET;
  6106. }
  6107. if (soap->sndbuf > 0 && setsockopt(soap->master, SOL_SOCKET, SO_SNDBUF, (char *) &soap->sndbuf, sizeof(int))) {
  6108. soap->errnum = soap_socket_errno(soap->master);
  6109. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR);
  6110. return SOAP_INVALID_SOCKET;
  6111. }
  6112. if (soap->rcvbuf > 0 && setsockopt(soap->master, SOL_SOCKET, SO_RCVBUF, (char *) &soap->rcvbuf, sizeof(int))) {
  6113. soap->errnum = soap_socket_errno(soap->master);
  6114. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR);
  6115. return SOAP_INVALID_SOCKET;
  6116. }
  6117. #ifdef TCP_NODELAY
  6118. if (!(soap->omode & SOAP_IO_UDP) &&
  6119. setsockopt(soap->master, IPPROTO_TCP, TCP_NODELAY, (char *) &set, sizeof(int))) {
  6120. soap->errnum = soap_socket_errno(soap->master);
  6121. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR);
  6122. return SOAP_INVALID_SOCKET;
  6123. }
  6124. #endif
  6125. #ifdef TCP_FASTOPEN
  6126. if (!(soap->omode & SOAP_IO_UDP) &&
  6127. setsockopt(soap->master, IPPROTO_TCP, TCP_FASTOPEN, (char *) &set, sizeof(int))) {
  6128. /* silently ignore */
  6129. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "setsockopt TCP_FASTOPEN failed in soap_bind()\n"));
  6130. }
  6131. #endif
  6132. #endif
  6133. #endif
  6134. #ifdef WITH_IPV6
  6135. if (res.ai_family == AF_INET6 && setsockopt(soap->master, IPPROTO_IPV6, IPV6_V6ONLY, soap->bind_v6only ? (char*)&set : (char*)&unset, sizeof(int)))
  6136. {
  6137. soap->errnum = soap_socket_errno(soap->master);
  6138. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR);
  6139. return SOAP_INVALID_SOCKET;
  6140. }
  6141. soap->errmode = 0;
  6142. if (bind(soap->master, res.ai_addr, (int)res.ai_addrlen))
  6143. {
  6144. soap->errnum = soap_socket_errno(soap->master);
  6145. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host, bind failed\n"));
  6146. soap_closesock(soap);
  6147. soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
  6148. return SOAP_INVALID_SOCKET;
  6149. }
  6150. #else
  6151. soap->peerlen = sizeof(soap->peer.in);
  6152. memset((void *) &soap->peer.in, 0, sizeof(soap->peer.in));
  6153. soap->peer.in.sin_family = AF_INET;
  6154. soap->errmode = 2;
  6155. if (host) {
  6156. if (soap->fresolve(soap, host, &soap->peer.in.sin_addr)) {
  6157. soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR);
  6158. return SOAP_INVALID_SOCKET;
  6159. }
  6160. } else
  6161. soap->peer.in.sin_addr.s_addr = htonl(INADDR_ANY);
  6162. soap->peer.in.sin_port = htons((short) port);
  6163. soap->errmode = 0;
  6164. if (bind(soap->master, &soap->peer.addr, (int) soap->peerlen)) {
  6165. soap->errnum = soap_socket_errno(soap->master);
  6166. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host, bind failed\n"));
  6167. soap_closesock(soap);
  6168. soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
  6169. return SOAP_INVALID_SOCKET;
  6170. }
  6171. #endif
  6172. if (!(soap->omode & SOAP_IO_UDP) && listen(soap->master, backlog)) {
  6173. soap->errnum = soap_socket_errno(soap->master);
  6174. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host, listen failed\n"));
  6175. soap_closesock(soap);
  6176. soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR);
  6177. return SOAP_INVALID_SOCKET;
  6178. }
  6179. return soap->master;
  6180. }
  6181. #endif
  6182. /******************************************************************************/
  6183. #ifndef WITH_NOIO
  6184. SOAP_FMAC1
  6185. int
  6186. SOAP_FMAC2
  6187. soap_poll(struct soap *soap) {
  6188. #ifndef WITH_LEAN
  6189. int r;
  6190. if (soap_valid_socket(soap->socket)) {
  6191. r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ALL, 0);
  6192. if (r > 0 && (r & SOAP_TCP_SELECT_ERR))
  6193. r = -1;
  6194. } else if (soap_valid_socket(soap->master)) {
  6195. r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, 0);
  6196. } else {
  6197. return SOAP_OK; /* OK when no socket! */
  6198. }
  6199. if (r > 0) {
  6200. int t;
  6201. #ifdef WITH_OPENSSL
  6202. if ((soap->imode & SOAP_ENC_SSL))
  6203. {
  6204. if (soap_valid_socket(soap->socket)
  6205. && (r & SOAP_TCP_SELECT_SND)
  6206. && (!(r & SOAP_TCP_SELECT_RCV)
  6207. || SSL_peek(soap->ssl, (char*)&t, 1) > 0))
  6208. return SOAP_OK;
  6209. }
  6210. else
  6211. #endif
  6212. {
  6213. if (soap_valid_socket(soap->socket)
  6214. && (r & SOAP_TCP_SELECT_SND)
  6215. && (!(r & SOAP_TCP_SELECT_RCV)
  6216. || recv(soap->socket, (char *) &t, 1, MSG_PEEK) > 0))
  6217. return SOAP_OK;
  6218. }
  6219. } else if (r < 0) {
  6220. if ((soap_valid_socket(soap->master) && soap_socket_errno(soap->master) != SOAP_EINTR)
  6221. || (soap_valid_socket(soap->socket) && soap_socket_errno(soap->socket) != SOAP_EINTR))
  6222. return soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR);
  6223. }
  6224. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_poll: other end down on socket=%d select=%d\n", (int) soap->socket, r));
  6225. return SOAP_EOF;
  6226. #else
  6227. (void)soap;
  6228. return SOAP_OK;
  6229. #endif
  6230. }
  6231. #endif
  6232. /******************************************************************************/
  6233. #ifndef WITH_NOIO
  6234. SOAP_FMAC1
  6235. int
  6236. SOAP_FMAC2
  6237. soap_ready(struct soap *soap) {
  6238. #ifndef WITH_LEAN
  6239. int r;
  6240. if (!soap_valid_socket(soap->socket))
  6241. return SOAP_OK; /* OK when no socket! */
  6242. r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, 0);
  6243. if (r > 0 && (r & SOAP_TCP_SELECT_ERR))
  6244. r = -1;
  6245. if (r < 0 && soap_socket_errno(soap->socket) != SOAP_EINTR)
  6246. return soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_ready()", SOAP_TCP_ERROR);
  6247. if (r > 0) {
  6248. char t;
  6249. #ifdef WITH_OPENSSL
  6250. if ((soap->imode & SOAP_ENC_SSL))
  6251. {
  6252. if (SSL_peek(soap->ssl, &t, 1) > 0)
  6253. return SOAP_OK;
  6254. }
  6255. else
  6256. #endif
  6257. {
  6258. if (recv(soap->socket, &t, 1, MSG_PEEK) > 0)
  6259. return SOAP_OK;
  6260. }
  6261. }
  6262. DBGLOG(TEST,
  6263. SOAP_MESSAGE(fdebug, "soap_ready: other end not ready to send on socket=%d select=%d\n", (int) soap->socket,
  6264. r));
  6265. return SOAP_EOF;
  6266. #else
  6267. (void)soap;
  6268. return SOAP_OK;
  6269. #endif
  6270. }
  6271. #endif
  6272. /******************************************************************************/
  6273. #ifndef WITH_NOIO
  6274. SOAP_FMAC1
  6275. SOAP_SOCKET
  6276. SOAP_FMAC2
  6277. soap_accept(struct soap *soap) {
  6278. int n = (int) sizeof(soap->peer);
  6279. int err;
  6280. #ifndef WITH_LEAN
  6281. int set = 1;
  6282. #endif
  6283. soap->error = SOAP_OK;
  6284. memset((void *) &soap->peer, 0, sizeof(soap->peer));
  6285. soap->socket = SOAP_INVALID_SOCKET;
  6286. soap->errmode = 0;
  6287. soap->errnum = 0;
  6288. soap->keep_alive = 0;
  6289. if (!soap_valid_socket(soap->master)) {
  6290. soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR);
  6291. return SOAP_INVALID_SOCKET;
  6292. }
  6293. #ifndef WITH_LEAN
  6294. if ((soap->omode & SOAP_IO_UDP))
  6295. return soap->socket = soap->master;
  6296. #endif
  6297. for (;;) {
  6298. if (soap->accept_timeout) {
  6299. for (;;) {
  6300. int r;
  6301. r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_ALL, soap->accept_timeout);
  6302. if (r > 0)
  6303. break;
  6304. if (!r) {
  6305. soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR);
  6306. return SOAP_INVALID_SOCKET;
  6307. }
  6308. if (r < 0) {
  6309. r = soap->errnum;
  6310. if (r != SOAP_EINTR) {
  6311. soap_closesock(soap);
  6312. soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()",
  6313. SOAP_TCP_ERROR);
  6314. return SOAP_INVALID_SOCKET;
  6315. }
  6316. }
  6317. }
  6318. }
  6319. n = (int) sizeof(soap->peer);
  6320. soap->socket = soap->faccept(soap, soap->master, &soap->peer.addr, &n);
  6321. soap->peerlen = (size_t) n;
  6322. if (soap_valid_socket(soap->socket)) {
  6323. #ifdef WITH_IPV6
  6324. char port[16];
  6325. struct addrinfo *res = NULL;
  6326. struct addrinfo hints;
  6327. memset(&hints, 0, sizeof(struct addrinfo));
  6328. hints.ai_family = PF_UNSPEC;
  6329. hints.ai_socktype = SOCK_STREAM;
  6330. hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
  6331. getnameinfo(&soap->peer.addr, n, soap->host, sizeof(soap->host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
  6332. soap->ip = 0;
  6333. soap->ip6[0] = 0;
  6334. soap->ip6[1] = 0;
  6335. soap->ip6[2] = 0;
  6336. soap->ip6[3] = 0;
  6337. if (getaddrinfo(soap->host, NULL, &hints, &res) == 0 && res)
  6338. {
  6339. struct sockaddr_storage result;
  6340. soap_memcpy(&result, sizeof(result), res->ai_addr, res->ai_addrlen);
  6341. freeaddrinfo(res);
  6342. if (result.ss_family == AF_INET6)
  6343. {
  6344. struct sockaddr_in6 *addr = (struct sockaddr_in6*)&result;
  6345. struct in6_addr *inaddr = &addr->sin6_addr;
  6346. int i;
  6347. for (i = 0; i < 16; i++)
  6348. soap->ip6[i/4] = (soap->ip6[i/4] << 8) + inaddr->s6_addr[i];
  6349. }
  6350. else if (result.ss_family == AF_INET)
  6351. {
  6352. struct sockaddr_in *addr = (struct sockaddr_in*)&result;
  6353. soap->ip = ntohl(addr->sin_addr.s_addr);
  6354. soap->ip6[2] = 0xFFFF;
  6355. soap->ip6[3] = soap->ip;
  6356. }
  6357. }
  6358. soap->port = soap_strtol(port, NULL, 10);
  6359. #else
  6360. soap->ip = ntohl(soap->peer.in.sin_addr.s_addr);
  6361. soap->ip6[0] = 0;
  6362. soap->ip6[1] = 0;
  6363. soap->ip6[2] = 0xFFFF;
  6364. soap->ip6[3] = soap->ip;
  6365. (SOAP_SNPRINTF(soap->host, sizeof(soap->host), 80), "%u.%u.%u.%u", (int) (soap->ip >> 24) & 0xFF,
  6366. (int) (soap->ip >> 16) & 0xFF,
  6367. (int) (soap->ip >> 8) & 0xFF, (int) soap->ip & 0xFF);
  6368. soap->port = (int) ntohs(soap->peer.in.sin_port); /* does not return port number on some systems */
  6369. #endif
  6370. DBGLOG(TEST,
  6371. SOAP_MESSAGE(fdebug, "Accept socket=%d at port=%d from IP='%s'\n", (int) soap->socket, soap->port,
  6372. soap->host));
  6373. #ifndef WITH_LEAN
  6374. if ((soap->accept_flags & SO_LINGER)) {
  6375. struct linger linger;
  6376. memset((void *) &linger, 0, sizeof(linger));
  6377. linger.l_onoff = 1;
  6378. linger.l_linger = soap->linger_time;
  6379. if (setsockopt(soap->socket, SOL_SOCKET, SO_LINGER, (char *) &linger, sizeof(struct linger))) {
  6380. soap->errnum = soap_socket_errno(soap->socket);
  6381. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()",
  6382. SOAP_TCP_ERROR);
  6383. soap_closesock(soap);
  6384. return SOAP_INVALID_SOCKET;
  6385. }
  6386. }
  6387. if ((soap->accept_flags & ~SO_LINGER) &&
  6388. setsockopt(soap->socket, SOL_SOCKET, soap->accept_flags & ~SO_LINGER, (char *) &set, sizeof(int))) {
  6389. soap->errnum = soap_socket_errno(soap->socket);
  6390. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR);
  6391. soap_closesock(soap);
  6392. return SOAP_INVALID_SOCKET;
  6393. }
  6394. #ifndef UNDER_CE
  6395. if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) &&
  6396. setsockopt(soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char *) &set, sizeof(int))) {
  6397. soap->errnum = soap_socket_errno(soap->socket);
  6398. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()",
  6399. SOAP_TCP_ERROR);
  6400. soap_closesock(soap);
  6401. return SOAP_INVALID_SOCKET;
  6402. }
  6403. if (soap->sndbuf > 0 &&
  6404. setsockopt(soap->socket, SOL_SOCKET, SO_SNDBUF, (char *) &soap->sndbuf, sizeof(int))) {
  6405. soap->errnum = soap_socket_errno(soap->socket);
  6406. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()",
  6407. SOAP_TCP_ERROR);
  6408. soap_closesock(soap);
  6409. return SOAP_INVALID_SOCKET;
  6410. }
  6411. if (soap->rcvbuf > 0 &&
  6412. setsockopt(soap->socket, SOL_SOCKET, SO_RCVBUF, (char *) &soap->rcvbuf, sizeof(int))) {
  6413. soap->errnum = soap_socket_errno(soap->socket);
  6414. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()",
  6415. SOAP_TCP_ERROR);
  6416. soap_closesock(soap);
  6417. return SOAP_INVALID_SOCKET;
  6418. }
  6419. #ifdef TCP_NODELAY
  6420. if (setsockopt(soap->socket, IPPROTO_TCP, TCP_NODELAY, (char *) &set, sizeof(int))) {
  6421. soap->errnum = soap_socket_errno(soap->socket);
  6422. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()",
  6423. SOAP_TCP_ERROR);
  6424. soap_closesock(soap);
  6425. return SOAP_INVALID_SOCKET;
  6426. }
  6427. #endif
  6428. #endif
  6429. #endif
  6430. soap->keep_alive = -(((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
  6431. if (soap->send_timeout || soap->recv_timeout)
  6432. SOAP_SOCKNONBLOCK(soap->socket)
  6433. else
  6434. SOAP_SOCKBLOCK(soap->socket)
  6435. return soap->socket;
  6436. }
  6437. err = soap_socket_errno(soap->socket);
  6438. if (err != 0 && err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK) {
  6439. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host));
  6440. soap->errnum = err;
  6441. soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
  6442. soap_closesock(soap);
  6443. return SOAP_INVALID_SOCKET;
  6444. }
  6445. }
  6446. }
  6447. #endif
  6448. /******************************************************************************/
  6449. SOAP_FMAC1
  6450. int
  6451. SOAP_FMAC2
  6452. soap_closesock(struct soap *soap) {
  6453. int status = soap->error;
  6454. int err = SOAP_OK;
  6455. soap->part = SOAP_END;
  6456. #ifndef WITH_LEANER
  6457. if (status && status < 200) /* attachment state is not to be trusted */
  6458. {
  6459. soap->mime.first = NULL;
  6460. soap->mime.last = NULL;
  6461. soap->dime.first = NULL;
  6462. soap->dime.last = NULL;
  6463. }
  6464. #endif
  6465. if (soap->fdisconnect)
  6466. err = soap->fdisconnect(soap);
  6467. if (err || status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive) {
  6468. soap->keep_alive = 0;
  6469. if (soap->fclose && (soap->error = soap->fclose(soap)) != SOAP_OK)
  6470. return soap->error;
  6471. if (err)
  6472. return soap->error = err;
  6473. }
  6474. #ifdef WITH_ZLIB
  6475. if (!(soap->mode & SOAP_MIME_POSTCHECK))
  6476. {
  6477. if (soap->zlib_state == SOAP_ZLIB_DEFLATE)
  6478. deflateEnd(soap->d_stream);
  6479. else if (soap->zlib_state == SOAP_ZLIB_INFLATE)
  6480. inflateEnd(soap->d_stream);
  6481. soap->zlib_state = SOAP_ZLIB_NONE;
  6482. }
  6483. #endif
  6484. soap->error = status;
  6485. std::cerr << "soap_closesock: " << status << std::endl;
  6486. return soap->error = status;
  6487. }
  6488. /******************************************************************************/
  6489. SOAP_FMAC1
  6490. int
  6491. SOAP_FMAC2
  6492. soap_force_closesock(struct soap *soap) {
  6493. soap->keep_alive = 0;
  6494. if (soap_valid_socket(soap->socket) && soap->fclosesocket) {
  6495. soap->fclosesocket(soap, soap->socket);
  6496. soap->socket = SOAP_INVALID_SOCKET;
  6497. }
  6498. return soap->error;
  6499. }
  6500. /******************************************************************************/
  6501. #ifdef WITH_SELF_PIPE
  6502. SOAP_FMAC1
  6503. void
  6504. SOAP_FMAC2
  6505. soap_close_connection(struct soap *soap)
  6506. {
  6507. if (soap_valid_socket(soap->socket))
  6508. write(soap->pipe_fd[1], "1", 1);
  6509. }
  6510. #endif
  6511. /******************************************************************************/
  6512. #ifndef WITH_NOIO
  6513. SOAP_FMAC1
  6514. void
  6515. SOAP_FMAC2
  6516. soap_cleanup(struct soap *soap) {
  6517. soap_done(soap);
  6518. #ifdef WIN32
  6519. if (!tcp_done)
  6520. return;
  6521. tcp_done = 0;
  6522. WSACleanup();
  6523. #endif
  6524. }
  6525. #endif
  6526. /******************************************************************************/
  6527. SOAP_FMAC1
  6528. void
  6529. SOAP_FMAC2
  6530. soap_done(struct soap *soap) {
  6531. #ifdef SOAP_DEBUG
  6532. int i;
  6533. #endif
  6534. if (soap_check_state(soap))
  6535. return;
  6536. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context%s\n", soap->state == SOAP_COPY ? " copy" : ""));
  6537. soap_free_temp(soap);
  6538. while (soap->clist) {
  6539. struct soap_clist *p = soap->clist->next;
  6540. SOAP_FREE(soap, soap->clist);
  6541. soap->clist = p;
  6542. }
  6543. if (soap->state == SOAP_INIT)
  6544. soap->omode &= ~SOAP_IO_UDP; /* to force close the socket */
  6545. soap->keep_alive = 0; /* to force close the socket */
  6546. if (soap->master == soap->socket) /* do not close twice */
  6547. soap->master = SOAP_INVALID_SOCKET;
  6548. soap_closesock(soap);
  6549. #ifdef WITH_COOKIES
  6550. soap_free_cookies(soap);
  6551. #endif
  6552. while (soap->plugins) {
  6553. struct soap_plugin *p = soap->plugins->next;
  6554. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id));
  6555. if (soap->plugins->fcopy || soap->state == SOAP_INIT)
  6556. soap->plugins->fdelete(soap, soap->plugins);
  6557. SOAP_FREE(soap, soap->plugins);
  6558. soap->plugins = p;
  6559. }
  6560. soap->fplugin = fplugin;
  6561. #ifndef WITH_NOHTTP
  6562. soap->fpost = http_post;
  6563. soap->fget = http_get;
  6564. soap->fput = http_put;
  6565. soap->fpatch = http_patch;
  6566. soap->fdel = http_del;
  6567. soap->fopt = http_200;
  6568. soap->fhead = http_200;
  6569. soap->fform = NULL;
  6570. soap->fposthdr = http_post_header;
  6571. soap->fresponse = http_response;
  6572. soap->fparse = http_parse;
  6573. soap->fparsehdr = http_parse_header;
  6574. #endif
  6575. soap->fheader = NULL;
  6576. #ifndef WITH_NOIO
  6577. #ifndef WITH_IPV6
  6578. soap->fresolve = tcp_gethost;
  6579. #else
  6580. soap->fresolve = NULL;
  6581. #endif
  6582. soap->faccept = tcp_accept;
  6583. soap->fopen = tcp_connect;
  6584. soap->fclose = tcp_disconnect;
  6585. soap->fclosesocket = tcp_closesocket;
  6586. soap->fshutdownsocket = tcp_shutdownsocket;
  6587. soap->fsend = fsend;
  6588. soap->frecv = frecv;
  6589. soap->fpoll = soap_poll;
  6590. #else
  6591. soap->fopen = NULL;
  6592. soap->fclose = NULL;
  6593. soap->fpoll = NULL;
  6594. #endif
  6595. #ifndef WITH_LEANER
  6596. soap->fsvalidate = NULL;
  6597. soap->fwvalidate = NULL;
  6598. soap->feltbegin = NULL;
  6599. soap->feltendin = NULL;
  6600. soap->feltbegout = NULL;
  6601. soap->feltendout = NULL;
  6602. soap->fprepareinitsend = NULL;
  6603. soap->fprepareinitrecv = NULL;
  6604. soap->fpreparesend = NULL;
  6605. soap->fpreparerecv = NULL;
  6606. soap->fpreparefinalsend = NULL;
  6607. soap->fpreparefinalrecv = NULL;
  6608. soap->ffiltersend = NULL;
  6609. soap->ffilterrecv = NULL;
  6610. #endif
  6611. soap->fseterror = NULL;
  6612. soap->fignore = NULL;
  6613. soap->fserveloop = NULL;
  6614. #ifdef WITH_OPENSSL
  6615. if (soap->session)
  6616. {
  6617. SSL_SESSION_free(soap->session);
  6618. soap->session = NULL;
  6619. }
  6620. #endif
  6621. if (soap->state == SOAP_INIT) {
  6622. if (soap_valid_socket(soap->master)) {
  6623. soap->fclosesocket(soap, soap->master);
  6624. soap->master = SOAP_INVALID_SOCKET;
  6625. }
  6626. }
  6627. #ifdef WITH_OPENSSL
  6628. if (soap->ssl)
  6629. {
  6630. SSL_free(soap->ssl);
  6631. soap->ssl = NULL;
  6632. }
  6633. if (soap->state == SOAP_INIT)
  6634. {
  6635. if (soap->ctx)
  6636. {
  6637. SSL_CTX_free(soap->ctx);
  6638. soap->ctx = NULL;
  6639. }
  6640. }
  6641. ERR_clear_error();
  6642. # if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
  6643. /* OpenSSL libraries handle thread init and deinit */
  6644. # elif OPENSSL_VERSION_NUMBER >= 0x10000000L
  6645. ERR_remove_thread_state(NULL);
  6646. # else
  6647. ERR_remove_state(0);
  6648. # endif
  6649. #endif
  6650. #ifdef WITH_GNUTLS
  6651. if (soap->state == SOAP_INIT)
  6652. {
  6653. if (soap->xcred)
  6654. {
  6655. gnutls_certificate_free_credentials(soap->xcred);
  6656. soap->xcred = NULL;
  6657. }
  6658. if (soap->acred)
  6659. {
  6660. gnutls_anon_free_client_credentials(soap->acred);
  6661. soap->acred = NULL;
  6662. }
  6663. if (soap->cache)
  6664. {
  6665. gnutls_priority_deinit(soap->cache);
  6666. soap->cache = NULL;
  6667. }
  6668. if (soap->dh_params)
  6669. {
  6670. gnutls_dh_params_deinit(soap->dh_params);
  6671. soap->dh_params = NULL;
  6672. }
  6673. # if GNUTLS_VERSION_NUMBER < 0x030300
  6674. if (soap->rsa_params)
  6675. {
  6676. gnutls_rsa_params_deinit(soap->rsa_params);
  6677. soap->rsa_params = NULL;
  6678. }
  6679. #endif
  6680. }
  6681. if (soap->session)
  6682. {
  6683. gnutls_deinit(soap->session);
  6684. soap->session = NULL;
  6685. }
  6686. #endif
  6687. #ifdef WITH_SYSTEMSSL
  6688. if (soap->ssl)
  6689. gsk_secure_socket_close(&soap->ssl);
  6690. if (soap->state == SOAP_INIT)
  6691. if (soap->ctx)
  6692. gsk_environment_close(&soap->ctx);
  6693. #endif
  6694. #ifdef WITH_C_LOCALE
  6695. SOAP_FREELOCALE(soap);
  6696. #endif
  6697. #ifdef WITH_ZLIB
  6698. if (soap->d_stream)
  6699. {
  6700. SOAP_FREE(soap, soap->d_stream);
  6701. soap->d_stream = NULL;
  6702. }
  6703. if (soap->z_buf)
  6704. {
  6705. SOAP_FREE(soap, soap->z_buf);
  6706. soap->z_buf = NULL;
  6707. }
  6708. #endif
  6709. #ifdef SOAP_DEBUG
  6710. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n"));
  6711. for (i = 0; i < SOAP_MAXLOGS; i++)
  6712. {
  6713. soap_close_logfile(soap, i);
  6714. if (soap->logfile[i])
  6715. {
  6716. SOAP_FREE_UNMANAGED(soap->logfile[i]);
  6717. soap->logfile[i] = NULL;
  6718. }
  6719. }
  6720. #endif
  6721. #ifdef WITH_SELF_PIPE
  6722. close(soap->pipe_fd[0]);
  6723. close(soap->pipe_fd[1]);
  6724. #endif
  6725. #ifdef SOAP_MEM_DEBUG
  6726. soap_free_mht(soap);
  6727. #endif
  6728. soap->state = SOAP_NONE;
  6729. }
  6730. /******************************************************************************\
  6731. *
  6732. * HTTP
  6733. *
  6734. \******************************************************************************/
  6735. #ifndef WITH_NOHTTP
  6736. static int
  6737. http_parse(struct soap *soap) {
  6738. char header[SOAP_HDRLEN], *s;
  6739. int err = SOAP_OK;
  6740. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n"));
  6741. soap->fform = NULL;
  6742. *soap->endpoint = '\0';
  6743. soap->bearer = NULL;
  6744. #ifdef WITH_NTLM
  6745. if (!soap->ntlm_challenge)
  6746. #endif
  6747. {
  6748. soap->userid = NULL;
  6749. soap->passwd = NULL;
  6750. soap->authrealm = NULL;
  6751. }
  6752. #ifdef WITH_NTLM
  6753. soap->ntlm_challenge = NULL;
  6754. #endif
  6755. soap->proxy_from = NULL;
  6756. soap->cors_origin = NULL;
  6757. soap->cors_method = NULL;
  6758. soap->cors_header = NULL;
  6759. do {
  6760. soap->length = 0;
  6761. soap->http_content = NULL;
  6762. soap->action = NULL;
  6763. soap->status = 0;
  6764. soap->body = 1;
  6765. if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) {
  6766. if (soap->error == SOAP_EOF)
  6767. return SOAP_EOF;
  6768. return soap->error = 414;
  6769. }
  6770. s = strchr(soap->msgbuf, ' ');
  6771. if (s) {
  6772. soap->status = (unsigned short) soap_strtoul(s, &s, 10);
  6773. if (!soap_coblank((soap_wchar) *s))
  6774. soap->status = 0;
  6775. }
  6776. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf));
  6777. for (;;) {
  6778. if (soap_getline(soap, header, SOAP_HDRLEN)) {
  6779. if (soap->error == SOAP_EOF) {
  6780. soap->error = SOAP_OK;
  6781. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "EOF in HTTP header, try to continue anyway\n"));
  6782. break;
  6783. }
  6784. return soap->error;
  6785. }
  6786. if (!*header)
  6787. break;
  6788. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header));
  6789. s = strchr(header, ':');
  6790. if (s) {
  6791. char *t;
  6792. *s = '\0';
  6793. do {
  6794. s++;
  6795. } while (*s && *s <= 32);
  6796. if (*s == '"')
  6797. s++;
  6798. t = s + strlen(s) - 1;
  6799. while (t > s && *t <= 32)
  6800. t--;
  6801. if (t >= s && *t == '"')
  6802. t--;
  6803. t[1] = '\0';
  6804. soap->error = soap->fparsehdr(soap, header, s);
  6805. if (soap->error) {
  6806. if (soap->error < SOAP_STOP)
  6807. return soap->error;
  6808. err = soap->error;
  6809. soap->error = SOAP_OK;
  6810. }
  6811. }
  6812. }
  6813. } while (soap->status == 100);
  6814. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Finished HTTP header parsing, status = %d\n", soap->status));
  6815. s = strstr(soap->msgbuf, "HTTP/");
  6816. if (s && s[5] == '1' && s[6] == '.' && s[7] == '0') {
  6817. soap->keep_alive = 0; /* HTTP 1.0 does not support keep-alive */
  6818. if (soap->status == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* soap->status == 0 for HTTP request */
  6819. soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; /* HTTP 1.0 does not support chunked transfers */
  6820. }
  6821. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive));
  6822. if (soap->status == 0) {
  6823. size_t l = 0;
  6824. if (s) {
  6825. if (!strncmp(soap->msgbuf, "POST ", l = 5))
  6826. soap->status = SOAP_POST;
  6827. else if (!strncmp(soap->msgbuf, "GET ", l = 4))
  6828. soap->status = SOAP_GET;
  6829. else if (!strncmp(soap->msgbuf, "PUT ", l = 4))
  6830. soap->status = SOAP_PUT;
  6831. else if (!strncmp(soap->msgbuf, "PATCH ", l = 4))
  6832. soap->status = SOAP_PATCH;
  6833. else if (!strncmp(soap->msgbuf, "DELETE ", l = 7))
  6834. soap->status = SOAP_DEL;
  6835. else if (!strncmp(soap->msgbuf, "HEAD ", l = 5))
  6836. soap->status = SOAP_HEAD;
  6837. else if (!strncmp(soap->msgbuf, "OPTIONS ", l = 8))
  6838. soap->status = SOAP_OPTIONS;
  6839. }
  6840. if (s && soap->status) {
  6841. size_t m, n, k;
  6842. int r;
  6843. while (soap->msgbuf[l] && soap_coblank((soap_wchar) soap->msgbuf[l]))
  6844. l++;
  6845. m = strlen(soap->endpoint);
  6846. n = m + (s - soap->msgbuf) - l - 1;
  6847. if (n >= sizeof(soap->endpoint))
  6848. n = sizeof(soap->endpoint) - 1;
  6849. if (m > n)
  6850. m = n;
  6851. k = n - m + 1;
  6852. if (k >= sizeof(soap->path))
  6853. k = sizeof(soap->path) - 1;
  6854. while (k > 0 && soap_coblank((soap_wchar) soap->msgbuf[l + k - 1]))
  6855. k--;
  6856. if (soap_strncpy(soap->path, sizeof(soap->path), soap->msgbuf + l, k))
  6857. return soap->error = 414;
  6858. if (*soap->path && *soap->path != '/')
  6859. r = soap_strncpy(soap->endpoint, sizeof(soap->endpoint), soap->path, k);
  6860. else
  6861. r = soap_strncat(soap->endpoint, sizeof(soap->endpoint), soap->path, k);
  6862. if (r)
  6863. return soap->error = 414;
  6864. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Target endpoint='%s' path='%s'\n", soap->endpoint, soap->path));
  6865. if (err)
  6866. return soap->error = err;
  6867. } else if (err) {
  6868. return soap->error = err;
  6869. } else if (s) {
  6870. return soap->error = 405;
  6871. }
  6872. return SOAP_OK;
  6873. }
  6874. if ((soap->status >= 200 && soap->status <= 299) /* OK, Accepted, etc */
  6875. || soap->status == 400 /* Bad Request */
  6876. || soap->status == 500) /* Internal Server Error */
  6877. return soap->error = SOAP_OK;
  6878. return soap->error = soap->status;
  6879. }
  6880. #endif
  6881. /******************************************************************************/
  6882. #ifndef WITH_NOHTTP
  6883. static int
  6884. http_parse_header(struct soap *soap, const char *key, const char *val) {
  6885. if (!soap_tag_cmp(key, "Host")) {
  6886. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
  6887. if ((soap->imode & SOAP_ENC_SSL))
  6888. soap_strcpy(soap->endpoint, sizeof(soap->endpoint), "https://");
  6889. else
  6890. #endif
  6891. soap_strcpy(soap->endpoint, sizeof(soap->endpoint), "http://");
  6892. if (soap_strncat(soap->endpoint, sizeof(soap->endpoint), val, sizeof(soap->endpoint) - 9))
  6893. return soap->error = SOAP_HDR;
  6894. }
  6895. #ifndef WITH_LEANER
  6896. else if (!soap_tag_cmp(key, "Content-Type")) {
  6897. const char *action;
  6898. soap->http_content = soap_strdup(soap, val);
  6899. if (soap_http_header_attribute(soap, val, "application/dime"))
  6900. soap->imode |= SOAP_ENC_DIME;
  6901. else if (soap_http_header_attribute(soap, val, "multipart/related")
  6902. || soap_http_header_attribute(soap, val, "multipart/form-data")) {
  6903. const char *type;
  6904. soap->mime.boundary = soap_strdup(soap, soap_http_header_attribute(soap, val, "boundary"));
  6905. soap->mime.start = soap_strdup(soap, soap_http_header_attribute(soap, val, "start"));
  6906. soap->imode |= SOAP_ENC_MIME;
  6907. type = soap_http_header_attribute(soap, val, "type");
  6908. if (type && !strcmp(type, "application/xop+xml"))
  6909. soap->imode |= SOAP_ENC_MTOM;
  6910. }
  6911. action = soap_http_header_attribute(soap, val, "action");
  6912. if (action) {
  6913. if (*action == '"') {
  6914. soap->action = soap_strdup(soap, action + 1);
  6915. if (soap->action && *soap->action)
  6916. soap->action[strlen(soap->action) - 1] = '\0';
  6917. } else
  6918. soap->action = soap_strdup(soap, action);
  6919. }
  6920. }
  6921. #endif
  6922. else if (!soap_tag_cmp(key, "Content-Length")) {
  6923. soap->length = soap_strtoull(val, NULL, 10);
  6924. if (soap->length == 0)
  6925. soap->body = 0;
  6926. } else if (!soap_tag_cmp(key, "Content-Encoding")) {
  6927. if (!soap_tag_cmp(val, "deflate"))
  6928. #ifdef WITH_ZLIB
  6929. soap->zlib_in = SOAP_ZLIB_DEFLATE;
  6930. #else
  6931. return SOAP_ZLIB_ERROR;
  6932. #endif
  6933. else if (!soap_tag_cmp(val, "gzip"))
  6934. #ifdef WITH_GZIP
  6935. soap->zlib_in = SOAP_ZLIB_GZIP;
  6936. #else
  6937. return SOAP_ZLIB_ERROR;
  6938. #endif
  6939. }
  6940. #ifdef WITH_ZLIB
  6941. else if (!soap_tag_cmp(key, "Accept-Encoding"))
  6942. {
  6943. #ifdef WITH_GZIP
  6944. if (strchr(val, '*') || soap_http_header_attribute(soap, val, "gzip"))
  6945. soap->zlib_out = SOAP_ZLIB_GZIP;
  6946. else
  6947. #endif
  6948. if (strchr(val, '*') || soap_http_header_attribute(soap, val, "deflate"))
  6949. soap->zlib_out = SOAP_ZLIB_DEFLATE;
  6950. else
  6951. soap->zlib_out = SOAP_ZLIB_NONE;
  6952. }
  6953. #endif
  6954. else if (!soap_tag_cmp(key, "Transfer-Encoding")) {
  6955. soap->imode &= ~SOAP_IO;
  6956. if (!soap_tag_cmp(val, "chunked"))
  6957. soap->imode |= SOAP_IO_CHUNK;
  6958. } else if (!soap_tag_cmp(key, "Connection")) {
  6959. if (!soap_tag_cmp(val, "close"))
  6960. soap->keep_alive = 0;
  6961. }
  6962. #if !defined(WITH_LEAN) || defined(WITH_NTLM)
  6963. else if (!soap_tag_cmp(key, "Authorization") || !soap_tag_cmp(key, "Proxy-Authorization")) {
  6964. #ifdef WITH_NTLM
  6965. if (!soap_tag_cmp(val, "NTLM*"))
  6966. {
  6967. soap->ntlm_challenge = soap_strdup(soap, val + 4);
  6968. }
  6969. else
  6970. #endif
  6971. if (!soap_tag_cmp(val, "Bearer *")) {
  6972. soap->bearer = soap_strdup(soap, val + 7);
  6973. } else if (!soap_tag_cmp(val, "Basic *")) {
  6974. int n;
  6975. char *s;
  6976. soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n);
  6977. soap->tmpbuf[n] = '\0';
  6978. s = strchr(soap->tmpbuf, ':');
  6979. if (s) {
  6980. *s = '\0';
  6981. soap->userid = soap_strdup(soap, soap->tmpbuf);
  6982. soap->passwd = soap_strdup(soap, s + 1);
  6983. }
  6984. }
  6985. } else if (!soap_tag_cmp(key, "WWW-Authenticate") || !soap_tag_cmp(key, "Proxy-Authenticate")) {
  6986. #ifdef WITH_NTLM
  6987. if (!soap_tag_cmp(val, "NTLM*"))
  6988. soap->ntlm_challenge = soap_strdup(soap, val + 4);
  6989. else
  6990. #endif
  6991. soap->authrealm = soap_strdup(soap, soap_http_header_attribute(soap, val + 6, "realm"));
  6992. } else if (!soap_tag_cmp(key, "Expect")) {
  6993. if (!soap_tag_cmp(val, "100-continue")) {
  6994. if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL)) != SOAP_OK
  6995. || (soap->error = soap->fposthdr(soap, NULL, NULL)) != SOAP_OK)
  6996. return soap->error;
  6997. }
  6998. }
  6999. #endif
  7000. else if (!soap_tag_cmp(key, "SOAPAction")) {
  7001. if (*val == '"') {
  7002. soap->action = soap_strdup(soap, val + 1);
  7003. if (*soap->action)
  7004. soap->action[strlen(soap->action) - 1] = '\0';
  7005. } else
  7006. soap->action = soap_strdup(soap, val);
  7007. } else if (!soap_tag_cmp(key, "Location")) {
  7008. soap_strcpy(soap->endpoint, sizeof(soap->endpoint), val);
  7009. } else if (!soap_tag_cmp(key, "X-Forwarded-For")) {
  7010. soap->proxy_from = soap_strdup(soap, val);
  7011. } else if (!soap_tag_cmp(key, "Origin")) {
  7012. soap->origin = soap_strdup(soap, val);
  7013. soap->cors_origin = soap->cors_allow;
  7014. } else if (!soap_tag_cmp(key, "Access-Control-Request-Method")) {
  7015. soap->cors_method = soap_strdup(soap, val);
  7016. } else if (!soap_tag_cmp(key, "Access-Control-Request-Headers")) {
  7017. soap->cors_header = soap_strdup(soap, val);
  7018. }
  7019. #ifdef WITH_COOKIES
  7020. else if (!soap_tag_cmp(key, "Cookie")
  7021. || !soap_tag_cmp(key, "Cookie2")
  7022. || !soap_tag_cmp(key, "Set-Cookie")
  7023. || !soap_tag_cmp(key, "Set-Cookie2"))
  7024. {
  7025. soap_getcookies(soap, val);
  7026. }
  7027. #endif
  7028. return SOAP_OK;
  7029. }
  7030. #endif
  7031. /******************************************************************************/
  7032. #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
  7033. SOAP_FMAC1
  7034. const char *
  7035. SOAP_FMAC2
  7036. soap_http_header_attribute(struct soap *soap, const char *line, const char *key) {
  7037. const char *s = line;
  7038. if (s) {
  7039. while (*s) {
  7040. short flag;
  7041. s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s);
  7042. flag = soap_tag_cmp(soap->tmpbuf, key);
  7043. s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s);
  7044. if (!flag)
  7045. return soap->tmpbuf;
  7046. }
  7047. }
  7048. return NULL;
  7049. }
  7050. #endif
  7051. /******************************************************************************/
  7052. #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
  7053. SOAP_FMAC1
  7054. const char *
  7055. SOAP_FMAC2
  7056. soap_decode_key(char *buf, size_t len, const char *val) {
  7057. return soap_decode(buf, len, val, "=,;");
  7058. }
  7059. #endif
  7060. /******************************************************************************/
  7061. #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
  7062. SOAP_FMAC1
  7063. const char *
  7064. SOAP_FMAC2
  7065. soap_decode_val(char *buf, size_t len, const char *val) {
  7066. if (*val != '=') {
  7067. *buf = '\0';
  7068. return val;
  7069. }
  7070. return soap_decode(buf, len, val + 1, ",;");
  7071. }
  7072. #endif
  7073. /******************************************************************************/
  7074. #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
  7075. static const char *
  7076. soap_decode(char *buf, size_t len, const char *val, const char *sep) {
  7077. const char *s;
  7078. char *t = buf;
  7079. size_t i = len;
  7080. for (s = val; *s; s++)
  7081. if (*s != ' ' && *s != '\t' && !strchr(sep, *s))
  7082. break;
  7083. if (len > 0) {
  7084. if (*s == '"') {
  7085. s++;
  7086. while (*s && *s != '"' && --i)
  7087. *t++ = *s++;
  7088. } else {
  7089. while (*s && !strchr(sep, *s) && --i) {
  7090. if (*s == '%' && s[1] && s[2]) {
  7091. *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4)
  7092. + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0');
  7093. s += 3;
  7094. } else
  7095. *t++ = *s++;
  7096. }
  7097. }
  7098. buf[len - 1] = '\0'; /* appease static checkers that get confused */
  7099. }
  7100. *t = '\0';
  7101. while (*s && !strchr(sep, *s))
  7102. s++;
  7103. return s;
  7104. }
  7105. #endif
  7106. /******************************************************************************/
  7107. #ifndef WITH_NOHTTP
  7108. static const char *
  7109. http_error(struct soap *soap, int status) {
  7110. const char *msg = SOAP_STR_EOS;
  7111. (void) soap;
  7112. (void) status;
  7113. #ifndef WITH_LEAN
  7114. msg = soap_code_str(h_http_error_codes, status);
  7115. if (!msg)
  7116. msg = SOAP_STR_EOS;
  7117. #endif
  7118. return msg;
  7119. }
  7120. #endif
  7121. /******************************************************************************/
  7122. #ifndef WITH_NOHTTP
  7123. static int
  7124. http_get(struct soap *soap) {
  7125. (void) soap;
  7126. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP GET request\n"));
  7127. return SOAP_GET_METHOD;
  7128. }
  7129. #endif
  7130. /******************************************************************************/
  7131. #ifndef WITH_NOHTTP
  7132. static int
  7133. http_put(struct soap *soap) {
  7134. (void) soap;
  7135. return SOAP_PUT_METHOD;
  7136. }
  7137. #endif
  7138. /******************************************************************************/
  7139. #ifndef WITH_NOHTTP
  7140. static int
  7141. http_patch(struct soap *soap) {
  7142. (void) soap;
  7143. return SOAP_PATCH_METHOD;
  7144. }
  7145. #endif
  7146. /******************************************************************************/
  7147. #ifndef WITH_NOHTTP
  7148. static int
  7149. http_del(struct soap *soap) {
  7150. (void) soap;
  7151. return SOAP_DEL_METHOD;
  7152. }
  7153. #endif
  7154. /******************************************************************************/
  7155. #ifndef WITH_NOHTTP
  7156. static int
  7157. http_200(struct soap *soap) {
  7158. if (soap->origin && soap->cors_method) /* CORS Origin and Access-Control-Request-Method headers */
  7159. {
  7160. soap->cors_origin = soap->cors_allow; /* modify this code or hook your own soap->fopt() callback with logic */
  7161. soap->cors_methods = "GET, PUT, PATCH, POST, HEAD, OPTIONS";
  7162. soap->cors_headers = soap->cors_header;
  7163. }
  7164. return soap_send_empty_response(soap, 200);
  7165. }
  7166. #endif
  7167. /******************************************************************************/
  7168. #ifndef WITH_NOHTTP
  7169. static int
  7170. http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action,
  7171. ULONG64 count) {
  7172. const char *s;
  7173. int err;
  7174. size_t l;
  7175. switch (soap->status) {
  7176. case SOAP_GET:
  7177. s = "GET";
  7178. break;
  7179. case SOAP_PUT:
  7180. s = "PUT";
  7181. break;
  7182. case SOAP_PATCH:
  7183. s = "PATCH";
  7184. break;
  7185. case SOAP_DEL:
  7186. s = "DELETE";
  7187. break;
  7188. case SOAP_CONNECT:
  7189. s = "CONNECT";
  7190. break;
  7191. case SOAP_HEAD:
  7192. s = "HEAD";
  7193. break;
  7194. case SOAP_OPTIONS:
  7195. s = "OPTIONS";
  7196. break;
  7197. default:
  7198. s = "POST";
  7199. }
  7200. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP %s to %s\n", s, endpoint ? endpoint : "(null)"));
  7201. if (!endpoint ||
  7202. (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && soap_tag_cmp(endpoint, "httpg:*")))
  7203. return SOAP_OK;
  7204. /* set l to prevent overruns ('host' and 'soap->host' are substrings of 'endpoint') */
  7205. l = strlen(endpoint) + strlen(soap->http_version) + 80;
  7206. if (l > sizeof(soap->tmpbuf))
  7207. return soap->error = SOAP_EOM;
  7208. if (soap->status == SOAP_CONNECT)
  7209. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "%s %s:%d HTTP/%s", s, soap->host, soap->port,
  7210. soap->http_version);
  7211. else if (soap->proxy_host && endpoint)
  7212. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "%s %s HTTP/%s", s, endpoint, soap->http_version);
  7213. else
  7214. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path),
  7215. soap->http_version);
  7216. err = soap->fposthdr(soap, soap->tmpbuf, NULL);
  7217. if (err)
  7218. return err;
  7219. #ifdef WITH_OPENSSL
  7220. if ((soap->ssl && port != 443) || (!soap->ssl && port != 80))
  7221. #else
  7222. if (port != 80)
  7223. #endif
  7224. {
  7225. #ifdef WITH_IPV6
  7226. if (*host != '[' && strchr(host, ':'))
  7227. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "[%s]:%d", host, port); /* RFC 2732 */
  7228. else
  7229. #endif
  7230. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "%s:%d", host, port);
  7231. } else {
  7232. #ifdef WITH_IPV6
  7233. if (*host != '[' && strchr(host, ':'))
  7234. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "[%s]", host); /* RFC 2732 */
  7235. else
  7236. #endif
  7237. soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), host);
  7238. }
  7239. err = soap->fposthdr(soap, "Host", soap->tmpbuf);
  7240. if (err)
  7241. return err;
  7242. err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.8");
  7243. if (err)
  7244. return err;
  7245. if (soap->origin) {
  7246. err = soap->fposthdr(soap, "Origin", soap->origin);
  7247. if (err)
  7248. return err;
  7249. if (soap->status == SOAP_OPTIONS) {
  7250. err = soap->fposthdr(soap, "Access-Control-Request-Method", soap->cors_method ? soap->cors_method : "POST");
  7251. if (err)
  7252. return err;
  7253. if (soap->cors_header) {
  7254. err = soap->fposthdr(soap, "Access-Control-Request-Headers", soap->cors_header);
  7255. if (err)
  7256. return err;
  7257. }
  7258. }
  7259. }
  7260. err = soap_puthttphdr(soap, SOAP_OK, count);
  7261. if (err)
  7262. return err;
  7263. #ifndef WITH_LEANER
  7264. if ((soap->imode & SOAP_ENC_MTOM)) {
  7265. err = soap->fposthdr(soap, "Accept", "multipart/related,application/xop+xml,*/*;q=0.8");
  7266. if (err)
  7267. return err;
  7268. }
  7269. #endif
  7270. #ifdef WITH_ZLIB
  7271. #ifdef WITH_GZIP
  7272. err = soap->fposthdr(soap, "Accept-Encoding", "gzip,deflate");
  7273. #else
  7274. err = soap->fposthdr(soap, "Accept-Encoding", "deflate");
  7275. #endif
  7276. if (err)
  7277. return err;
  7278. #endif
  7279. #if !defined(WITH_LEAN) || defined(WITH_NTLM)
  7280. if (soap->bearer) {
  7281. l = strlen(soap->bearer);
  7282. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l + 1), "Bearer %s", soap->bearer);
  7283. err = soap->fposthdr(soap, "Authorization", soap->tmpbuf);
  7284. if (err)
  7285. return err;
  7286. }
  7287. #ifdef WITH_NTLM
  7288. if (soap->ntlm_challenge)
  7289. {
  7290. l = strlen(soap->ntlm_challenge);
  7291. if (l)
  7292. {
  7293. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l + 5), "NTLM %s", soap->ntlm_challenge);
  7294. if (soap->proxy_host)
  7295. {
  7296. err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf);
  7297. if (err)
  7298. return err;
  7299. }
  7300. else
  7301. {
  7302. err = soap->fposthdr(soap, "Authorization", soap->tmpbuf);
  7303. if (err)
  7304. return err;
  7305. }
  7306. }
  7307. }
  7308. else
  7309. {
  7310. #endif
  7311. if (soap->userid && soap->passwd) {
  7312. soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "Basic ");
  7313. (SOAP_SNPRINTF(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262, strlen(soap->userid) + strlen(soap->passwd) + 1),
  7314. "%s:%s", soap->userid, soap->passwd);
  7315. soap_s2base64(soap, (const unsigned char *) (soap->tmpbuf + 262), soap->tmpbuf + 6,
  7316. (int) strlen(soap->tmpbuf + 262));
  7317. err = soap->fposthdr(soap, "Authorization", soap->tmpbuf);
  7318. if (err)
  7319. return err;
  7320. }
  7321. if (soap->proxy_userid && soap->proxy_passwd) {
  7322. soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "Basic ");
  7323. (SOAP_SNPRINTF(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262,
  7324. strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) + 1), "%s:%s", soap->proxy_userid,
  7325. soap->proxy_passwd);
  7326. soap_s2base64(soap, (const unsigned char *) (soap->tmpbuf + 262), soap->tmpbuf + 6,
  7327. (int) strlen(soap->tmpbuf + 262));
  7328. err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf);
  7329. if (err)
  7330. return err;
  7331. }
  7332. #ifdef WITH_NTLM
  7333. }
  7334. #endif
  7335. #endif
  7336. #ifdef WITH_COOKIES
  7337. #ifdef WITH_OPENSSL
  7338. if (soap_putcookies(soap, host, path, soap->ssl != NULL))
  7339. return soap->error;
  7340. #else
  7341. if (soap_putcookies(soap, host, path, 0))
  7342. return soap->error;
  7343. #endif
  7344. #endif
  7345. if (action && soap->status != SOAP_GET && soap->status != SOAP_DEL) {
  7346. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(action) + 2), "\"%s\"", action);
  7347. err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf);
  7348. if (err)
  7349. return err;
  7350. }
  7351. return soap->fposthdr(soap, NULL, NULL);
  7352. }
  7353. #endif
  7354. /******************************************************************************/
  7355. #ifndef WITH_NOHTTP
  7356. static int
  7357. http_send_header(struct soap *soap, const char *s) {
  7358. const char *t;
  7359. do {
  7360. t = strchr(s, '\n'); /* disallow \n in HTTP headers */
  7361. if (!t)
  7362. t = s + strlen(s);
  7363. if (soap_send_raw(soap, s, t - s))
  7364. return soap->error;
  7365. s = t + 1;
  7366. } while (*t);
  7367. return SOAP_OK;
  7368. }
  7369. #endif
  7370. /******************************************************************************/
  7371. #ifndef WITH_NOHTTP
  7372. static int
  7373. http_post_header(struct soap *soap, const char *key, const char *val) {
  7374. if (key) {
  7375. if (http_send_header(soap, key))
  7376. return soap->error;
  7377. if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val)))
  7378. return soap->error;
  7379. }
  7380. return soap_send_raw(soap, "\r\n", 2);
  7381. }
  7382. #endif
  7383. /******************************************************************************/
  7384. #ifndef WITH_NOHTTP
  7385. static int
  7386. http_response(struct soap *soap, int status, ULONG64 count) {
  7387. int err;
  7388. char http[32];
  7389. int code = status;
  7390. const char *line;
  7391. #ifdef WMW_RPM_IO
  7392. if (soap->rpmreqid)
  7393. httpOutputEnable(soap->rpmreqid);
  7394. if (soap->rpmreqid
  7395. || soap_valid_socket(soap->master)
  7396. || soap_valid_socket(soap->socket)
  7397. || soap->recvfd != 0
  7398. || soap->sendfd != 1
  7399. || soap->os) /* RPM behaves as if standalone */
  7400. #else
  7401. if (soap_valid_socket(soap->master)
  7402. || soap_valid_socket(soap->socket)
  7403. #ifndef UNDER_CE
  7404. || soap->recvfd != 0
  7405. || soap->sendfd != 1
  7406. #else
  7407. || soap->recvfd != stdin
  7408. || soap->sendfd != stdout
  7409. #endif
  7410. || soap->os) /* standalone server application (over sockets), not CGI (over stdin/out) */
  7411. #endif
  7412. (SOAP_SNPRINTF(http, sizeof(http), strlen(soap->http_version) + 5), "HTTP/%s", soap->http_version);
  7413. else
  7414. soap_strcpy(http, sizeof(http), "Status:");
  7415. if (status >= SOAP_FILE && status < SOAP_FILE + 600) {
  7416. code = status - SOAP_FILE;
  7417. if (code == 0)
  7418. code = 200;
  7419. } else if (!status || status == SOAP_HTML) {
  7420. if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
  7421. code = 200;
  7422. else
  7423. code = 202;
  7424. } else if (status < 200 || status >= 600) {
  7425. const char *s = *soap_faultcode(soap);
  7426. if (status >= SOAP_GET_METHOD && status <= SOAP_HTTP_METHOD)
  7427. code = 405;
  7428. else if (soap->version == 2 && (!s || !strcmp(s, "SOAP-ENV:Sender")))
  7429. code = 400;
  7430. else
  7431. code = 500;
  7432. }
  7433. line = http_error(soap, code);
  7434. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP Status = %d %s\n", code, line));
  7435. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), sizeof(http) + 22 + strlen(line)), "%s %d %s", http, code, line);
  7436. err = soap->fposthdr(soap, soap->tmpbuf, NULL);
  7437. if (err)
  7438. return err;
  7439. #ifndef WITH_LEAN
  7440. if (status == 401) {
  7441. (SOAP_SNPRINTF_SAFE(soap->tmpbuf, sizeof(soap->tmpbuf)), "Basic realm=\"%s\"", (soap->authrealm &&
  7442. strlen(soap->authrealm) + 14 <
  7443. sizeof(soap->tmpbuf))
  7444. ? soap->authrealm
  7445. : "gSOAP Web Service");
  7446. err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf);
  7447. if (err)
  7448. return err;
  7449. } else if ((status >= 301 && status <= 303) || status == 307) {
  7450. err = soap->fposthdr(soap, "Location", soap->endpoint);
  7451. if (err)
  7452. return err;
  7453. }
  7454. #endif
  7455. err = soap->fposthdr(soap, "Server", "ACS/1.1 By Sassan");
  7456. // err = soap->fposthdr(soap, "Server", "gSOAP/2.8");
  7457. if (err)
  7458. return err;
  7459. if (soap->cors_origin) {
  7460. err = soap->fposthdr(soap, "Access-Control-Allow-Origin", soap->cors_origin);
  7461. if (err)
  7462. return err;
  7463. err = soap->fposthdr(soap, "Access-Control-Allow-Credentials", "true");
  7464. if (err)
  7465. return err;
  7466. if (soap->cors_methods) {
  7467. err = soap->fposthdr(soap, "Access-Control-Allow-Methods", soap->cors_methods);
  7468. if (err)
  7469. return err;
  7470. if (soap->cors_headers) {
  7471. err = soap->fposthdr(soap, "Access-Control-Allow-Headers", soap->cors_headers);
  7472. if (err)
  7473. return err;
  7474. }
  7475. }
  7476. }
  7477. if (soap->x_frame_options) {
  7478. err = soap->fposthdr(soap, "X-Frame-Options", soap->x_frame_options);
  7479. if (err)
  7480. return err;
  7481. }
  7482. soap->cors_origin = NULL;
  7483. soap->cors_methods = NULL;
  7484. soap->cors_headers = NULL;
  7485. err = soap_puthttphdr(soap, status, count);
  7486. if (err)
  7487. return err;
  7488. #ifdef WITH_COOKIES
  7489. if (soap_putsetcookies(soap))
  7490. return soap->error;
  7491. soap_free_cookies(soap);
  7492. #endif
  7493. return soap->fposthdr(soap, NULL, NULL);
  7494. }
  7495. #endif
  7496. /******************************************************************************/
  7497. SOAP_FMAC1
  7498. int
  7499. SOAP_FMAC2
  7500. soap_response(struct soap *soap, int status) {
  7501. ULONG64 count;
  7502. if (!(soap->omode & (SOAP_ENC_PLAIN | SOAP_IO_STORE /* this tests for chunking too */))
  7503. && (status == SOAP_HTML || (status >= SOAP_FILE && status < SOAP_FILE + 600)))
  7504. soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE;
  7505. soap->status = status;
  7506. count = soap_count_attachments(soap);
  7507. if (soap_init_send(soap))
  7508. return soap->error;
  7509. #ifndef WITH_NOHTTP
  7510. if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_PLAIN)) {
  7511. int k = soap->mode;
  7512. soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
  7513. if ((k & SOAP_IO) != SOAP_IO_FLUSH)
  7514. soap->mode |= SOAP_IO_BUFFER;
  7515. soap->error = soap->fresponse(soap, status, count);
  7516. if (soap->error)
  7517. return soap->error;
  7518. #ifndef WITH_LEANER
  7519. if ((k & SOAP_IO) == SOAP_IO_CHUNK) {
  7520. if (soap_flush(soap))
  7521. return soap->error;
  7522. }
  7523. #endif
  7524. soap->mode = k;
  7525. }
  7526. #endif
  7527. #ifndef WITH_LEANER
  7528. if (soap_begin_attachments(soap))
  7529. return soap->error;
  7530. #endif
  7531. return SOAP_OK;
  7532. }
  7533. /******************************************************************************/
  7534. SOAP_FMAC1
  7535. const char *
  7536. SOAP_FMAC2
  7537. soap_extend_url(struct soap *soap, const char *s, const char *t) {
  7538. if (s)
  7539. soap_strcpy(soap->msgbuf, sizeof(soap->msgbuf), s);
  7540. else
  7541. *soap->msgbuf = '\0';
  7542. if (t && (*t == '/' || *t == '?')) {
  7543. char *r = strchr(soap->msgbuf, '?');
  7544. if (r) {
  7545. if (*t == '?') {
  7546. soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), "&");
  7547. soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), t + 1);
  7548. } else /* *t == '/' */
  7549. {
  7550. size_t l = r - soap->msgbuf;
  7551. *r = '\0';
  7552. soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), t);
  7553. if (s)
  7554. soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), s + l);
  7555. }
  7556. } else {
  7557. soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), t);
  7558. }
  7559. }
  7560. return soap->msgbuf;
  7561. }
  7562. /******************************************************************************/
  7563. SOAP_FMAC1
  7564. const char *
  7565. SOAP_FMAC2
  7566. soap_extend_url_query(struct soap *soap, const char *s, const char *t) {
  7567. (void) soap_extend_url(soap, s, t); /* fills and returns soap->msgbuf */
  7568. if (strchr(soap->msgbuf, '?'))
  7569. soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), "&");
  7570. else
  7571. soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), "?");
  7572. return soap->msgbuf;
  7573. }
  7574. /******************************************************************************/
  7575. SOAP_FMAC1
  7576. void
  7577. SOAP_FMAC2
  7578. soap_url_query(struct soap *soap, const char *s, const char *t) {
  7579. size_t n = strlen(s);
  7580. if (n) {
  7581. char *r = soap->msgbuf;
  7582. size_t k = n - (s[n - 1] == '=');
  7583. while ((r = strchr(r, '{')) != NULL)
  7584. if (!strncmp(++r, s, k) && r[k] == '}')
  7585. break;
  7586. if (r) {
  7587. size_t m = t ? strlen(t) : 0;
  7588. (void) soap_memmove(r + m - 1, soap->msgbuf + sizeof(soap->msgbuf) - (r + n + 1), r + k + 1,
  7589. strlen(r + k + 1) + 1);
  7590. if (m)
  7591. (void) soap_memmove(r - 1, soap->msgbuf + sizeof(soap->msgbuf) - (r - 1), t, m);
  7592. } else {
  7593. soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), s);
  7594. if (t) {
  7595. int m = (int) strlen(soap->msgbuf); /* msgbuf length is max SOAP_TMPLEN or just 1024 bytes */
  7596. (void) soap_encode_url(t, soap->msgbuf + m, (int) sizeof(soap->msgbuf) - m);
  7597. }
  7598. soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), "&");
  7599. }
  7600. }
  7601. }
  7602. /******************************************************************************/
  7603. SOAP_FMAC1
  7604. int
  7605. SOAP_FMAC2
  7606. soap_encode_url(const char *s, char *t, int len) {
  7607. int c;
  7608. int n = len;
  7609. if (s && n > 0) {
  7610. while ((c = *s++) && --n > 0) {
  7611. if (c == '-'
  7612. || c == '.'
  7613. || (c >= '0' && c <= '9')
  7614. || (c >= 'A' && c <= 'Z')
  7615. || c == '_'
  7616. || (c >= 'a' && c <= 'z')
  7617. || c == '~') {
  7618. *t++ = c;
  7619. } else if (n > 2) {
  7620. *t++ = '%';
  7621. *t++ = (c >> 4) + (c > 159 ? '7' : '0');
  7622. c &= 0xF;
  7623. *t++ = c + (c > 9 ? '7' : '0');
  7624. n -= 2;
  7625. } else {
  7626. break;
  7627. }
  7628. }
  7629. *t = '\0';
  7630. }
  7631. return len - n;
  7632. }
  7633. /******************************************************************************/
  7634. SOAP_FMAC1
  7635. const char *
  7636. SOAP_FMAC2
  7637. soap_encode_url_string(struct soap *soap, const char *s) {
  7638. if (s) {
  7639. int n = 3 * (int) strlen(s) + 1;
  7640. char *t = (char *) soap_malloc(soap, n);
  7641. if (t) {
  7642. (void) soap_encode_url(s, t, n);
  7643. return t;
  7644. }
  7645. }
  7646. return SOAP_STR_EOS;
  7647. }
  7648. /******************************************************************************\
  7649. *
  7650. * HTTP Cookies RFC 6265
  7651. *
  7652. \******************************************************************************/
  7653. #ifdef WITH_COOKIES
  7654. SOAP_FMAC1
  7655. struct soap_cookie*
  7656. SOAP_FMAC2
  7657. soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
  7658. {
  7659. return soap_cookie_env(soap, name, domain, path, 0);
  7660. }
  7661. /******************************************************************************/
  7662. SOAP_FMAC1
  7663. struct soap_cookie*
  7664. SOAP_FMAC2
  7665. soap_cookie_env(struct soap *soap, const char *name, const char *domain, const char *path, short env)
  7666. {
  7667. struct soap_cookie *p;
  7668. if (!domain && !env)
  7669. domain = soap->cookie_domain;
  7670. if (!path)
  7671. path = soap->cookie_path;
  7672. if (!path)
  7673. path = SOAP_STR_EOS;
  7674. else if (*path == '/')
  7675. path++;
  7676. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie='%s' domain='%s' path='%s' env=%hd\n", name, domain ? domain : "(null)", path ? path : "(null)", env));
  7677. for (p = soap->cookies; p; p = p->next)
  7678. {
  7679. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie in database: %s='%s' domain='%s' path='%s' env=%hd\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->env));
  7680. if ((!env || p->env)
  7681. && !strcmp(p->name, name)
  7682. && (!domain || (domain && p->domain && !strcmp(p->domain, domain)))
  7683. && (!path || (path && p->path && !strncmp(p->path, path, strlen(p->path)))))
  7684. break;
  7685. }
  7686. return p;
  7687. }
  7688. /******************************************************************************/
  7689. SOAP_FMAC1
  7690. struct soap_cookie*
  7691. SOAP_FMAC2
  7692. soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path)
  7693. {
  7694. struct soap_cookie **p, *q;
  7695. int n;
  7696. if (!domain)
  7697. domain = soap->cookie_domain;
  7698. if (!path)
  7699. path = soap->cookie_path;
  7700. if (!path)
  7701. path = SOAP_STR_EOS;
  7702. else if (*path == '/')
  7703. path++;
  7704. q = soap_cookie(soap, name, domain, path);
  7705. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set %scookie: %s='%s' domain='%s' path='%s'\n", q ? SOAP_STR_EOS : "new ", name, value ? value : "(null)", domain ? domain : "(null)", path ? path : "(null)"));
  7706. if (!q)
  7707. {
  7708. q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie));
  7709. if (q)
  7710. {
  7711. size_t l = strlen(name) + 1;
  7712. q->name = NULL;
  7713. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  7714. q->name = (char*)SOAP_MALLOC(soap, l);
  7715. if (q->name)
  7716. (void)soap_memcpy(q->name, l, name, l);
  7717. q->value = NULL;
  7718. q->domain = NULL;
  7719. q->path = NULL;
  7720. q->expire = 0;
  7721. q->maxage = -1;
  7722. q->version = 1;
  7723. q->secure = 0;
  7724. q->modified = 0;
  7725. for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--)
  7726. if (!strcmp((*p)->name, name) && (*p)->path && path && strcmp((*p)->path, path) < 0)
  7727. break;
  7728. if (n)
  7729. {
  7730. q->next = *p;
  7731. *p = q;
  7732. }
  7733. else
  7734. {
  7735. SOAP_FREE(soap, q->name);
  7736. SOAP_FREE(soap, q);
  7737. q = NULL;
  7738. }
  7739. }
  7740. }
  7741. else
  7742. {
  7743. q->modified = 1;
  7744. }
  7745. if (q)
  7746. {
  7747. if (q->value)
  7748. {
  7749. if (!value || strcmp(value, q->value))
  7750. {
  7751. SOAP_FREE(soap, q->value);
  7752. q->value = NULL;
  7753. }
  7754. }
  7755. if (value && *value && !q->value)
  7756. {
  7757. size_t l = strlen(value) + 1;
  7758. q->value = NULL;
  7759. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  7760. q->value = (char*)SOAP_MALLOC(soap, l);
  7761. if (q->value)
  7762. soap_strcpy(q->value, l, value);
  7763. }
  7764. if (q->domain)
  7765. {
  7766. if (!domain || strcmp(domain, q->domain))
  7767. {
  7768. SOAP_FREE(soap, q->domain);
  7769. q->domain = NULL;
  7770. }
  7771. }
  7772. if (domain && !q->domain)
  7773. {
  7774. size_t l = strlen(domain) + 1;
  7775. q->domain = NULL;
  7776. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  7777. q->domain = (char*)SOAP_MALLOC(soap, l);
  7778. if (q->domain)
  7779. soap_strcpy(q->domain, l, domain);
  7780. }
  7781. if (q->path)
  7782. {
  7783. if (!path || strncmp(path, q->path, strlen(q->path)))
  7784. {
  7785. SOAP_FREE(soap, q->path);
  7786. q->path = NULL;
  7787. }
  7788. }
  7789. if (path && !q->path)
  7790. {
  7791. size_t l = strlen(path) + 1;
  7792. q->path = NULL;
  7793. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  7794. q->path = (char*)SOAP_MALLOC(soap, l);
  7795. if (q->path)
  7796. soap_strcpy(q->path, l, path);
  7797. }
  7798. q->session = 1;
  7799. q->env = 0;
  7800. }
  7801. return q;
  7802. }
  7803. /******************************************************************************/
  7804. SOAP_FMAC1
  7805. void
  7806. SOAP_FMAC2
  7807. soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
  7808. {
  7809. struct soap_cookie **p, *q;
  7810. if (!domain)
  7811. domain = soap->cookie_domain;
  7812. if (!domain)
  7813. {
  7814. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie='%s': cookie domain not set\n", name ? name : "(null)"));
  7815. return;
  7816. }
  7817. if (!path)
  7818. path = soap->cookie_path;
  7819. if (!path)
  7820. path = SOAP_STR_EOS;
  7821. else if (*path == '/')
  7822. path++;
  7823. for (p = &soap->cookies, q = *p; q; q = *p)
  7824. {
  7825. if (!strcmp(q->name, name) && (!q->domain || !strcmp(q->domain, domain)) && (!q->path || !strncmp(q->path, path, strlen(q->path))))
  7826. {
  7827. SOAP_FREE(soap, q->name);
  7828. if (q->value)
  7829. SOAP_FREE(soap, q->value);
  7830. if (q->domain)
  7831. SOAP_FREE(soap, q->domain);
  7832. if (q->path)
  7833. SOAP_FREE(soap, q->path);
  7834. *p = q->next;
  7835. SOAP_FREE(soap, q);
  7836. }
  7837. else
  7838. p = &q->next;
  7839. }
  7840. }
  7841. /******************************************************************************/
  7842. SOAP_FMAC1
  7843. const char *
  7844. SOAP_FMAC2
  7845. soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
  7846. {
  7847. struct soap_cookie *p;
  7848. p = soap_cookie(soap, name, domain, path);
  7849. if (p)
  7850. return p->value;
  7851. return NULL;
  7852. }
  7853. /******************************************************************************/
  7854. SOAP_FMAC1
  7855. const char *
  7856. SOAP_FMAC2
  7857. soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
  7858. {
  7859. struct soap_cookie *p;
  7860. p = soap_cookie(soap, name, domain, path);
  7861. if (p && p->env)
  7862. return p->value;
  7863. return NULL;
  7864. }
  7865. /******************************************************************************/
  7866. SOAP_FMAC1
  7867. time_t
  7868. SOAP_FMAC2
  7869. soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path)
  7870. {
  7871. struct soap_cookie *p;
  7872. p = soap_cookie(soap, name, domain, path);
  7873. if (p)
  7874. return (time_t)p->expire;
  7875. return -1;
  7876. }
  7877. /******************************************************************************/
  7878. SOAP_FMAC1
  7879. int
  7880. SOAP_FMAC2
  7881. soap_set_cookie_expire(struct soap *soap, const char *name, long maxage, const char *domain, const char *path)
  7882. {
  7883. struct soap_cookie *p;
  7884. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie expiration max-age=%ld: cookie='%s' domain='%s' path='%s'\n", maxage, name, domain ? domain : "(null)", path ? path : "(null)"));
  7885. p = soap_cookie(soap, name, domain, path);
  7886. if (p)
  7887. {
  7888. p->maxage = maxage;
  7889. p->modified = 1;
  7890. return SOAP_OK;
  7891. }
  7892. return SOAP_ERR;
  7893. }
  7894. /******************************************************************************/
  7895. SOAP_FMAC1
  7896. int
  7897. SOAP_FMAC2
  7898. soap_set_cookie_secure(struct soap *soap, const char *name, const char *domain, const char *path)
  7899. {
  7900. struct soap_cookie *p;
  7901. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie secure: cookie='%s' domain='%s' path='%s'\n", name, domain ? domain : "(null)", path ? path : "(null)"));
  7902. p = soap_cookie(soap, name, domain, path);
  7903. if (p)
  7904. {
  7905. p->secure = 1;
  7906. p->modified = 1;
  7907. return SOAP_OK;
  7908. }
  7909. return SOAP_ERR;
  7910. }
  7911. /******************************************************************************/
  7912. SOAP_FMAC1
  7913. int
  7914. SOAP_FMAC2
  7915. soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
  7916. {
  7917. struct soap_cookie *p;
  7918. p = soap_cookie(soap, name, domain, path);
  7919. if (p)
  7920. {
  7921. p->session = 1;
  7922. p->modified = 1;
  7923. return SOAP_OK;
  7924. }
  7925. return SOAP_ERR;
  7926. }
  7927. /******************************************************************************/
  7928. SOAP_FMAC1
  7929. int
  7930. SOAP_FMAC2
  7931. soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
  7932. {
  7933. struct soap_cookie *p;
  7934. p = soap_cookie(soap, name, domain, path);
  7935. if (p)
  7936. {
  7937. p->session = 0;
  7938. p->modified = 1;
  7939. return SOAP_OK;
  7940. }
  7941. return SOAP_ERR;
  7942. }
  7943. /******************************************************************************/
  7944. SOAP_FMAC1
  7945. int
  7946. SOAP_FMAC2
  7947. soap_putsetcookies(struct soap *soap)
  7948. {
  7949. struct soap_cookie *p;
  7950. char *s, tmp[4096];
  7951. const char *t;
  7952. for (p = soap->cookies; p; p = p->next)
  7953. {
  7954. if ((p->modified
  7955. #ifdef WITH_OPENSSL
  7956. || (!p->env && !soap->ssl == !p->secure)
  7957. #endif
  7958. ) && p->name && p->value && *p->name && *p->value)
  7959. {
  7960. s = tmp;
  7961. s += soap_encode_url(p->name, s, 3967);
  7962. *s++ = '=';
  7963. s += soap_encode_url(p->value, s, 3968 - (int)(s-tmp));
  7964. t = p->domain ? p->domain : soap->cookie_domain;
  7965. if (t && (int)strlen(t) < 3968 - (int)(s-tmp))
  7966. {
  7967. soap_strcpy(s, 4096 - (s-tmp), ";Domain=");
  7968. s += 8;
  7969. soap_strcpy(s, 4096 - (s-tmp), t);
  7970. s += strlen(s);
  7971. }
  7972. t = p->path ? p->path : soap->cookie_path;
  7973. if (t && (int)strlen(t) < 3976 - (int)(s-tmp))
  7974. {
  7975. soap_strcpy(s, 4096 - (s-tmp), ";Path=/");
  7976. s += 7;
  7977. if (*t == '/')
  7978. t++;
  7979. if (strchr(t, '%')) /* already URL encoded? */
  7980. {
  7981. soap_strcpy(s, 4096 - (s-tmp), t);
  7982. s += strlen(s);
  7983. }
  7984. else
  7985. {
  7986. s += soap_encode_url(t, s, 4096 - (int)(s-tmp));
  7987. }
  7988. }
  7989. if (p->version > 0 && s-tmp < 3983)
  7990. {
  7991. (SOAP_SNPRINTF(s, 4096 - (s-tmp), 29), ";Version=%u", p->version);
  7992. s += strlen(s);
  7993. }
  7994. if (p->maxage >= 0 && s-tmp < 4012)
  7995. {
  7996. (SOAP_SNPRINTF(s, 4096 - (s-tmp), 29), ";Max-Age=%ld", p->maxage);
  7997. s += strlen(s);
  7998. }
  7999. #if !defined(WITH_LEAN)
  8000. #if defined(HAVE_GMTIME_R) || defined(HAVE_GMTIME)
  8001. if (p->maxage >= 0 && s-tmp < 4041)
  8002. {
  8003. time_t n = time(NULL) + p->maxage;
  8004. struct tm T, *pT = &T;
  8005. size_t l = 0;
  8006. /* format is Wed, 09 Jun 2021 10:18:14 GMT */
  8007. #if defined(HAVE_GMTIME_R)
  8008. if (gmtime_r(&n, pT) != SOAP_FUNC_R_ERR)
  8009. l = strftime(s, 4096 - (s-tmp), ";Expires=%a, %d %b %Y %H:%M:%S GMT", pT);
  8010. #else
  8011. pT = gmtime(&n);
  8012. if (pT)
  8013. l = strftime(s, 4096 - (s-tmp), ";Expires=%a, %d %b %Y %H:%M:%S GMT", pT);
  8014. #endif
  8015. s += l;
  8016. }
  8017. #endif
  8018. #endif
  8019. if (s-tmp < 4079
  8020. && (p->secure
  8021. #ifdef WITH_OPENSSL
  8022. || soap->ssl
  8023. #endif
  8024. ))
  8025. {
  8026. soap_strcpy(s, 4096 - (s-tmp), ";Secure");
  8027. s += strlen(s);
  8028. }
  8029. if (s-tmp < 4086)
  8030. soap_strcpy(s, 4096 - (s-tmp), ";HttpOnly");
  8031. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp));
  8032. soap->error = soap->fposthdr(soap, "Set-Cookie", tmp);
  8033. if (soap->error)
  8034. return soap->error;
  8035. }
  8036. }
  8037. return SOAP_OK;
  8038. }
  8039. /******************************************************************************/
  8040. SOAP_FMAC1
  8041. int
  8042. SOAP_FMAC2
  8043. soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure)
  8044. {
  8045. struct soap_cookie **p, *q;
  8046. char *s, tmp[4096];
  8047. unsigned int version = 0;
  8048. time_t now = time(NULL);
  8049. if (!domain || !path)
  8050. return SOAP_OK;
  8051. s = tmp;
  8052. p = &soap->cookies;
  8053. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain='%s' path='%s'\n", domain, path));
  8054. if (*path == '/')
  8055. path++;
  8056. while ((q = *p))
  8057. {
  8058. if (q->expire && now >= (time_t)q->expire)
  8059. {
  8060. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name));
  8061. SOAP_FREE(soap, q->name);
  8062. if (q->value)
  8063. SOAP_FREE(soap, q->value);
  8064. if (q->domain)
  8065. SOAP_FREE(soap, q->domain);
  8066. if (q->path)
  8067. SOAP_FREE(soap, q->path);
  8068. *p = q->next;
  8069. SOAP_FREE(soap, q);
  8070. }
  8071. else
  8072. {
  8073. int flag;
  8074. char *t = q->domain;
  8075. size_t n = 0;
  8076. if (!t)
  8077. flag = 1;
  8078. else
  8079. {
  8080. const char *r = strchr(t, ':');
  8081. if (r)
  8082. n = r - t;
  8083. else
  8084. n = strlen(t);
  8085. flag = !strncmp(t, domain, n);
  8086. }
  8087. /* domain-level cookies, cannot compile when WITH_NOIO set */
  8088. #ifndef WITH_NOIO
  8089. if (!flag)
  8090. {
  8091. struct hostent hostent;
  8092. if (!tcp_gethostbyname(soap, (char*)domain, &hostent, NULL))
  8093. {
  8094. const char *r = hostent.h_name;
  8095. if (*t == '.')
  8096. {
  8097. size_t k = strlen(hostent.h_name);
  8098. if (k >= n)
  8099. r = hostent.h_name + k - n;
  8100. }
  8101. flag = !strncmp(t, r, n);
  8102. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Domain cookie %s host %s (match=%d)\n", t, r, flag));
  8103. }
  8104. }
  8105. #endif
  8106. if (flag
  8107. && (!q->path || !strncmp(q->path, path, strlen(q->path)))
  8108. #ifndef WITH_INSECURE_COOKIES
  8109. && (!q->secure || secure)
  8110. #endif
  8111. )
  8112. {
  8113. size_t n = 12;
  8114. if (q->name)
  8115. n += 3*strlen(q->name);
  8116. if (q->value && *q->value)
  8117. n += 3*strlen(q->value) + 1;
  8118. if (q->path && *q->path)
  8119. n += strlen(q->path) + 9;
  8120. if (q->domain)
  8121. n += strlen(q->domain) + 11;
  8122. if (s + n >= tmp + sizeof(tmp))
  8123. {
  8124. if (s == tmp)
  8125. return SOAP_OK; /* header too big, cannot split */
  8126. /* split up HTTP header */
  8127. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp));
  8128. soap->error = soap->fposthdr(soap, "Cookie", tmp);
  8129. if (soap->error)
  8130. return soap->error;
  8131. s = tmp;
  8132. }
  8133. else if (s != tmp)
  8134. {
  8135. *s++ = ';';
  8136. }
  8137. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookie %s=%s path=\"/%s\" domain=\"%s\"\n", q->name ? q->name : "(null)", q->value ? q->value : "(null)", q->path ? q->path : "(null)", q->domain ? q->domain : "(null)"));
  8138. if (q->version != version && (s-tmp) + (size_t)36 < sizeof(tmp))
  8139. {
  8140. (SOAP_SNPRINTF_SAFE(s, sizeof(tmp) - (s-tmp)), "$Version=%u;", q->version);
  8141. version = q->version;
  8142. s += strlen(s);
  8143. }
  8144. if (q->name && (s-tmp) + strlen(q->name) + (size_t)15 < sizeof(tmp))
  8145. {
  8146. s += soap_encode_url(q->name, s, (int)(tmp+sizeof(tmp)-s)-15);
  8147. }
  8148. if (q->value && *q->value && (s-tmp) + strlen(q->value) + (size_t)16 < sizeof(tmp))
  8149. {
  8150. *s++ = '=';
  8151. s += soap_encode_url(q->value, s, (int)(tmp+sizeof(tmp)-s)-16);
  8152. }
  8153. if (q->path && (s-tmp) + strlen(q->path) + (size_t)36 < sizeof(tmp))
  8154. {
  8155. (SOAP_SNPRINTF_SAFE(s, sizeof(tmp) - (s-tmp)), ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path));
  8156. s += strlen(s);
  8157. }
  8158. if (q->domain && (s-tmp) + strlen(q->domain) + (size_t)36 < sizeof(tmp))
  8159. {
  8160. (SOAP_SNPRINTF_SAFE(s, sizeof(tmp) - (s-tmp)), ";$Domain=\"%s\"", q->domain);
  8161. s += strlen(s);
  8162. }
  8163. }
  8164. p = &q->next;
  8165. }
  8166. }
  8167. if (s != tmp)
  8168. {
  8169. soap->error = soap->fposthdr(soap, "Cookie", tmp);
  8170. if (soap->error)
  8171. return soap->error;
  8172. }
  8173. return SOAP_OK;
  8174. }
  8175. /******************************************************************************/
  8176. SOAP_FMAC1
  8177. void
  8178. SOAP_FMAC2
  8179. soap_getcookies(struct soap *soap, const char *val)
  8180. {
  8181. struct soap_cookie *p = NULL, *q;
  8182. const char *s;
  8183. char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
  8184. char *domain = NULL;
  8185. char *path = NULL;
  8186. unsigned int version = 0;
  8187. time_t now = time(NULL);
  8188. if (!val)
  8189. return;
  8190. s = val;
  8191. while (*s)
  8192. {
  8193. s = soap_decode_key(tmp, sizeof(tmp), s);
  8194. if (!soap_tag_cmp(tmp, "$Version"))
  8195. {
  8196. s = soap_decode_val(tmp, sizeof(tmp), s);
  8197. if (s)
  8198. {
  8199. if (p)
  8200. p->version = (int)soap_strtol(tmp, NULL, 10);
  8201. else
  8202. version = (int)soap_strtol(tmp, NULL, 10);
  8203. }
  8204. }
  8205. else if (!soap_tag_cmp(tmp, "$Path"))
  8206. {
  8207. s = soap_decode_val(tmp, sizeof(tmp), s);
  8208. if (*tmp)
  8209. {
  8210. size_t l = strlen(tmp) + 1;
  8211. t = NULL;
  8212. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8213. t = (char*)SOAP_MALLOC(soap, l);
  8214. if (t)
  8215. (void)soap_memcpy((void*)t, l, (const void*)tmp, l);
  8216. }
  8217. else
  8218. {
  8219. t = NULL;
  8220. }
  8221. if (p)
  8222. {
  8223. if (p->path)
  8224. SOAP_FREE(soap, p->path);
  8225. p->path = t;
  8226. }
  8227. else
  8228. {
  8229. if (path)
  8230. SOAP_FREE(soap, path);
  8231. path = t;
  8232. }
  8233. }
  8234. else if (!soap_tag_cmp(tmp, "$Domain"))
  8235. {
  8236. s = soap_decode_val(tmp, sizeof(tmp), s);
  8237. if (*tmp)
  8238. {
  8239. size_t l = strlen(tmp) + 1;
  8240. t = NULL;
  8241. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8242. t = (char*)SOAP_MALLOC(soap, l);
  8243. if (t)
  8244. (void)soap_memcpy((void*)t, l, (const void*)tmp, l);
  8245. }
  8246. else
  8247. {
  8248. t = NULL;
  8249. }
  8250. if (p)
  8251. {
  8252. if (p->domain)
  8253. SOAP_FREE(soap, p->domain);
  8254. p->domain = t;
  8255. }
  8256. else
  8257. {
  8258. if (domain)
  8259. SOAP_FREE(soap, domain);
  8260. domain = t;
  8261. }
  8262. }
  8263. else if (p && !soap_tag_cmp(tmp, "Path"))
  8264. {
  8265. if (p->path)
  8266. SOAP_FREE(soap, p->path);
  8267. s = soap_decode_val(tmp, sizeof(tmp), s);
  8268. if (*tmp)
  8269. {
  8270. size_t l = strlen(tmp) + 1;
  8271. p->path = NULL;
  8272. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8273. p->path = (char*)SOAP_MALLOC(soap, l);
  8274. if (p->path)
  8275. (void)soap_memcpy((void*)p->path, l, (const void*)tmp, l);
  8276. }
  8277. else
  8278. {
  8279. p->path = NULL;
  8280. }
  8281. }
  8282. else if (p && !soap_tag_cmp(tmp, "Domain"))
  8283. {
  8284. if (p->domain)
  8285. SOAP_FREE(soap, p->domain);
  8286. s = soap_decode_val(tmp, sizeof(tmp), s);
  8287. if (*tmp)
  8288. {
  8289. size_t l = strlen(tmp) + 1;
  8290. p->domain = NULL;
  8291. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8292. p->domain = (char*)SOAP_MALLOC(soap, l);
  8293. if (p->domain)
  8294. (void)soap_memcpy((void*)p->domain, l, (const void*)tmp, l);
  8295. }
  8296. else
  8297. {
  8298. p->domain = NULL;
  8299. }
  8300. }
  8301. else if (p && !soap_tag_cmp(tmp, "Version"))
  8302. {
  8303. s = soap_decode_val(tmp, sizeof(tmp), s);
  8304. p->version = (unsigned int)soap_strtoul(tmp, NULL, 10);
  8305. }
  8306. else if (p && !soap_tag_cmp(tmp, "Max-Age"))
  8307. {
  8308. s = soap_decode_val(tmp, sizeof(tmp), s);
  8309. p->expire = (ULONG64)(now + soap_strtol(tmp, NULL, 10));
  8310. }
  8311. else if (p && !soap_tag_cmp(tmp, "Expires"))
  8312. {
  8313. if (*s == '=')
  8314. {
  8315. s = soap_decode(tmp, sizeof(tmp), s + 1, ";");
  8316. if (!p->expire && strlen(tmp) >= 23)
  8317. {
  8318. char a[3];
  8319. struct tm T;
  8320. static const char mns[] = "anebarprayunulugepctovec";
  8321. const char *t = strchr(tmp, ' ');
  8322. if (t)
  8323. {
  8324. a[2] = '\0';
  8325. memset((void*)&T, 0, sizeof(T));
  8326. if (t[1] >= 'A')
  8327. {
  8328. /* format is Sun Nov 6 08:49:37 94 */
  8329. a[0] = t[2];
  8330. a[1] = t[3];
  8331. T.tm_mon = (int)(strstr(mns, a) - mns) / 2;
  8332. a[0] = t[5];
  8333. a[1] = t[6];
  8334. T.tm_mday = (int)soap_strtol(a, NULL, 10);
  8335. if (t[17] && t[18] && t[19] != ' ')
  8336. t += 2; /* format is Sun Nov 6 08:49:37 2017 - ANSI-C */
  8337. a[0] = t[17];
  8338. a[1] = t[18];
  8339. T.tm_year = 100 + (int)soap_strtol(a, NULL, 10);
  8340. t += 6;
  8341. }
  8342. else
  8343. {
  8344. /* format is Sunday, 06-Nov-17 08:49:37 GMT - RFC 850 */
  8345. a[0] = t[1];
  8346. a[1] = t[2];
  8347. T.tm_mday = (int)soap_strtol(a, NULL, 10);
  8348. a[0] = t[5];
  8349. a[1] = t[6];
  8350. T.tm_mon = (int)(strstr(mns, a) - mns) / 2;
  8351. if (t[10] != ' ')
  8352. t += 2; /* format is Wed, 09 Jun 2021 10:18:14 GMT - RFC 822 */
  8353. a[0] = t[8];
  8354. a[1] = t[9];
  8355. T.tm_year = 100 + (int)soap_strtol(a, NULL, 10);
  8356. t += 11;
  8357. }
  8358. a[0] = t[0];
  8359. a[1] = t[1];
  8360. T.tm_hour = (int)soap_strtol(a, NULL, 10);
  8361. a[0] = t[3];
  8362. a[1] = t[4];
  8363. T.tm_min = (int)soap_strtol(a, NULL, 10);
  8364. a[0] = t[6];
  8365. a[1] = t[7];
  8366. T.tm_sec = (int)soap_strtol(a, NULL, 10);
  8367. p->expire = (ULONG64)soap_timegm(&T);
  8368. }
  8369. }
  8370. }
  8371. }
  8372. else if (p && !soap_tag_cmp(tmp, "Secure"))
  8373. {
  8374. p->secure = 1;
  8375. s = soap_decode_val(tmp, sizeof(tmp), s);
  8376. }
  8377. else if (p && !soap_tag_cmp(tmp, "HttpOnly"))
  8378. {
  8379. s = soap_decode_val(tmp, sizeof(tmp), s);
  8380. }
  8381. else if (p && !soap_tag_cmp(tmp, "Comment"))
  8382. {
  8383. s = soap_decode_val(tmp, sizeof(tmp), s);
  8384. }
  8385. else if (*tmp)
  8386. {
  8387. if (p)
  8388. {
  8389. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie='%s' value='%s' domain='%s' path='%s' expire=" SOAP_ULONG_FORMAT " secure=%d\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->expire, p->secure));
  8390. q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path);
  8391. if (q)
  8392. {
  8393. q->version = p->version;
  8394. q->expire = p->expire;
  8395. q->secure = p->secure;
  8396. q->env = 1;
  8397. }
  8398. if (p->name)
  8399. SOAP_FREE(soap, p->name);
  8400. if (p->value)
  8401. SOAP_FREE(soap, p->value);
  8402. if (p->domain)
  8403. SOAP_FREE(soap, p->domain);
  8404. if (p->path)
  8405. SOAP_FREE(soap, p->path);
  8406. SOAP_FREE(soap, p);
  8407. }
  8408. p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie));
  8409. if (p)
  8410. {
  8411. size_t l = strlen(tmp) + 1;
  8412. p->name = NULL;
  8413. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8414. p->name = (char*)SOAP_MALLOC(soap, l);
  8415. if (p->name)
  8416. (void)soap_memcpy(p->name, l, tmp, l);
  8417. s = soap_decode_val(tmp, sizeof(tmp), s);
  8418. if (*tmp)
  8419. {
  8420. l = strlen(tmp) + 1;
  8421. p->value = NULL;
  8422. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8423. p->value = (char*)SOAP_MALLOC(soap, l);
  8424. if (p->value)
  8425. (void)soap_memcpy((void*)p->value, l, (const void*)tmp, l);
  8426. }
  8427. else
  8428. {
  8429. p->value = NULL;
  8430. }
  8431. if (domain)
  8432. {
  8433. p->domain = domain;
  8434. }
  8435. else
  8436. {
  8437. p->domain = NULL;
  8438. }
  8439. if (path)
  8440. {
  8441. p->path = path;
  8442. }
  8443. else if (*soap->path)
  8444. {
  8445. l = strlen(soap->path) + 1;
  8446. p->path = NULL;
  8447. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8448. p->path = (char*)SOAP_MALLOC(soap, l);
  8449. if (p->path)
  8450. (void)soap_memcpy((void*)p->path, l, (const void*)soap->path, l);
  8451. }
  8452. else
  8453. {
  8454. p->path = (char*)SOAP_MALLOC(soap, 2);
  8455. if (p->path)
  8456. (void)soap_memcpy((void*)p->path, 2, (const void*)"/", 2);
  8457. }
  8458. p->expire = 0;
  8459. p->secure = 0;
  8460. p->version = version;
  8461. }
  8462. }
  8463. }
  8464. if (p)
  8465. {
  8466. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie='%s' value='%s' domain='%s' path='%s' expire=" SOAP_ULONG_FORMAT " secure=%d\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->expire, p->secure));
  8467. q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path);
  8468. if (q)
  8469. {
  8470. q->version = p->version;
  8471. q->expire = p->expire;
  8472. q->secure = p->secure;
  8473. q->env = 1;
  8474. }
  8475. if (p->name)
  8476. SOAP_FREE(soap, p->name);
  8477. if (p->value)
  8478. SOAP_FREE(soap, p->value);
  8479. if (p->domain)
  8480. SOAP_FREE(soap, p->domain);
  8481. if (p->path)
  8482. SOAP_FREE(soap, p->path);
  8483. SOAP_FREE(soap, p);
  8484. }
  8485. if (domain)
  8486. SOAP_FREE(soap, domain);
  8487. if (path)
  8488. SOAP_FREE(soap, path);
  8489. }
  8490. /******************************************************************************/
  8491. SOAP_FMAC1
  8492. int
  8493. SOAP_FMAC2
  8494. soap_getenv_cookies(struct soap *soap)
  8495. {
  8496. struct soap_cookie *p;
  8497. const char *s;
  8498. char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
  8499. s = getenv("HTTP_COOKIE");
  8500. if (!s)
  8501. return SOAP_ERR;
  8502. do
  8503. {
  8504. s = soap_decode_key(key, sizeof(key), s);
  8505. s = soap_decode_val(val, sizeof(val), s);
  8506. p = soap_set_cookie(soap, key, val, NULL, NULL);
  8507. if (p)
  8508. p->env = 1;
  8509. } while (*s);
  8510. return SOAP_OK;
  8511. }
  8512. /******************************************************************************/
  8513. SOAP_FMAC1
  8514. struct soap_cookie*
  8515. SOAP_FMAC2
  8516. soap_copy_cookies(struct soap *copy, const struct soap *soap)
  8517. {
  8518. struct soap_cookie *p, **q, *r;
  8519. (void)copy;
  8520. q = &r;
  8521. for (p = soap->cookies; p; p = p->next)
  8522. {
  8523. *q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie));
  8524. if (!*q)
  8525. return r;
  8526. **q = *p;
  8527. if (p->name)
  8528. {
  8529. size_t l = strlen(p->name) + 1;
  8530. (*q)->name = NULL;
  8531. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8532. (*q)->name = (char*)SOAP_MALLOC(copy, l);
  8533. if ((*q)->name)
  8534. (void)soap_memcpy((*q)->name, l, p->name, l);
  8535. }
  8536. if (p->value)
  8537. {
  8538. size_t l = strlen(p->value) + 1;
  8539. (*q)->value = NULL;
  8540. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8541. (*q)->value = (char*)SOAP_MALLOC(copy, l);
  8542. if ((*q)->value)
  8543. (void)soap_memcpy((*q)->value, l, p->value, l);
  8544. }
  8545. if (p->domain)
  8546. {
  8547. size_t l = strlen(p->domain) + 1;
  8548. (*q)->domain = NULL;
  8549. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8550. (*q)->domain = (char*)SOAP_MALLOC(copy, l);
  8551. if ((*q)->domain)
  8552. (void)soap_memcpy((*q)->domain, l, p->domain, l);
  8553. }
  8554. if (p->path)
  8555. {
  8556. size_t l = strlen(p->path) + 1;
  8557. (*q)->path = NULL;
  8558. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8559. (*q)->path = (char*)SOAP_MALLOC(copy, l);
  8560. if ((*q)->path)
  8561. (void)soap_memcpy((*q)->path, l, p->path, l);
  8562. }
  8563. q = &(*q)->next;
  8564. }
  8565. *q = NULL;
  8566. return r;
  8567. }
  8568. /******************************************************************************/
  8569. SOAP_FMAC1
  8570. void
  8571. SOAP_FMAC2
  8572. soap_free_cookies(struct soap *soap)
  8573. {
  8574. struct soap_cookie *p;
  8575. for (p = soap->cookies; p; p = soap->cookies)
  8576. {
  8577. soap->cookies = p->next;
  8578. SOAP_FREE(soap, p->name);
  8579. if (p->value)
  8580. SOAP_FREE(soap, p->value);
  8581. if (p->domain)
  8582. SOAP_FREE(soap, p->domain);
  8583. if (p->path)
  8584. SOAP_FREE(soap, p->path);
  8585. SOAP_FREE(soap, p);
  8586. }
  8587. }
  8588. /******************************************************************************/
  8589. #endif /* WITH_COOKIES */
  8590. /******************************************************************************/
  8591. SOAP_FMAC1
  8592. size_t
  8593. SOAP_FMAC2
  8594. soap_hash(const char *s) {
  8595. size_t h = 0;
  8596. while (*s)
  8597. h = 65599 * h + *s++;
  8598. return h % SOAP_IDHASH;
  8599. }
  8600. /******************************************************************************/
  8601. static void
  8602. soap_init_pht(struct soap *soap) {
  8603. int i;
  8604. soap->pblk = NULL;
  8605. soap->pidx = 0;
  8606. for (i = 0; i < (int) SOAP_PTRHASH; i++)
  8607. soap->pht[i] = NULL;
  8608. }
  8609. /******************************************************************************/
  8610. SOAP_FMAC1
  8611. struct soap *
  8612. SOAP_FMAC2
  8613. soap_versioning(soap_new)(soap_mode imode, soap_mode omode) {
  8614. struct soap *soap;
  8615. #ifdef __cplusplus
  8616. soap = SOAP_NEW_UNMANAGED(struct soap);
  8617. #else
  8618. soap = (struct soap*)SOAP_MALLOC_UNMANAGED(sizeof(struct soap));
  8619. #endif
  8620. if (soap)
  8621. soap_versioning(soap_init)(soap, imode, omode);
  8622. return soap;
  8623. }
  8624. /******************************************************************************/
  8625. SOAP_FMAC1
  8626. void
  8627. SOAP_FMAC2
  8628. soap_free(struct soap *soap) {
  8629. soap_done(soap);
  8630. #ifdef __cplusplus
  8631. SOAP_DELETE_UNMANAGED(soap);
  8632. #else
  8633. SOAP_FREE_UNMANAGED(soap);
  8634. #endif
  8635. }
  8636. /******************************************************************************/
  8637. SOAP_FMAC1
  8638. void
  8639. SOAP_FMAC2
  8640. soap_del(struct soap *soap) {
  8641. free(soap);
  8642. }
  8643. /******************************************************************************/
  8644. static void
  8645. soap_free_pht(struct soap *soap) {
  8646. struct soap_pblk *pb, *next;
  8647. int i;
  8648. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n"));
  8649. for (pb = soap->pblk; pb; pb = next) {
  8650. next = pb->next;
  8651. SOAP_FREE(soap, pb);
  8652. }
  8653. soap->pblk = NULL;
  8654. soap->pidx = 0;
  8655. for (i = 0; i < (int) SOAP_PTRHASH; i++)
  8656. soap->pht[i] = NULL;
  8657. }
  8658. /******************************************************************************/
  8659. #ifndef WITH_NOIDREF
  8660. SOAP_FMAC1
  8661. int
  8662. SOAP_FMAC2
  8663. soap_embed(struct soap *soap, const void *p, const void *a, int n, int t) {
  8664. int id;
  8665. struct soap_plist *pp;
  8666. if (soap->version == 2)
  8667. soap->encoding = 1;
  8668. if (!p || (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) || (soap->mode & SOAP_XML_TREE))
  8669. return 0;
  8670. if (a)
  8671. id = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
  8672. else
  8673. id = soap_pointer_lookup(soap, p, t, &pp);
  8674. if (id) {
  8675. if (soap_is_embedded(soap, pp)
  8676. || soap_is_single(soap, pp))
  8677. return 0;
  8678. soap_set_embedded(soap, pp);
  8679. }
  8680. return id;
  8681. }
  8682. #endif
  8683. /******************************************************************************/
  8684. SOAP_FMAC1
  8685. int
  8686. SOAP_FMAC2
  8687. soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp) {
  8688. struct soap_plist *pp;
  8689. *ppp = NULL;
  8690. if (p) {
  8691. for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next) {
  8692. if (pp->ptr == p && pp->type == type) {
  8693. *ppp = pp;
  8694. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id));
  8695. return pp->id;
  8696. }
  8697. }
  8698. }
  8699. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type));
  8700. return 0;
  8701. }
  8702. /******************************************************************************/
  8703. SOAP_FMAC1
  8704. int
  8705. SOAP_FMAC2
  8706. soap_pointer_enter(struct soap *soap, const void *p, const void *a, int n, int type, struct soap_plist **ppp) {
  8707. size_t h;
  8708. struct soap_plist *pp;
  8709. (void) n;
  8710. if (!soap->pblk || soap->pidx >= SOAP_PTRBLK) {
  8711. struct soap_pblk *pb = (struct soap_pblk *) SOAP_MALLOC(soap, sizeof(struct soap_pblk));
  8712. if (!pb) {
  8713. soap->error = SOAP_EOM;
  8714. return 0;
  8715. }
  8716. pb->next = soap->pblk;
  8717. soap->pblk = pb;
  8718. soap->pidx = 0;
  8719. }
  8720. *ppp = pp = &soap->pblk->plist[soap->pidx++];
  8721. if (a)
  8722. h = soap_hash_ptr(a);
  8723. else
  8724. h = soap_hash_ptr(p);
  8725. DBGLOG(TEST,
  8726. SOAP_MESSAGE(fdebug, "Pointer enter location=%p array=%p size=%lu type=%d id=%d\n", p, a, (unsigned long) n,
  8727. type, soap->idnum + 1));
  8728. pp->next = soap->pht[h];
  8729. pp->type = type;
  8730. pp->mark1 = 0;
  8731. pp->mark2 = 0;
  8732. pp->ptr = p;
  8733. pp->dup = NULL;
  8734. pp->array = a;
  8735. pp->size = n;
  8736. soap->pht[h] = pp;
  8737. pp->id = ++soap->idnum;
  8738. return pp->id;
  8739. }
  8740. /******************************************************************************/
  8741. SOAP_FMAC1
  8742. int
  8743. SOAP_FMAC2
  8744. soap_array_pointer_lookup(struct soap *soap, const void *p, const void *a, int n, int type, struct soap_plist **ppp) {
  8745. struct soap_plist *pp;
  8746. *ppp = NULL;
  8747. if (!p || !a)
  8748. return 0;
  8749. for (pp = soap->pht[soap_hash_ptr(a)]; pp; pp = pp->next) {
  8750. if (pp->type == type && pp->array == a && pp->size == n) {
  8751. *ppp = pp;
  8752. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a, type, pp->id));
  8753. return pp->id;
  8754. }
  8755. }
  8756. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a, type));
  8757. return 0;
  8758. }
  8759. /******************************************************************************/
  8760. SOAP_FMAC1
  8761. int
  8762. SOAP_FMAC2
  8763. soap_begin_count(struct soap *soap) {
  8764. soap_free_ns(soap);
  8765. soap->error = SOAP_OK;
  8766. #ifndef WITH_LEANER
  8767. if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME)) {
  8768. soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME;
  8769. } else
  8770. #endif
  8771. {
  8772. soap->mode = soap->omode;
  8773. if ((soap->mode & SOAP_IO_UDP)) {
  8774. soap->mode &= SOAP_IO;
  8775. soap->mode |= SOAP_IO_BUFFER | SOAP_ENC_PLAIN;
  8776. }
  8777. if ((soap->mode & SOAP_IO) == SOAP_IO_STORE
  8778. || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_PLAIN))
  8779. #ifndef WITH_LEANER
  8780. && !soap->fpreparesend
  8781. #endif
  8782. ))
  8783. soap->mode &= ~SOAP_IO_LENGTH;
  8784. else
  8785. soap->mode |= SOAP_IO_LENGTH;
  8786. }
  8787. #ifdef WITH_ZLIB
  8788. if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
  8789. {
  8790. if (!(soap->mode & SOAP_ENC_DIME))
  8791. soap->mode &= ~SOAP_IO_LENGTH;
  8792. if ((soap->mode & SOAP_ENC_PLAIN))
  8793. soap->mode |= SOAP_IO_BUFFER;
  8794. else
  8795. soap->mode |= SOAP_IO_STORE;
  8796. }
  8797. #endif
  8798. #ifndef WITH_LEANER
  8799. if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
  8800. soap->mode |= SOAP_ENC_MIME;
  8801. else if (!(soap->mode & SOAP_ENC_MIME))
  8802. soap->mode &= ~SOAP_ENC_MTOM;
  8803. if ((soap->mode & SOAP_ENC_MIME))
  8804. soap_select_mime_boundary(soap);
  8805. soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */
  8806. #endif
  8807. soap->count = 0;
  8808. soap->ns = 0;
  8809. soap->null = 0;
  8810. soap->position = 0;
  8811. soap->mustUnderstand = 0;
  8812. soap->encoding = 0;
  8813. soap->part = SOAP_BEGIN_SEND;
  8814. soap->event = 0;
  8815. soap->evlev = 0;
  8816. soap->idnum = 0;
  8817. soap->body = 1;
  8818. soap->level = 0;
  8819. soap_clr_attr(soap);
  8820. soap_set_local_namespaces(soap);
  8821. #ifndef WITH_LEANER
  8822. soap->dime.size = 0; /* accumulate total size of attachments */
  8823. if (soap->fprepareinitsend && (soap->mode & SOAP_IO) != SOAP_IO_STORE &&
  8824. (soap->error = soap->fprepareinitsend(soap)) != SOAP_OK)
  8825. return soap->error;
  8826. #endif
  8827. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count="
  8828. SOAP_ULONG_FORMAT
  8829. ")\n", (int) soap->socket, (unsigned int) soap->mode, soap->count));
  8830. #ifndef WITH_LEANER
  8831. if ((soap->mode & SOAP_IO_LENGTH))
  8832. return soap_begin_attachments(soap);
  8833. #endif
  8834. return SOAP_OK;
  8835. }
  8836. /******************************************************************************/
  8837. SOAP_FMAC1
  8838. int
  8839. SOAP_FMAC2
  8840. soap_end_count(struct soap *soap) {
  8841. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n"));
  8842. #ifndef WITH_LEANER
  8843. if ((soap->mode & SOAP_IO_LENGTH)) {
  8844. if (soap_end_attachments(soap))
  8845. return soap->error;
  8846. if (soap->fpreparefinalsend && (soap->error = soap->fpreparefinalsend(soap)) != SOAP_OK)
  8847. return soap->error;
  8848. }
  8849. #else
  8850. (void)soap;
  8851. #endif
  8852. return SOAP_OK;
  8853. }
  8854. /******************************************************************************/
  8855. static int
  8856. soap_init_send(struct soap *soap) {
  8857. DBGLOG(TEST,
  8858. SOAP_MESSAGE(fdebug, "Initializing for output to socket=%d/fd=%d\n", (int) soap->socket, soap->sendfd));
  8859. *soap->tag = '\0';
  8860. soap_free_ns(soap);
  8861. soap->error = SOAP_OK;
  8862. soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME));
  8863. #ifndef WITH_LEAN
  8864. if ((soap->mode & SOAP_IO_UDP)) {
  8865. soap->mode &= ~SOAP_IO;
  8866. soap->mode |= SOAP_IO_BUFFER | SOAP_ENC_PLAIN;
  8867. if ((soap->mode & SOAP_IO_LENGTH) && soap->count > sizeof(soap->buf))
  8868. return soap->error = SOAP_UDP_ERROR;
  8869. }
  8870. #endif
  8871. #ifdef WITH_ZLIB
  8872. if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
  8873. {
  8874. if ((soap->mode & SOAP_ENC_PLAIN))
  8875. soap->mode |= SOAP_IO_BUFFER;
  8876. else
  8877. soap->mode |= SOAP_IO_STORE;
  8878. }
  8879. #endif
  8880. #if !defined(__cplusplus) || defined(WITH_COMPAT)
  8881. if (soap->os)
  8882. {
  8883. *soap->os = NULL;
  8884. soap->mode = (soap->mode & ~SOAP_IO) | SOAP_IO_STORE;
  8885. }
  8886. else
  8887. #endif
  8888. if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket)) {
  8889. if ((soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_PLAIN))
  8890. soap->mode |= SOAP_IO_BUFFER;
  8891. else
  8892. soap->mode |= SOAP_IO_STORE;
  8893. }
  8894. soap->mode &= ~SOAP_IO_LENGTH;
  8895. if ((soap->mode & SOAP_IO) == SOAP_IO_STORE && soap_alloc_block(soap) == NULL)
  8896. return soap->error;
  8897. if (!(soap->mode & SOAP_IO_KEEPALIVE))
  8898. soap->keep_alive = 0;
  8899. #ifndef WITH_LEANER
  8900. if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) {
  8901. soap->mode |= SOAP_ENC_MIME;
  8902. soap->mode &= ~SOAP_ENC_DIME;
  8903. } else if (!(soap->mode & SOAP_ENC_MIME)) {
  8904. soap->mode &= ~SOAP_ENC_MTOM;
  8905. }
  8906. if ((soap->mode & SOAP_ENC_MIME))
  8907. soap_select_mime_boundary(soap);
  8908. #ifdef WIN32
  8909. #ifndef UNDER_CE
  8910. #ifndef WITH_FASTCGI
  8911. if (!soap_valid_socket(soap->socket) && !soap->os && soap->sendfd >= 0) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
  8912. #ifdef __BORLANDC__
  8913. setmode(soap->sendfd, _O_BINARY);
  8914. #else
  8915. _setmode(soap->sendfd, _O_BINARY);
  8916. #endif
  8917. #endif
  8918. #endif
  8919. #endif
  8920. #endif
  8921. if ((soap->mode & SOAP_IO))
  8922. soap->buflen = soap->bufidx = 0;
  8923. soap->chunksize = 0;
  8924. soap->ns = 0;
  8925. soap->null = 0;
  8926. soap->position = 0;
  8927. soap->mustUnderstand = 0;
  8928. soap->encoding = 0;
  8929. soap->event = 0;
  8930. soap->evlev = 0;
  8931. soap->idnum = 0;
  8932. soap->body = 1;
  8933. soap->level = 0;
  8934. soap_clr_attr(soap);
  8935. soap_set_local_namespaces(soap);
  8936. #ifdef WITH_ZLIB
  8937. soap->z_ratio_out = 1.0;
  8938. if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE)
  8939. {
  8940. if (!soap->d_stream)
  8941. {
  8942. soap->d_stream = (z_stream*)SOAP_MALLOC(soap, sizeof(z_stream));
  8943. if (!soap->d_stream)
  8944. return soap->error = SOAP_EOM;
  8945. soap->d_stream->zalloc = Z_NULL;
  8946. soap->d_stream->zfree = Z_NULL;
  8947. soap->d_stream->opaque = Z_NULL;
  8948. soap->d_stream->next_in = Z_NULL;
  8949. }
  8950. if (!soap->z_buf)
  8951. soap->z_buf = (char*)SOAP_MALLOC(soap, sizeof(soap->buf));
  8952. if (!soap->z_buf)
  8953. return soap->error = SOAP_EOM;
  8954. soap->d_stream->next_out = (Byte*)soap->z_buf;
  8955. soap->d_stream->avail_out = sizeof(soap->buf);
  8956. #ifdef WITH_GZIP
  8957. if (soap->zlib_out != SOAP_ZLIB_DEFLATE)
  8958. {
  8959. (void)soap_memcpy((void*)soap->z_buf, sizeof(soap->buf), (const void*)"\37\213\10\0\0\0\0\0\0\377", 10);
  8960. soap->d_stream->next_out = (Byte*)soap->z_buf + 10;
  8961. soap->d_stream->avail_out = sizeof(soap->buf) - 10;
  8962. soap->z_crc = crc32(0L, NULL, 0);
  8963. soap->zlib_out = SOAP_ZLIB_GZIP;
  8964. if (soap->z_dict)
  8965. *((Byte*)soap->z_buf + 2) = 0xff;
  8966. if (deflateInit2(soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK)
  8967. return soap->error = SOAP_ZLIB_ERROR;
  8968. }
  8969. else
  8970. #endif
  8971. if (deflateInit(soap->d_stream, soap->z_level) != Z_OK)
  8972. return soap->error = SOAP_ZLIB_ERROR;
  8973. if (soap->z_dict)
  8974. {
  8975. if (deflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
  8976. return soap->error = SOAP_ZLIB_ERROR;
  8977. }
  8978. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n"));
  8979. soap->zlib_state = SOAP_ZLIB_DEFLATE;
  8980. }
  8981. #endif
  8982. #ifdef WITH_OPENSSL
  8983. if (soap->ssl)
  8984. ERR_clear_error();
  8985. #endif
  8986. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count="
  8987. SOAP_ULONG_FORMAT
  8988. ")\n", (int) soap->socket, soap->mode, soap->count));
  8989. soap->part = SOAP_BEGIN_SEND;
  8990. #ifndef WITH_LEANER
  8991. if (soap->fprepareinitsend && (soap->mode & SOAP_IO) == SOAP_IO_STORE &&
  8992. (soap->error = soap->fprepareinitsend(soap)) != SOAP_OK)
  8993. return soap->error;
  8994. #endif
  8995. #ifndef WITH_LEAN
  8996. soap->start = (ULONG64) time(NULL);
  8997. #endif
  8998. return SOAP_OK;
  8999. }
  9000. /******************************************************************************/
  9001. SOAP_FMAC1
  9002. int
  9003. SOAP_FMAC2
  9004. soap_begin_send(struct soap *soap) {
  9005. #ifndef WITH_LEANER
  9006. if (soap_init_send(soap))
  9007. return soap->error;
  9008. return soap_begin_attachments(soap);
  9009. #else
  9010. return soap_init_send(soap);
  9011. #endif
  9012. }
  9013. /******************************************************************************/
  9014. #ifndef WITH_NOIDREF
  9015. SOAP_FMAC1
  9016. void
  9017. SOAP_FMAC2
  9018. soap_embedded(struct soap *soap, const void *p, int t) {
  9019. struct soap_plist *pp;
  9020. if (soap_pointer_lookup(soap, p, t, &pp)) {
  9021. pp->mark1 = 1;
  9022. pp->mark2 = 1;
  9023. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t));
  9024. }
  9025. }
  9026. #endif
  9027. /******************************************************************************/
  9028. #ifndef WITH_NOIDREF
  9029. SOAP_FMAC1
  9030. int
  9031. SOAP_FMAC2
  9032. soap_reference(struct soap *soap, const void *p, int t) {
  9033. struct soap_plist *pp;
  9034. if (!p ||
  9035. (!soap->encodingStyle && !(soap->omode & (SOAP_ENC_DIME | SOAP_ENC_MIME | SOAP_ENC_MTOM | SOAP_XML_GRAPH))) ||
  9036. (soap->omode & SOAP_XML_TREE))
  9037. return 1;
  9038. if (soap_pointer_lookup(soap, p, t, &pp)) {
  9039. if (pp->mark1 == 0) {
  9040. pp->mark1 = 2;
  9041. pp->mark2 = 2;
  9042. }
  9043. } else if (!soap_pointer_enter(soap, p, NULL, 0, t, &pp)) {
  9044. return 1;
  9045. }
  9046. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int) pp->mark1, (int) pp->mark2));
  9047. return pp->mark1;
  9048. }
  9049. #endif
  9050. /******************************************************************************/
  9051. #ifndef WITH_NOIDREF
  9052. SOAP_FMAC1
  9053. int
  9054. SOAP_FMAC2
  9055. soap_array_reference(struct soap *soap, const void *p, const void *a, int n, int t) {
  9056. struct soap_plist *pp;
  9057. if (!p || !a || (!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH)) || (soap->omode & SOAP_XML_TREE))
  9058. return 1;
  9059. if (soap_array_pointer_lookup(soap, p, a, n, t, &pp)) {
  9060. if (pp->mark1 == 0) {
  9061. pp->mark1 = 2;
  9062. pp->mark2 = 2;
  9063. }
  9064. } else if (!soap_pointer_enter(soap, p, a, n, t, &pp)) {
  9065. return 1;
  9066. }
  9067. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array reference %p ptr=%p n=%lu t=%d (%d %d)\n", p, a, (unsigned long) n, t,
  9068. (int) pp->mark1, (int) pp->mark2));
  9069. return pp->mark1;
  9070. }
  9071. #endif
  9072. /******************************************************************************/
  9073. #ifndef WITH_NOIDREF
  9074. SOAP_FMAC1
  9075. int
  9076. SOAP_FMAC2
  9077. soap_attachment_reference(struct soap *soap, const void *p, const void *a, int n, int t, const char *id,
  9078. const char *type) {
  9079. struct soap_plist *pp;
  9080. if (!p || !a || (!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH) && !id && !type) ||
  9081. (soap->omode & SOAP_XML_TREE))
  9082. return 1;
  9083. if (soap_array_pointer_lookup(soap, p, a, n, t, &pp)) {
  9084. if (pp->mark1 == 0) {
  9085. pp->mark1 = 2;
  9086. pp->mark2 = 2;
  9087. }
  9088. } else if (!soap_pointer_enter(soap, p, a, n, t, &pp)) {
  9089. return 1;
  9090. }
  9091. if (id || type)
  9092. soap->mode |= SOAP_ENC_DIME;
  9093. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment reference %p ptr=%p n=%lu t=%d (%d %d)\n", p, a, (unsigned long) n, t,
  9094. (int) pp->mark1, (int) pp->mark2));
  9095. return pp->mark1;
  9096. }
  9097. #endif
  9098. /******************************************************************************/
  9099. #ifndef WITH_NOIDREF
  9100. SOAP_FMAC1
  9101. int
  9102. SOAP_FMAC2
  9103. soap_embedded_id(struct soap *soap, int id, const void *p, int t) {
  9104. struct soap_plist *pp = NULL;
  9105. if (id >= 0 || (!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH)) || (soap->omode & SOAP_XML_TREE))
  9106. return id;
  9107. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id));
  9108. if (id < -1)
  9109. return soap_embed(soap, p, NULL, 0, t);
  9110. if (id < 0) {
  9111. id = soap_pointer_lookup(soap, p, t, &pp);
  9112. if (soap->version == 1 && soap->part != SOAP_IN_HEADER) {
  9113. if (id) {
  9114. if ((soap->mode & SOAP_IO_LENGTH))
  9115. pp->mark1 = 2;
  9116. else
  9117. pp->mark2 = 2;
  9118. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id multiref id=%d %p type=%d = (%d %d)\n", id, p, t,
  9119. (int) pp->mark1, (int) pp->mark2));
  9120. }
  9121. return -1;
  9122. } else if (id) {
  9123. if ((soap->mode & SOAP_IO_LENGTH))
  9124. pp->mark1 = 1;
  9125. else
  9126. pp->mark2 = 1;
  9127. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id embedded ref id=%d %p type=%d = (%d %d)\n", id, p, t,
  9128. (int) pp->mark1, (int) pp->mark2));
  9129. }
  9130. }
  9131. return id;
  9132. }
  9133. #endif
  9134. /******************************************************************************/
  9135. #ifndef WITH_NOIDREF
  9136. SOAP_FMAC1
  9137. int
  9138. SOAP_FMAC2
  9139. soap_is_embedded(struct soap *soap, struct soap_plist *pp) {
  9140. if (!pp)
  9141. return 0;
  9142. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int) pp->mark1, (int) pp->mark2));
  9143. if (soap->version == 1 && soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) {
  9144. if ((soap->mode & SOAP_IO_LENGTH))
  9145. return pp->mark1 != 0;
  9146. return pp->mark2 != 0;
  9147. }
  9148. if ((soap->mode & SOAP_IO_LENGTH))
  9149. return pp->mark1 == 1;
  9150. return pp->mark2 == 1;
  9151. }
  9152. #endif
  9153. /******************************************************************************/
  9154. #ifndef WITH_NOIDREF
  9155. SOAP_FMAC1
  9156. int
  9157. SOAP_FMAC2
  9158. soap_is_single(struct soap *soap, struct soap_plist *pp) {
  9159. if (soap->part == SOAP_IN_HEADER)
  9160. return 1;
  9161. if (!pp)
  9162. return 0;
  9163. if ((soap->mode & SOAP_IO_LENGTH))
  9164. return pp->mark1 == 0;
  9165. return pp->mark2 == 0;
  9166. }
  9167. #endif
  9168. /******************************************************************************/
  9169. #ifndef WITH_NOIDREF
  9170. SOAP_FMAC1
  9171. void
  9172. SOAP_FMAC2
  9173. soap_set_embedded(struct soap *soap, struct soap_plist *pp) {
  9174. if (!pp)
  9175. return;
  9176. if ((soap->mode & SOAP_IO_LENGTH))
  9177. pp->mark1 = 1;
  9178. else
  9179. pp->mark2 = 1;
  9180. }
  9181. #endif
  9182. /******************************************************************************/
  9183. #ifndef WITH_LEANER
  9184. SOAP_FMAC1
  9185. int
  9186. SOAP_FMAC2
  9187. soap_attachment(struct soap *soap, const char *tag, int id, const void *p, const void *a, int n, const char *aid,
  9188. const char *atype, const char *aoptions, const char *type, int t) {
  9189. struct soap_plist *pp;
  9190. int i;
  9191. if (!p || !a || (!aid && !atype) ||
  9192. (!soap->encodingStyle && !(soap->omode & (SOAP_ENC_DIME | SOAP_ENC_MIME | SOAP_ENC_MTOM | SOAP_XML_GRAPH))) ||
  9193. (soap->omode & SOAP_XML_TREE))
  9194. return soap_element_id(soap, tag, id, p, a, n, type, t, NULL);
  9195. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid ? aid : SOAP_STR_EOS, id,
  9196. atype ? atype : SOAP_STR_EOS));
  9197. i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
  9198. if (!i) {
  9199. i = soap_pointer_enter(soap, p, a, n, t, &pp);
  9200. if (!i) {
  9201. soap->error = SOAP_EOM;
  9202. return -1;
  9203. }
  9204. }
  9205. if (id <= 0)
  9206. id = i;
  9207. if (!aid) {
  9208. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(soap->dime_id_format) + 20), soap->dime_id_format,
  9209. id);
  9210. aid = soap_strdup(soap, soap->tmpbuf);
  9211. if (!aid)
  9212. return -1;
  9213. }
  9214. /* Add MTOM xop:Include element when necessary */
  9215. /* TODO: this code to be obsoleted with new import/xop.h conventions */
  9216. if ((soap->omode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include")) {
  9217. if (soap_element_begin_out(soap, tag, 0, type)
  9218. ||
  9219. soap_element_href(soap, "xop:Include", 0, "xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" href", aid)
  9220. || soap_element_end_out(soap, tag))
  9221. return soap->error;
  9222. } else if (soap_element_href(soap, tag, 0, "href", aid)) {
  9223. return soap->error;
  9224. }
  9225. if ((soap->mode & SOAP_IO_LENGTH)) {
  9226. if (pp->mark1 != 3) {
  9227. struct soap_multipart *content;
  9228. if ((soap->omode & SOAP_ENC_MTOM))
  9229. content = soap_alloc_multipart(soap, &soap->mime.first, &soap->mime.last, (const char *) a, n);
  9230. else
  9231. content = soap_alloc_multipart(soap, &soap->dime.first, &soap->dime.last, (const char *) a, n);
  9232. if (!content) {
  9233. soap->error = SOAP_EOM;
  9234. return -1;
  9235. }
  9236. if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */
  9237. {
  9238. if ((soap->omode & SOAP_ENC_MTOM)) {
  9239. size_t l = strlen(aid) - 1;
  9240. char *s = (char *) soap_malloc(soap, l);
  9241. if (s) {
  9242. s[0] = '<';
  9243. (void) soap_strncpy(s + 1, l - 1, aid + 4, l - 3);
  9244. s[l - 2] = '>';
  9245. s[l - 1] = '\0';
  9246. content->id = s;
  9247. }
  9248. } else {
  9249. content->id = aid + 4;
  9250. }
  9251. } else {
  9252. content->id = aid;
  9253. }
  9254. content->type = atype;
  9255. content->options = aoptions;
  9256. content->encoding = SOAP_MIME_BINARY;
  9257. pp->mark1 = 3;
  9258. }
  9259. } else {
  9260. pp->mark2 = 3;
  9261. }
  9262. return -1;
  9263. }
  9264. #endif
  9265. /******************************************************************************/
  9266. #ifndef WITH_NOIDREF
  9267. static void
  9268. soap_init_iht(struct soap *soap) {
  9269. int i;
  9270. for (i = 0; i < SOAP_IDHASH; i++)
  9271. soap->iht[i] = NULL;
  9272. }
  9273. #endif
  9274. /******************************************************************************/
  9275. #ifndef WITH_NOIDREF
  9276. static void
  9277. soap_free_iht(struct soap *soap) {
  9278. int i;
  9279. struct soap_ilist *ip = NULL, *p = NULL;
  9280. struct soap_flist *fp = NULL, *fq = NULL;
  9281. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n"));
  9282. for (i = 0; i < SOAP_IDHASH; i++) {
  9283. for (ip = soap->iht[i]; ip; ip = p) {
  9284. for (fp = ip->flist; fp; fp = fq) {
  9285. fq = fp->next;
  9286. SOAP_FREE(soap, fp);
  9287. }
  9288. p = ip->next;
  9289. SOAP_FREE(soap, ip);
  9290. }
  9291. soap->iht[i] = NULL;
  9292. }
  9293. }
  9294. #endif
  9295. /******************************************************************************/
  9296. #ifndef WITH_NOIDREF
  9297. SOAP_FMAC1
  9298. struct soap_ilist *
  9299. SOAP_FMAC2
  9300. soap_lookup(struct soap *soap, const char *id) {
  9301. struct soap_ilist *ip = NULL;
  9302. for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next)
  9303. if (!strcmp(ip->id, id))
  9304. return ip;
  9305. return NULL;
  9306. }
  9307. #endif
  9308. /******************************************************************************/
  9309. #ifndef WITH_NOIDREF
  9310. SOAP_FMAC1
  9311. struct soap_ilist *
  9312. SOAP_FMAC2
  9313. soap_enter(struct soap *soap, const char *id, int t, size_t n) {
  9314. size_t h;
  9315. struct soap_ilist *ip = NULL;
  9316. size_t l = strlen(id);
  9317. if (sizeof(struct soap_ilist) + l > l &&
  9318. (SOAP_MAXALLOCSIZE <= 0 || sizeof(struct soap_ilist) + l <= SOAP_MAXALLOCSIZE))
  9319. ip = (struct soap_ilist *) SOAP_MALLOC(soap, sizeof(struct soap_ilist) + l);
  9320. if (ip) {
  9321. ip->type = t;
  9322. ip->size = n;
  9323. ip->ptr = NULL;
  9324. ip->spine = NULL;
  9325. ip->link = NULL;
  9326. ip->copy = NULL;
  9327. ip->flist = NULL;
  9328. ip->smart = NULL;
  9329. ip->shaky = 0;
  9330. (void) soap_memcpy((char *) ip->id, l + 1, id, l + 1);
  9331. h = soap_hash(id); /* h = (HASH(id) % SOAP_IDHASH) so soap->iht[h] is safe */
  9332. ip->next = soap->iht[h];
  9333. soap->iht[h] = ip;
  9334. }
  9335. return ip;
  9336. }
  9337. #endif
  9338. /******************************************************************************/
  9339. SOAP_FMAC1
  9340. void *
  9341. SOAP_FMAC2
  9342. soap_malloc(struct soap *soap, size_t n) {
  9343. char *p;
  9344. size_t k = n;
  9345. if (SOAP_MAXALLOCSIZE > 0 && n > SOAP_MAXALLOCSIZE) {
  9346. soap->error = SOAP_EOM;
  9347. return NULL;
  9348. }
  9349. if (!soap)
  9350. return SOAP_MALLOC(soap, n);
  9351. n += sizeof(short);
  9352. n += (~n + 1) & (sizeof(void *) - 1); /* align at 4-, 8- or 16-byte boundary by rounding up */
  9353. if (n + sizeof(void *) + sizeof(size_t) < k) {
  9354. soap->error = SOAP_EOM;
  9355. return NULL;
  9356. }
  9357. p = (char *) SOAP_MALLOC(soap, n + sizeof(void *) + sizeof(size_t));
  9358. if (!p) {
  9359. soap->error = SOAP_EOM;
  9360. return NULL;
  9361. }
  9362. /* set a canary word to detect memory overruns and data corruption */
  9363. *(unsigned short *) (p + n - sizeof(unsigned short)) = (unsigned short) SOAP_CANARY;
  9364. /* keep chain of alloced cells for destruction */
  9365. *(void **) (p + n) = soap->alist;
  9366. *(size_t *) (p + n + sizeof(void *)) = n;
  9367. soap->alist = p + n;
  9368. return p;
  9369. }
  9370. /******************************************************************************/
  9371. #ifdef SOAP_MEM_DEBUG
  9372. static void
  9373. soap_init_mht(struct soap *soap) {
  9374. int i;
  9375. for (i = 0; i < (int) SOAP_PTRHASH; i++)
  9376. soap->mht[i] = NULL;
  9377. }
  9378. #endif
  9379. /******************************************************************************/
  9380. #ifdef SOAP_MEM_DEBUG
  9381. static void
  9382. soap_free_mht(struct soap *soap) {
  9383. int i;
  9384. struct soap_mlist *mp, *mq;
  9385. for (i = 0; i < (int) SOAP_PTRHASH; i++) {
  9386. for (mp = soap->mht[i]; mp; mp = mq) {
  9387. mq = mp->next;
  9388. if (mp->live)
  9389. fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n",
  9390. mp->file, mp->line, mp->ptr);
  9391. free(mp);
  9392. }
  9393. soap->mht[i] = NULL;
  9394. }
  9395. }
  9396. #endif
  9397. /******************************************************************************/
  9398. #ifdef SOAP_MEM_DEBUG
  9399. SOAP_FMAC1
  9400. void *
  9401. SOAP_FMAC2
  9402. soap_track_malloc(struct soap *soap, const char *file, int line, size_t size) {
  9403. void *p = malloc(size);
  9404. if (soap) {
  9405. size_t h = soap_hash_ptr(p);
  9406. struct soap_mlist *mp = (struct soap_mlist *) malloc(sizeof(struct soap_mlist));
  9407. if (soap->fdebug[SOAP_INDEX_TEST]) {
  9408. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long) size, p));
  9409. }
  9410. mp->next = soap->mht[h];
  9411. mp->ptr = p;
  9412. mp->file = file;
  9413. mp->line = line;
  9414. mp->live = 1;
  9415. soap->mht[h] = mp;
  9416. }
  9417. return p;
  9418. }
  9419. #endif
  9420. /******************************************************************************/
  9421. #ifdef SOAP_MEM_DEBUG
  9422. SOAP_FMAC1
  9423. void
  9424. SOAP_FMAC2
  9425. soap_track_free(struct soap *soap, const char *file, int line, void *p) {
  9426. if (!soap) {
  9427. free(p);
  9428. } else {
  9429. size_t h = soap_hash_ptr(p);
  9430. struct soap_mlist *mp;
  9431. for (mp = soap->mht[h]; mp; mp = mp->next)
  9432. if (mp->ptr == p)
  9433. break;
  9434. if (mp) {
  9435. if (mp->live) {
  9436. if (soap->fdebug[SOAP_INDEX_TEST]) {
  9437. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p));
  9438. }
  9439. free(p);
  9440. mp->live = 0;
  9441. } else {
  9442. fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file,
  9443. mp->line);
  9444. }
  9445. } else {
  9446. fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p);
  9447. }
  9448. }
  9449. }
  9450. #endif
  9451. /******************************************************************************/
  9452. #ifdef SOAP_MEM_DEBUG
  9453. static void
  9454. soap_track_unlink(struct soap *soap, const void *p) {
  9455. size_t h = soap_hash_ptr(p);
  9456. struct soap_mlist *mp;
  9457. for (mp = soap->mht[h]; mp; mp = mp->next)
  9458. if (mp->ptr == p)
  9459. break;
  9460. if (mp)
  9461. mp->live = 0;
  9462. }
  9463. #endif
  9464. /******************************************************************************/
  9465. SOAP_FMAC1
  9466. void
  9467. SOAP_FMAC2
  9468. soap_dealloc(struct soap *soap, void *p) {
  9469. if (soap_check_state(soap))
  9470. return;
  9471. if (p) {
  9472. char **q;
  9473. for (q = (char **) (void *) &soap->alist; *q; q = *(char ***) q) {
  9474. if (*(unsigned short *) (char *) (*q - sizeof(unsigned short)) != (unsigned short) SOAP_CANARY) {
  9475. #ifdef SOAP_MEM_DEBUG
  9476. fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
  9477. #endif
  9478. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
  9479. DBGHEX(TEST, *q - 200, 200);
  9480. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
  9481. soap->error = SOAP_MOE;
  9482. return;
  9483. }
  9484. if (p == (void *) (*q - *(size_t *) (*q + sizeof(void *)))) {
  9485. *q = **(char ***) q;
  9486. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p));
  9487. SOAP_FREE(soap, p);
  9488. return;
  9489. }
  9490. }
  9491. soap_delete(soap, p);
  9492. } else {
  9493. char *q;
  9494. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n"));
  9495. while (soap->alist) {
  9496. q = (char *) soap->alist;
  9497. if (*(unsigned short *) (char *) (q - sizeof(unsigned short)) != (unsigned short) SOAP_CANARY) {
  9498. #ifdef SOAP_MEM_DEBUG
  9499. fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
  9500. #endif
  9501. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
  9502. DBGHEX(TEST, q - 200, 200);
  9503. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
  9504. soap->error = SOAP_MOE;
  9505. return;
  9506. }
  9507. soap->alist = *(void **) q;
  9508. q -= *(size_t *) (q + sizeof(void *));
  9509. SOAP_FREE(soap, q);
  9510. }
  9511. /* assume these were deallocated: */
  9512. soap->http_content = NULL;
  9513. soap->action = NULL;
  9514. soap->fault = NULL;
  9515. soap->header = NULL;
  9516. soap->bearer = NULL;
  9517. soap->userid = NULL;
  9518. soap->passwd = NULL;
  9519. soap->authrealm = NULL;
  9520. #ifdef WITH_NTLM
  9521. soap->ntlm_challenge = NULL;
  9522. #endif
  9523. #ifndef WITH_LEANER
  9524. soap_clr_mime(soap);
  9525. #endif
  9526. }
  9527. }
  9528. /******************************************************************************/
  9529. SOAP_FMAC1
  9530. void
  9531. SOAP_FMAC2
  9532. soap_delete(struct soap *soap, void *p) {
  9533. struct soap_clist **cp;
  9534. if (soap_check_state(soap))
  9535. return;
  9536. cp = &soap->clist;
  9537. if (p) {
  9538. while (*cp) {
  9539. if (p == (*cp)->ptr) {
  9540. struct soap_clist *q = *cp;
  9541. *cp = q->next;
  9542. if (q->fdelete(soap, q)) {
  9543. DBGLOG(TEST, SOAP_MESSAGE(fdebug,
  9544. "Could not dealloc data %p: deletion callback failed for object type=%d\n",
  9545. q->ptr, q->type));
  9546. #ifdef SOAP_MEM_DEBUG
  9547. fprintf(stderr, "new(object type=%d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
  9548. #endif
  9549. }
  9550. SOAP_FREE(soap, q);
  9551. return;
  9552. }
  9553. cp = &(*cp)->next;
  9554. }
  9555. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p));
  9556. } else {
  9557. while (*cp) {
  9558. struct soap_clist *q = *cp;
  9559. *cp = q->next;
  9560. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Delete %p type=%d (cp=%p)\n", q->ptr, q->type, (void *) q));
  9561. if (q->fdelete(soap, q)) {
  9562. DBGLOG(TEST,
  9563. SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type=%d\n",
  9564. q->ptr, q->type));
  9565. #ifdef SOAP_MEM_DEBUG
  9566. fprintf(stderr, "new(object type=%d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
  9567. #endif
  9568. }
  9569. SOAP_FREE(soap, q);
  9570. }
  9571. }
  9572. soap->fault = NULL; /* assume this was deallocated */
  9573. soap->header = NULL; /* assume this was deallocated */
  9574. }
  9575. /******************************************************************************/
  9576. SOAP_FMAC1
  9577. void
  9578. SOAP_FMAC2
  9579. soap_delegate_deletion(struct soap *soap, struct soap *soap_to) {
  9580. struct soap_clist *cp;
  9581. char **q;
  9582. #ifdef SOAP_MEM_DEBUG
  9583. void *p;
  9584. struct soap_mlist **mp, *mq;
  9585. size_t h;
  9586. #endif
  9587. for (q = (char **) (void *) &soap->alist; *q; q = *(char ***) q) {
  9588. if (*(unsigned short *) (char *) (*q - sizeof(unsigned short)) != (unsigned short) SOAP_CANARY) {
  9589. #ifdef SOAP_MEM_DEBUG
  9590. fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
  9591. #endif
  9592. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
  9593. DBGHEX(TEST, *q - 200, 200);
  9594. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
  9595. soap->error = SOAP_MOE;
  9596. return;
  9597. }
  9598. #ifdef SOAP_MEM_DEBUG
  9599. p = (void *) (*q - *(size_t *) (*q + sizeof(void *)));
  9600. h = soap_hash_ptr(p);
  9601. for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next) {
  9602. if ((*mp)->ptr == p) {
  9603. mq = *mp;
  9604. *mp = mq->next;
  9605. mq->next = soap_to->mht[h];
  9606. soap_to->mht[h] = mq;
  9607. break;
  9608. }
  9609. }
  9610. #endif
  9611. }
  9612. *q = (char *) soap_to->alist;
  9613. soap_to->alist = soap->alist;
  9614. soap->alist = NULL;
  9615. #ifdef SOAP_MEM_DEBUG
  9616. cp = soap->clist;
  9617. while (cp) {
  9618. h = soap_hash_ptr(cp);
  9619. for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next) {
  9620. if ((*mp)->ptr == cp) {
  9621. mq = *mp;
  9622. *mp = mq->next;
  9623. mq->next = soap_to->mht[h];
  9624. soap_to->mht[h] = mq;
  9625. break;
  9626. }
  9627. }
  9628. cp = cp->next;
  9629. }
  9630. #endif
  9631. cp = soap_to->clist;
  9632. if (cp) {
  9633. while (cp->next)
  9634. cp = cp->next;
  9635. cp->next = soap->clist;
  9636. } else {
  9637. soap_to->clist = soap->clist;
  9638. }
  9639. soap->clist = NULL;
  9640. }
  9641. /******************************************************************************/
  9642. SOAP_FMAC1
  9643. struct soap_clist *
  9644. SOAP_FMAC2
  9645. soap_link(struct soap *soap, int t, int n, int (*fdelete)(struct soap *, struct soap_clist *)) {
  9646. struct soap_clist *cp = NULL;
  9647. if (soap) {
  9648. if (n != SOAP_NO_LINK_TO_DELETE) {
  9649. cp = (struct soap_clist *) SOAP_MALLOC(soap, sizeof(struct soap_clist));
  9650. if (!cp) {
  9651. soap->error = SOAP_EOM;
  9652. } else {
  9653. cp->next = soap->clist;
  9654. cp->type = t;
  9655. cp->size = n;
  9656. cp->ptr = NULL;
  9657. cp->fdelete = fdelete;
  9658. soap->clist = cp;
  9659. }
  9660. }
  9661. soap->alloced = t;
  9662. }
  9663. return cp;
  9664. }
  9665. /******************************************************************************/
  9666. SOAP_FMAC1
  9667. int
  9668. SOAP_FMAC2
  9669. soap_unlink(struct soap *soap, const void *p) {
  9670. char **q;
  9671. struct soap_clist **cp;
  9672. if (soap && p) {
  9673. for (q = (char **) (void *) &soap->alist; *q; q = *(char ***) q) {
  9674. if (p == (void *) (*q - *(size_t *) (*q + sizeof(void *)))) {
  9675. *q = **(char ***) q;
  9676. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p));
  9677. #ifdef SOAP_MEM_DEBUG
  9678. soap_track_unlink(soap, p);
  9679. #endif
  9680. return SOAP_OK; /* found and removed from dealloc chain */
  9681. }
  9682. }
  9683. for (cp = &soap->clist; *cp; cp = &(*cp)->next) {
  9684. if (p == (*cp)->ptr) {
  9685. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p));
  9686. q = (char **) *cp;
  9687. *cp = (*cp)->next;
  9688. SOAP_FREE(soap, q);
  9689. return SOAP_OK; /* found and removed from dealloc chain */
  9690. }
  9691. }
  9692. }
  9693. return SOAP_ERR;
  9694. }
  9695. /******************************************************************************/
  9696. #ifndef WITH_NOIDREF
  9697. SOAP_FMAC1
  9698. int
  9699. SOAP_FMAC2
  9700. soap_lookup_type(struct soap *soap, const char *id) {
  9701. struct soap_ilist *ip;
  9702. if (id && *id) {
  9703. ip = soap_lookup(soap, id);
  9704. if (ip) {
  9705. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type));
  9706. return ip->type;
  9707. }
  9708. }
  9709. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id));
  9710. return 0;
  9711. }
  9712. #endif
  9713. /******************************************************************************/
  9714. #ifndef WITH_NOIDREF
  9715. SOAP_FMAC1
  9716. short
  9717. SOAP_FMAC2
  9718. soap_begin_shaky(struct soap *soap) {
  9719. short f = soap->shaky;
  9720. soap->shaky = 1;
  9721. return f;
  9722. }
  9723. #endif
  9724. /******************************************************************************/
  9725. #ifndef WITH_NOIDREF
  9726. SOAP_FMAC1
  9727. void
  9728. SOAP_FMAC2
  9729. soap_end_shaky(struct soap *soap, short f) {
  9730. soap->shaky = f;
  9731. }
  9732. #endif
  9733. /******************************************************************************/
  9734. #ifndef WITH_NOIDREF
  9735. static int
  9736. soap_is_shaky(struct soap *soap, void *p) {
  9737. (void) p;
  9738. if (!soap->blist && !soap->shaky)
  9739. return 0;
  9740. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shaky %p\n", p));
  9741. return 1;
  9742. }
  9743. #endif
  9744. /******************************************************************************/
  9745. #ifndef WITH_NOIDREF
  9746. SOAP_FMAC1
  9747. void *
  9748. SOAP_FMAC2
  9749. soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k, int (*fbase)(int, int)) {
  9750. struct soap_ilist *ip;
  9751. if (!p || !id || !*id)
  9752. return p;
  9753. ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
  9754. if (!ip) {
  9755. ip = soap_enter(soap, id, t, n); /* new hash table entry for string id */
  9756. if (!ip)
  9757. return NULL;
  9758. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d location=%p (%u bytes) level=%u\n", id, t,
  9759. (void *) p, (unsigned int) n, k));
  9760. *p = NULL;
  9761. if (k) {
  9762. int i;
  9763. if (k > SOAP_MAXPTRS)
  9764. return NULL;
  9765. ip->spine = (void **) soap_malloc(soap, SOAP_MAXPTRS * sizeof(void *));
  9766. if (!ip->spine)
  9767. return NULL;
  9768. ip->spine[0] = NULL;
  9769. for (i = 1; i < SOAP_MAXPTRS; i++)
  9770. ip->spine[i] = &ip->spine[i - 1];
  9771. *p = &ip->spine[k - 1];
  9772. } else {
  9773. ip->link = p;
  9774. ip->shaky = soap_is_shaky(soap, (void *) p);
  9775. }
  9776. } else if (ip->type != t && (!fbase || !fbase(ip->type, t)) &&
  9777. (!fbase || !fbase(t, ip->type) || soap_type_punned(soap, ip))) {
  9778. DBGLOG(TEST,
  9779. SOAP_MESSAGE(fdebug, "Lookup type incompatibility: ref='%s' id-type=%d ref-type=%d\n", id, ip->type, t));
  9780. (void) soap_id_nullify(soap, id);
  9781. return NULL;
  9782. } else if (k == 0 && ip->ptr && !ip->shaky) /* when block lists are in use, ip->ptr will change */
  9783. {
  9784. DBGLOG(TEST,
  9785. SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes) level=%u\n", id, t, ip->ptr,
  9786. (unsigned int) n, k));
  9787. *p = ip->ptr;
  9788. } else {
  9789. DBGLOG(TEST,
  9790. SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes) level=%u\n", id, t, (void *) p,
  9791. (unsigned int) n, k));
  9792. if (fbase && fbase(t, ip->type) && !soap_type_punned(soap, ip)) {
  9793. ip->type = t;
  9794. ip->size = n;
  9795. }
  9796. *p = NULL;
  9797. if (k) {
  9798. if (!ip->spine) {
  9799. int i;
  9800. if (k > SOAP_MAXPTRS)
  9801. return NULL;
  9802. ip->spine = (void **) soap_malloc(soap, SOAP_MAXPTRS * sizeof(void *));
  9803. if (!ip->spine)
  9804. return NULL;
  9805. ip->spine[0] = NULL;
  9806. for (i = 1; i < SOAP_MAXPTRS; i++)
  9807. ip->spine[i] = &ip->spine[i - 1];
  9808. }
  9809. *p = &ip->spine[k - 1];
  9810. if (ip->ptr && !ip->shaky)
  9811. ip->spine[0] = ip->ptr;
  9812. } else {
  9813. void *q = ip->link;
  9814. ip->link = p;
  9815. ip->shaky = soap_is_shaky(soap, (void *) p);
  9816. *p = q;
  9817. }
  9818. }
  9819. return p;
  9820. }
  9821. #endif
  9822. /******************************************************************************/
  9823. #ifndef WITH_NOIDREF
  9824. SOAP_FMAC1
  9825. void *
  9826. SOAP_FMAC2
  9827. soap_id_forward(struct soap *soap, const char *href, void *p, size_t i, int t, int tt, size_t n, unsigned int k,
  9828. void (*finsert)(struct soap *, int, int, void *, size_t, const void *, void **),
  9829. int (*fbase)(int, int)) {
  9830. struct soap_ilist *ip;
  9831. if (!p || !href || !*href)
  9832. return p;
  9833. ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */
  9834. if (!ip) {
  9835. ip = soap_enter(soap, href, t, n); /* new hash table entry for string id */
  9836. if (!ip)
  9837. return NULL;
  9838. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New entry href='%s' type=%d size=%lu level=%d location=%p\n", href, t,
  9839. (unsigned long) n, k, p));
  9840. } else if ((ip->type != t || ip->size != n) && k == 0) {
  9841. DBGLOG(TEST, SOAP_MESSAGE(fdebug,
  9842. "Forward type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n",
  9843. href, ip->type, (unsigned long) ip->size, k, t, (unsigned long) n));
  9844. (void) soap_id_nullify(soap, href);
  9845. return NULL;
  9846. }
  9847. if (finsert || n < sizeof(void *)) {
  9848. struct soap_flist *fp = (struct soap_flist *) SOAP_MALLOC(soap, sizeof(struct soap_flist));
  9849. if (!fp) {
  9850. soap->error = SOAP_EOM;
  9851. return NULL;
  9852. }
  9853. if (fbase && fbase(t, ip->type) && !soap_type_punned(soap, ip)) {
  9854. ip->type = t;
  9855. ip->size = n;
  9856. }
  9857. if ((ip->type != t || ip->size != n) && (!fbase || !fbase(ip->type, t))) {
  9858. DBGLOG(TEST, SOAP_MESSAGE(fdebug,
  9859. "Forward type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n",
  9860. href, ip->type, (unsigned long) ip->size, k, t, (unsigned long) n));
  9861. SOAP_FREE(soap, fp);
  9862. (void) soap_id_nullify(soap, href);
  9863. return NULL;
  9864. }
  9865. fp->next = ip->flist;
  9866. fp->type = tt;
  9867. fp->ptr = p;
  9868. fp->level = k;
  9869. fp->index = i;
  9870. fp->finsert = finsert;
  9871. ip->flist = fp;
  9872. DBGLOG(TEST, SOAP_MESSAGE(fdebug,
  9873. "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u index=%lu href='%s'\n",
  9874. t, tt, (unsigned long) n, p, k, (unsigned long) i, href));
  9875. } else {
  9876. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, t, href));
  9877. *(void **) p = ip->copy;
  9878. ip->copy = p;
  9879. }
  9880. ip->shaky = soap_is_shaky(soap, p);
  9881. return p;
  9882. }
  9883. #endif
  9884. /******************************************************************************/
  9885. SOAP_FMAC1
  9886. void *
  9887. SOAP_FMAC2
  9888. soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, const char *type, const char *arrayType,
  9889. void *(*finstantiate)(struct soap *, int, const char *, const char *, size_t *), int (*fbase)(int, int)) {
  9890. #ifndef WITH_NOIDREF
  9891. struct soap_ilist *ip;
  9892. #endif
  9893. (void) id;
  9894. (void) fbase;
  9895. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d location=%p size=%lu\n", id, t, p, (unsigned long) n));
  9896. soap->alloced = 0;
  9897. if (!p) {
  9898. if (finstantiate) {
  9899. p = finstantiate(soap, t, type, arrayType, &n); /* soap->alloced is set in soap_link() */
  9900. t = soap->alloced;
  9901. } else {
  9902. p = soap_malloc(soap, n);
  9903. soap->alloced = t;
  9904. }
  9905. }
  9906. #ifndef WITH_NOIDREF
  9907. if (!id || !*id)
  9908. #endif
  9909. return p;
  9910. #ifndef WITH_NOIDREF
  9911. ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
  9912. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup entry id='%s' for location=%p type=%d\n", id, p, t));
  9913. if (!ip) {
  9914. ip = soap_enter(soap, id, t, n); /* new hash table entry for string id */
  9915. if (!ip)
  9916. return NULL;
  9917. ip->ptr = p;
  9918. DBGLOG(TEST,
  9919. SOAP_MESSAGE(fdebug, "New entry id='%s' type=%d size=%lu location=%p\n", id, t, (unsigned long) n, p));
  9920. if (!soap->alloced)
  9921. ip->shaky = soap_is_shaky(soap, p);
  9922. } else if (ip->ptr) {
  9923. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id));
  9924. soap_strcpy(soap->id, sizeof(soap->id), id);
  9925. soap->error = SOAP_DUPLICATE_ID;
  9926. return NULL;
  9927. } else if ((ip->type != t && (!fbase || !fbase(t, ip->type) || soap_type_punned(soap, ip)))
  9928. || (ip->type == t && ip->size != n && soap_type_punned(soap, ip))) {
  9929. DBGLOG(TEST,
  9930. SOAP_MESSAGE(fdebug, "Enter type incompatibility id='%s' expect type=%d size=%lu got type=%d size=%lu\n",
  9931. id, ip->type, (unsigned long) ip->size, t, (unsigned long) n));
  9932. (void) soap_id_nullify(soap, id);
  9933. return NULL;
  9934. } else {
  9935. ip->type = t;
  9936. ip->size = n;
  9937. ip->ptr = p;
  9938. if (!soap->alloced)
  9939. ip->shaky = soap_is_shaky(soap, p);
  9940. if (soap->alloced || !ip->shaky) {
  9941. void **q; /* ptr will not change later, so resolve links now */
  9942. if (ip->spine)
  9943. ip->spine[0] = p;
  9944. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s' type=%d\n", ip->id, ip->type));
  9945. q = (void **) ip->link;
  9946. while (q) {
  9947. void *r = *q;
  9948. *q = p;
  9949. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... link %p -> %p\n", (void *) q, p));
  9950. q = (void **) r;
  9951. }
  9952. ip->link = NULL;
  9953. }
  9954. }
  9955. return ip->ptr;
  9956. #endif
  9957. }
  9958. /******************************************************************************/
  9959. SOAP_FMAC1
  9960. void **
  9961. SOAP_FMAC2
  9962. soap_id_smart(struct soap *soap, const char *id, int t, size_t n) {
  9963. (void) soap;
  9964. (void) id;
  9965. (void) t;
  9966. (void) n;
  9967. #ifndef WITH_NOIDREF
  9968. if (id && *id) {
  9969. struct soap_ilist *ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
  9970. if (!ip) {
  9971. ip = soap_enter(soap, id, t, n); /* new hash table entry for string id */
  9972. if (!ip)
  9973. return NULL;
  9974. }
  9975. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New smart shared pointer entry id='%s' type=%d size=%lu smart=%p\n", id, t,
  9976. (unsigned long) n, ip->smart));
  9977. return &ip->smart;
  9978. }
  9979. #endif
  9980. return NULL;
  9981. }
  9982. /******************************************************************************/
  9983. #ifndef WITH_NOIDREF
  9984. static int
  9985. soap_type_punned(struct soap *soap, const struct soap_ilist *ip) {
  9986. const struct soap_flist *fp;
  9987. (void) soap;
  9988. if (ip->ptr || ip->copy)
  9989. return 1;
  9990. for (fp = ip->flist; fp; fp = fp->next)
  9991. if (fp->level == 0)
  9992. return 1;
  9993. return 0;
  9994. }
  9995. #endif
  9996. /******************************************************************************/
  9997. #ifndef WITH_NOIDREF
  9998. SOAP_FMAC1
  9999. int
  10000. SOAP_FMAC2
  10001. soap_id_nullify(struct soap *soap, const char *id) {
  10002. int i;
  10003. for (i = 0; i < SOAP_IDHASH; i++) {
  10004. struct soap_ilist *ip;
  10005. for (ip = soap->iht[i]; ip; ip = ip->next) {
  10006. void *p, *q;
  10007. for (p = ip->link; p; p = q) {
  10008. q = *(void **) p;
  10009. *(void **) p = NULL;
  10010. }
  10011. ip->link = NULL;
  10012. }
  10013. }
  10014. soap_strcpy(soap->id, sizeof(soap->id), id);
  10015. return soap->error = SOAP_HREF;
  10016. }
  10017. #endif
  10018. /******************************************************************************/
  10019. SOAP_FMAC1
  10020. int
  10021. SOAP_FMAC2
  10022. soap_end_send(struct soap *soap) {
  10023. #ifndef WITH_LEANER
  10024. int err;
  10025. err = soap_end_attachments(soap);
  10026. if (soap->dime.list) {
  10027. /* SOAP body referenced attachments must appear first */
  10028. soap->dime.last->next = soap->dime.first;
  10029. soap->dime.first = soap->dime.list->next;
  10030. soap->dime.list->next = NULL;
  10031. soap->dime.last = soap->dime.list;
  10032. }
  10033. if (!err)
  10034. err = soap_putdime(soap);
  10035. if (!err)
  10036. err = soap_putmime(soap);
  10037. soap->mime.list = NULL;
  10038. soap->mime.first = NULL;
  10039. soap->mime.last = NULL;
  10040. soap->dime.list = NULL;
  10041. soap->dime.first = NULL;
  10042. soap->dime.last = NULL;
  10043. if (err)
  10044. return err;
  10045. #endif
  10046. return soap_end_send_flush(soap);
  10047. }
  10048. /******************************************************************************/
  10049. SOAP_FMAC1
  10050. int
  10051. SOAP_FMAC2
  10052. soap_end_send_flush(struct soap *soap) {
  10053. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send mode=0x%x\n", soap->mode));
  10054. if ((soap->mode & SOAP_IO)) /* need to flush the remaining data in buffer */
  10055. {
  10056. if (soap_flush(soap))
  10057. #ifdef WITH_ZLIB
  10058. {
  10059. if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state == SOAP_ZLIB_DEFLATE)
  10060. {
  10061. soap->zlib_state = SOAP_ZLIB_NONE;
  10062. deflateEnd(soap->d_stream);
  10063. }
  10064. return soap->error;
  10065. }
  10066. #else
  10067. return soap->error;
  10068. #endif
  10069. #ifdef WITH_ZLIB
  10070. if ((soap->mode & SOAP_ENC_ZLIB) && soap->d_stream)
  10071. {
  10072. int r;
  10073. soap->d_stream->avail_in = 0;
  10074. do
  10075. {
  10076. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n"));
  10077. r = deflate(soap->d_stream, Z_FINISH);
  10078. if (soap->d_stream->avail_out != sizeof(soap->buf))
  10079. {
  10080. if (soap_flush_raw(soap, soap->z_buf, sizeof(soap->buf) - soap->d_stream->avail_out))
  10081. {
  10082. soap->zlib_state = SOAP_ZLIB_NONE;
  10083. deflateEnd(soap->d_stream);
  10084. return soap->error;
  10085. }
  10086. soap->d_stream->next_out = (Byte*)soap->z_buf;
  10087. soap->d_stream->avail_out = sizeof(soap->buf);
  10088. }
  10089. } while (r == Z_OK);
  10090. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
  10091. soap->z_ratio_out = (float)soap->d_stream->total_out / (float)soap->d_stream->total_in;
  10092. soap->mode &= ~SOAP_ENC_ZLIB;
  10093. soap->zlib_state = SOAP_ZLIB_NONE;
  10094. if (deflateEnd(soap->d_stream) != Z_OK || r != Z_STREAM_END)
  10095. {
  10096. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
  10097. return soap->error = SOAP_ZLIB_ERROR;
  10098. }
  10099. #ifdef WITH_GZIP
  10100. if (soap->zlib_out != SOAP_ZLIB_DEFLATE)
  10101. {
  10102. soap->z_buf[0] = soap->z_crc & 0xFF;
  10103. soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF;
  10104. soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF;
  10105. soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF;
  10106. soap->z_buf[4] = soap->d_stream->total_in & 0xFF;
  10107. soap->z_buf[5] = (soap->d_stream->total_in >> 8) & 0xFF;
  10108. soap->z_buf[6] = (soap->d_stream->total_in >> 16) & 0xFF;
  10109. soap->z_buf[7] = (soap->d_stream->total_in >> 24) & 0xFF;
  10110. if (soap_flush_raw(soap, soap->z_buf, 8))
  10111. return soap->error;
  10112. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc));
  10113. }
  10114. #endif
  10115. }
  10116. #endif
  10117. if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) {
  10118. #if !defined(__cplusplus) || defined(WITH_COMPAT)
  10119. if (soap->os)
  10120. {
  10121. char *b = (char*)soap_push_block(soap, NULL, 1);
  10122. if (b)
  10123. {
  10124. *b = '\0';
  10125. *soap->os = soap_save_block(soap, NULL, NULL, 0);
  10126. }
  10127. }
  10128. else
  10129. #endif
  10130. {
  10131. char *p;
  10132. #ifndef WITH_NOHTTP
  10133. if (!(soap->mode & SOAP_ENC_PLAIN)) {
  10134. soap->mode--;
  10135. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n",
  10136. (unsigned int) soap->blist->size));
  10137. if (soap->status >= SOAP_POST)
  10138. soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path,
  10139. soap->action, soap->blist->size);
  10140. else if (soap->status != SOAP_STOP)
  10141. soap->error = soap->fresponse(soap, soap->status, soap->blist->size);
  10142. if (soap->error || soap_flush(soap))
  10143. return soap->error;
  10144. soap->mode++;
  10145. }
  10146. #endif
  10147. for (p = soap_first_block(soap, NULL); p; p = soap_next_block(soap, NULL)) {
  10148. DBGMSG(SENT, p, soap_block_size(soap, NULL));
  10149. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send %u bytes to socket=%d/fd=%d\n",
  10150. (unsigned int) soap_block_size(soap, NULL), (int) soap->socket,
  10151. soap->sendfd));
  10152. soap->error = soap->fsend(soap, p, soap_block_size(soap, NULL));
  10153. if (soap->error) {
  10154. soap_end_block(soap, NULL);
  10155. return soap->error;
  10156. }
  10157. }
  10158. soap_end_block(soap, NULL);
  10159. }
  10160. #ifndef WITH_LEANER
  10161. if (soap->fpreparefinalsend && (soap->error = soap->fpreparefinalsend(soap)) != SOAP_OK)
  10162. return soap->error;
  10163. #endif
  10164. if ((soap->omode & SOAP_IO) == SOAP_IO_STORE && (soap->imode & SOAP_IO) != SOAP_IO_STORE)
  10165. soap->omode = (soap->omode & ~SOAP_IO) | (soap->imode & SOAP_IO);
  10166. }
  10167. #ifndef WITH_LEANER
  10168. else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) {
  10169. DBGMSG(SENT, "\r\n0\r\n\r\n", 7);
  10170. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send 7 bytes to socket=%d/fd=%d\n", (int) soap->socket, soap->sendfd));
  10171. soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7);
  10172. if (soap->error)
  10173. return soap->error;
  10174. }
  10175. #endif
  10176. }
  10177. #ifdef WITH_TCPFIN
  10178. #if defined(WITH_OPENSSL) || defined(WITH_SYSTEMSSL)
  10179. if (!soap->ssl)
  10180. #endif
  10181. if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
  10182. soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR); /* Send TCP FIN */
  10183. #endif
  10184. #if defined(__cplusplus) && !defined(WITH_COMPAT)
  10185. if (soap->os)
  10186. soap->os->flush();
  10187. #endif
  10188. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n"));
  10189. soap->omode &= ~SOAP_SEC_WSUID;
  10190. soap->count = 0;
  10191. soap->part = SOAP_END;
  10192. return SOAP_OK;
  10193. }
  10194. /******************************************************************************/
  10195. SOAP_FMAC1
  10196. int
  10197. SOAP_FMAC2
  10198. soap_end_recv(struct soap *soap) {
  10199. soap->part = SOAP_END;
  10200. #ifndef WITH_LEAN
  10201. soap->wsuid = NULL; /* reset before next send */
  10202. soap->c14nexclude = NULL; /* reset before next send */
  10203. soap->c14ninclude = NULL; /* reset before next send */
  10204. #endif
  10205. #ifndef WITH_LEANER
  10206. soap->ffilterrecv = NULL;
  10207. if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap)) {
  10208. soap->dime.first = NULL;
  10209. soap->dime.last = NULL;
  10210. return soap->error;
  10211. }
  10212. soap->dime.list = soap->dime.first;
  10213. soap->dime.first = NULL;
  10214. soap->dime.last = NULL;
  10215. /* Check if MIME attachments and mime-post-check flag is set, if so call soap_resolve() and return */
  10216. if ((soap->mode & SOAP_ENC_MIME)) {
  10217. if ((soap->mode & SOAP_MIME_POSTCHECK)) {
  10218. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Post checking MIME attachments\n"));
  10219. if (!soap->keep_alive)
  10220. soap->keep_alive = -2; /* special case to keep alive */
  10221. #ifndef WITH_NOIDREF
  10222. soap_resolve(soap);
  10223. #endif
  10224. return SOAP_OK;
  10225. }
  10226. if (soap_getmime(soap))
  10227. return soap->error;
  10228. }
  10229. soap->mime.list = soap->mime.first;
  10230. soap->mime.first = NULL;
  10231. soap->mime.last = NULL;
  10232. soap->mime.boundary = NULL;
  10233. if (soap->xlist) {
  10234. struct soap_multipart *content;
  10235. for (content = soap->mime.list; content; content = content->next)
  10236. soap_resolve_attachment(soap, content);
  10237. }
  10238. #endif
  10239. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of receive message ok\n"));
  10240. #ifdef WITH_ZLIB
  10241. if ((soap->mode & SOAP_ENC_ZLIB) && soap->d_stream)
  10242. {
  10243. /* Make sure end of compressed content is reached */
  10244. while (soap->d_stream->next_out != Z_NULL)
  10245. if ((int)soap_get1(soap) == EOF)
  10246. break;
  10247. soap->mode &= ~SOAP_ENC_ZLIB;
  10248. (void)soap_memcpy((void*)soap->buf, sizeof(soap->buf), (const void*)soap->z_buf, sizeof(soap->buf));
  10249. soap->bufidx = (char*)soap->d_stream->next_in - soap->z_buf;
  10250. soap->buflen = soap->z_buflen;
  10251. soap->zlib_state = SOAP_ZLIB_NONE;
  10252. if (inflateEnd(soap->d_stream) != Z_OK)
  10253. return soap->error = SOAP_ZLIB_ERROR;
  10254. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate end ok\n"));
  10255. #ifdef WITH_GZIP
  10256. if (soap->zlib_in == SOAP_ZLIB_GZIP)
  10257. {
  10258. soap_wchar c;
  10259. short i;
  10260. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate gzip crc check\n"));
  10261. for (i = 0; i < 8; i++)
  10262. {
  10263. if ((int)(c = soap_get1(soap)) == EOF)
  10264. {
  10265. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Gzip error: unable to read crc value\n"));
  10266. return soap->error = SOAP_ZLIB_ERROR;
  10267. }
  10268. soap->z_buf[i] = (char)c;
  10269. }
  10270. if (soap->z_crc != ((uLong)(unsigned char)soap->z_buf[0] | ((uLong)(unsigned char)soap->z_buf[1] << 8) | ((uLong)(unsigned char)soap->z_buf[2] << 16) | ((uLong)(unsigned char)soap->z_buf[3] << 24)))
  10271. {
  10272. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Gzip inflate error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc));
  10273. return soap->error = SOAP_ZLIB_ERROR;
  10274. }
  10275. if (soap->d_stream->total_out != ((uLong)(unsigned char)soap->z_buf[4] | ((uLong)(unsigned char)soap->z_buf[5] << 8) | ((uLong)(unsigned char)soap->z_buf[6] << 16) | ((uLong)(unsigned char)soap->z_buf[7] << 24)))
  10276. {
  10277. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Gzip inflate error: incorrect message length\n"));
  10278. return soap->error = SOAP_ZLIB_ERROR;
  10279. }
  10280. }
  10281. soap->zlib_in = SOAP_ZLIB_NONE;
  10282. #endif
  10283. }
  10284. #endif
  10285. if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
  10286. while ((int) soap->ahead != EOF && !soap_recv_raw(soap))
  10287. continue;
  10288. #ifndef WITH_NOIDREF
  10289. if (soap_resolve(soap))
  10290. return soap->error;
  10291. #endif
  10292. #ifndef WITH_LEANER
  10293. if (soap->xlist) {
  10294. if ((soap->mode & SOAP_ENC_MTOM))
  10295. return soap->error = SOAP_MIME_HREF;
  10296. return soap->error = SOAP_DIME_HREF;
  10297. }
  10298. #endif
  10299. soap_free_ns(soap);
  10300. #ifndef WITH_LEANER
  10301. if (soap->fpreparefinalrecv)
  10302. return soap->error = soap->fpreparefinalrecv(soap);
  10303. #endif
  10304. return SOAP_OK;
  10305. }
  10306. /******************************************************************************/
  10307. SOAP_FMAC1
  10308. void
  10309. SOAP_FMAC2
  10310. soap_free_temp(struct soap *soap) {
  10311. struct soap_attribute *tp, *tq;
  10312. struct Namespace *ns;
  10313. soap_free_ns(soap);
  10314. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n"));
  10315. while (soap->blist)
  10316. soap_end_block(soap, NULL);
  10317. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n"));
  10318. for (tp = soap->attributes; tp; tp = tq) {
  10319. tq = tp->next;
  10320. if (tp->value)
  10321. SOAP_FREE(soap, tp->value);
  10322. SOAP_FREE(soap, tp);
  10323. }
  10324. soap->attributes = NULL;
  10325. #ifdef WITH_FAST
  10326. if (soap->labbuf)
  10327. SOAP_FREE(soap, soap->labbuf);
  10328. soap->labbuf = NULL;
  10329. soap->lablen = 0;
  10330. soap->labidx = 0;
  10331. #endif
  10332. ns = soap->local_namespaces;
  10333. if (ns) {
  10334. for (; ns->id; ns++) {
  10335. if (ns->out) {
  10336. SOAP_FREE(soap, ns->out);
  10337. ns->out = NULL;
  10338. }
  10339. }
  10340. SOAP_FREE(soap, soap->local_namespaces);
  10341. soap->local_namespaces = NULL;
  10342. }
  10343. #ifndef WITH_LEANER
  10344. while (soap->xlist) {
  10345. struct soap_xlist *xp = soap->xlist->next;
  10346. SOAP_FREE(soap, soap->xlist);
  10347. soap->xlist = xp;
  10348. }
  10349. #endif
  10350. #ifndef WITH_NOIDREF
  10351. soap_free_iht(soap);
  10352. #endif
  10353. soap_free_pht(soap);
  10354. }
  10355. /******************************************************************************/
  10356. static void
  10357. soap_free_ns(struct soap *soap) {
  10358. struct soap_nlist *np, *nq;
  10359. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n"));
  10360. for (np = soap->nlist; np; np = nq) {
  10361. nq = np->next;
  10362. SOAP_FREE(soap, np);
  10363. }
  10364. soap->nlist = NULL;
  10365. }
  10366. /******************************************************************************/
  10367. #ifdef SOAP_DEBUG
  10368. static void
  10369. soap_init_logs(struct soap *soap)
  10370. {
  10371. int i;
  10372. for (i = 0; i < SOAP_MAXLOGS; i++)
  10373. {
  10374. soap->logfile[i] = NULL;
  10375. soap->fdebug[i] = NULL;
  10376. }
  10377. }
  10378. #endif
  10379. /******************************************************************************/
  10380. #ifdef SOAP_DEBUG
  10381. SOAP_FMAC1
  10382. void
  10383. SOAP_FMAC2
  10384. soap_open_logfile(struct soap *soap, int i)
  10385. {
  10386. if (soap->logfile[i])
  10387. soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a");
  10388. }
  10389. #endif
  10390. /******************************************************************************/
  10391. #ifdef SOAP_DEBUG
  10392. static void
  10393. soap_close_logfile(struct soap *soap, int i)
  10394. {
  10395. if (soap->fdebug[i])
  10396. {
  10397. fclose(soap->fdebug[i]);
  10398. soap->fdebug[i] = NULL;
  10399. }
  10400. }
  10401. #endif
  10402. /******************************************************************************/
  10403. #ifdef SOAP_DEBUG
  10404. SOAP_FMAC1
  10405. void
  10406. SOAP_FMAC2
  10407. soap_close_logfiles(struct soap *soap)
  10408. {
  10409. int i;
  10410. for (i = 0; i < SOAP_MAXLOGS; i++)
  10411. soap_close_logfile(soap, i);
  10412. }
  10413. #endif
  10414. /******************************************************************************/
  10415. #ifdef SOAP_DEBUG
  10416. static void
  10417. soap_set_logfile(struct soap *soap, int i, const char *logfile)
  10418. {
  10419. const char *s;
  10420. char *t = NULL;
  10421. soap_close_logfile(soap, i);
  10422. s = soap->logfile[i];
  10423. if (s)
  10424. SOAP_FREE_UNMANAGED(s);
  10425. if (logfile)
  10426. {
  10427. size_t l = strlen(logfile) + 1;
  10428. t = (char*)SOAP_MALLOC_UNMANAGED(l);
  10429. if (t)
  10430. (void)soap_memcpy((void*)t, l, (const void*)logfile, l);
  10431. }
  10432. soap->logfile[i] = t;
  10433. }
  10434. #endif
  10435. /******************************************************************************/
  10436. SOAP_FMAC1
  10437. void
  10438. SOAP_FMAC2
  10439. soap_set_recv_logfile(struct soap *soap, const char *logfile) {
  10440. (void) soap;
  10441. (void) logfile;
  10442. #ifdef SOAP_DEBUG
  10443. soap_set_logfile(soap, SOAP_INDEX_RECV, logfile);
  10444. #endif
  10445. }
  10446. /******************************************************************************/
  10447. SOAP_FMAC1
  10448. void
  10449. SOAP_FMAC2
  10450. soap_set_sent_logfile(struct soap *soap, const char *logfile) {
  10451. (void) soap;
  10452. (void) logfile;
  10453. #ifdef SOAP_DEBUG
  10454. soap_set_logfile(soap, SOAP_INDEX_SENT, logfile);
  10455. #endif
  10456. }
  10457. /******************************************************************************/
  10458. SOAP_FMAC1
  10459. void
  10460. SOAP_FMAC2
  10461. soap_set_test_logfile(struct soap *soap, const char *logfile) {
  10462. (void) soap;
  10463. (void) logfile;
  10464. #ifdef SOAP_DEBUG
  10465. soap_set_logfile(soap, SOAP_INDEX_TEST, logfile);
  10466. #endif
  10467. }
  10468. /******************************************************************************/
  10469. SOAP_FMAC1
  10470. struct soap *
  10471. SOAP_FMAC2
  10472. soap_copy(const struct soap *soap) {
  10473. struct soap *copy = soap_versioning(soap_new)(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT);
  10474. soap_done(copy);
  10475. if (soap_copy_context(copy, soap) != NULL)
  10476. return copy;
  10477. soap_free(copy);
  10478. return NULL;
  10479. }
  10480. /******************************************************************************/
  10481. SOAP_FMAC1
  10482. struct soap *
  10483. SOAP_FMAC2
  10484. soap_copy_context(struct soap *copy, const struct soap *soap) {
  10485. if (copy == soap)
  10486. return copy;
  10487. if (soap_check_state(soap))
  10488. return NULL;
  10489. if (copy) {
  10490. struct soap_plugin *p = NULL;
  10491. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying context\n"));
  10492. (void) soap_memcpy((void *) copy, sizeof(struct soap), (const void *) soap, sizeof(struct soap));
  10493. copy->state = SOAP_COPY;
  10494. copy->error = SOAP_OK;
  10495. copy->bearer = NULL;
  10496. copy->userid = NULL;
  10497. copy->passwd = NULL;
  10498. #ifdef WITH_NTLM
  10499. copy->ntlm_challenge = NULL;
  10500. #endif
  10501. copy->nlist = NULL;
  10502. copy->blist = NULL;
  10503. copy->clist = NULL;
  10504. copy->alist = NULL;
  10505. copy->attributes = NULL;
  10506. copy->labbuf = NULL;
  10507. copy->lablen = 0;
  10508. copy->labidx = 0;
  10509. #ifdef SOAP_MEM_DEBUG
  10510. soap_init_mht(copy);
  10511. #endif
  10512. #ifdef SOAP_DEBUG
  10513. soap_init_logs(copy);
  10514. soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]);
  10515. soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]);
  10516. soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]);
  10517. #endif
  10518. copy->namespaces = soap->local_namespaces;
  10519. copy->local_namespaces = NULL;
  10520. soap_set_local_namespaces(copy); /* copy content of soap->local_namespaces */
  10521. copy->namespaces = soap->namespaces; /* point to shared read-only namespaces table */
  10522. copy->c_locale = NULL;
  10523. #ifdef WITH_OPENSSL
  10524. copy->bio = NULL;
  10525. copy->ssl = NULL;
  10526. copy->session = NULL;
  10527. copy->session_host[0] = '\0';
  10528. copy->session_port = 443;
  10529. #endif
  10530. #ifdef WITH_GNUTLS
  10531. copy->session = NULL;
  10532. #endif
  10533. #ifdef WITH_ZLIB
  10534. copy->d_stream = NULL;
  10535. copy->z_buf = NULL;
  10536. #endif
  10537. #ifndef WITH_NOIDREF
  10538. soap_init_iht(copy);
  10539. #endif
  10540. soap_init_pht(copy);
  10541. copy->header = NULL;
  10542. copy->fault = NULL;
  10543. copy->action = NULL;
  10544. #ifndef WITH_LEAN
  10545. #ifdef WITH_COOKIES
  10546. copy->cookies = soap_copy_cookies(copy, soap);
  10547. #else
  10548. copy->cookies = NULL;
  10549. #endif
  10550. #endif
  10551. copy->plugins = NULL;
  10552. for (p = soap->plugins; p; p = p->next) {
  10553. struct soap_plugin *q = (struct soap_plugin *) SOAP_MALLOC(copy, sizeof(struct soap_plugin));
  10554. if (!q) {
  10555. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not allocate plugin '%s'\n", p->id));
  10556. soap_end(copy);
  10557. soap_done(copy);
  10558. return NULL;
  10559. }
  10560. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id));
  10561. *q = *p;
  10562. if (p->fcopy && (copy->error = p->fcopy(copy, q, p)) != SOAP_OK) {
  10563. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s' error = %d\n", p->id, copy->error));
  10564. SOAP_FREE(copy, q);
  10565. soap_end(copy);
  10566. soap_done(copy);
  10567. return NULL;
  10568. }
  10569. q->next = copy->plugins;
  10570. copy->plugins = q;
  10571. }
  10572. }
  10573. #ifdef WITH_SELF_PIPE
  10574. pipe(copy->pipe_fd);
  10575. SOAP_SOCKNONBLOCK(copy->pipe_fd[0])
  10576. SOAP_SOCKNONBLOCK(copy->pipe_fd[1])
  10577. #endif
  10578. return copy;
  10579. }
  10580. /******************************************************************************/
  10581. SOAP_FMAC1
  10582. void
  10583. SOAP_FMAC2
  10584. soap_copy_stream(struct soap *copy, struct soap *soap) {
  10585. struct soap_attribute *tp = NULL, *tq;
  10586. if (copy == soap)
  10587. return;
  10588. copy->header = soap->header;
  10589. copy->mode = soap->mode;
  10590. copy->imode = soap->imode;
  10591. copy->omode = soap->omode;
  10592. copy->socket = soap->socket;
  10593. copy->sendsk = soap->sendsk;
  10594. copy->recvsk = soap->recvsk;
  10595. copy->transfer_timeout = soap->transfer_timeout;
  10596. copy->recv_maxlength = soap->recv_maxlength;
  10597. copy->recv_timeout = soap->recv_timeout;
  10598. copy->send_timeout = soap->send_timeout;
  10599. copy->connect_timeout = soap->connect_timeout;
  10600. copy->accept_timeout = soap->accept_timeout;
  10601. copy->socket_flags = soap->socket_flags;
  10602. copy->connect_flags = soap->connect_flags;
  10603. copy->bind_flags = soap->bind_flags;
  10604. copy->bind_inet6 = soap->bind_inet6;
  10605. copy->bind_v6only = soap->bind_v6only;
  10606. copy->accept_flags = soap->accept_flags;
  10607. copy->sndbuf = soap->sndbuf;
  10608. copy->rcvbuf = soap->rcvbuf;
  10609. copy->linger_time = soap->linger_time;
  10610. copy->maxlevel = soap->maxlevel;
  10611. copy->maxlength = soap->maxlength;
  10612. copy->maxoccurs = soap->maxoccurs;
  10613. copy->os = soap->os;
  10614. copy->is = soap->is;
  10615. copy->sendfd = soap->sendfd;
  10616. copy->recvfd = soap->recvfd;
  10617. copy->bufidx = soap->bufidx;
  10618. copy->buflen = soap->buflen;
  10619. copy->ahead = soap->ahead;
  10620. copy->cdata = soap->cdata;
  10621. copy->chunksize = soap->chunksize;
  10622. copy->chunkbuflen = soap->chunkbuflen;
  10623. copy->keep_alive = soap->keep_alive;
  10624. copy->tcp_keep_alive = soap->tcp_keep_alive;
  10625. copy->tcp_keep_idle = soap->tcp_keep_idle;
  10626. copy->tcp_keep_intvl = soap->tcp_keep_intvl;
  10627. copy->tcp_keep_cnt = soap->tcp_keep_cnt;
  10628. copy->max_keep_alive = soap->max_keep_alive;
  10629. #ifndef WITH_NOIO
  10630. copy->peer = soap->peer;
  10631. copy->peerlen = soap->peerlen;
  10632. copy->ip = soap->ip;
  10633. copy->ip6[0] = soap->ip6[0];
  10634. copy->ip6[1] = soap->ip6[1];
  10635. copy->ip6[2] = soap->ip6[2];
  10636. copy->ip6[3] = soap->ip6[3];
  10637. copy->port = soap->port;
  10638. (void) soap_memcpy((void *) copy->host, sizeof(copy->host), (const void *) soap->host, sizeof(soap->host));
  10639. (void) soap_memcpy((void *) copy->endpoint, sizeof(copy->endpoint), (const void *) soap->endpoint,
  10640. sizeof(soap->endpoint));
  10641. #endif
  10642. #ifdef WITH_OPENSSL
  10643. copy->bio = soap->bio;
  10644. copy->ctx = soap->ctx;
  10645. copy->ssl = soap->ssl;
  10646. #endif
  10647. #ifdef WITH_GNUTLS
  10648. copy->session = soap->session;
  10649. #endif
  10650. #ifdef WITH_SYSTEMSSL
  10651. copy->ctx = soap->ctx;
  10652. copy->ssl = soap->ssl;
  10653. #endif
  10654. #ifdef WITH_ZLIB
  10655. copy->zlib_state = soap->zlib_state;
  10656. copy->zlib_in = soap->zlib_in;
  10657. copy->zlib_out = soap->zlib_out;
  10658. if (soap->d_stream && soap->zlib_state != SOAP_ZLIB_NONE)
  10659. {
  10660. if (!copy->d_stream)
  10661. copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream));
  10662. if (copy->d_stream)
  10663. (void)soap_memcpy((void*)copy->d_stream, sizeof(z_stream), (const void*)soap->d_stream, sizeof(z_stream));
  10664. }
  10665. copy->z_crc = soap->z_crc;
  10666. copy->z_ratio_in = soap->z_ratio_in;
  10667. copy->z_ratio_out = soap->z_ratio_out;
  10668. copy->z_buf = NULL;
  10669. copy->z_buflen = soap->z_buflen;
  10670. copy->z_level = soap->z_level;
  10671. if (soap->z_buf && soap->zlib_state != SOAP_ZLIB_NONE)
  10672. {
  10673. copy->z_buf = (char*)SOAP_MALLOC(copy, sizeof(soap->buf));
  10674. if (copy->z_buf)
  10675. (void)soap_memcpy((void*)copy->z_buf, sizeof(soap->buf), (const void*)soap->z_buf, sizeof(soap->buf));
  10676. }
  10677. copy->z_dict = soap->z_dict;
  10678. copy->z_dict_len = soap->z_dict_len;
  10679. #endif
  10680. (void) soap_memcpy((void *) copy->buf, sizeof(copy->buf), (const void *) soap->buf, sizeof(soap->buf));
  10681. /* copy XML parser state */
  10682. soap_free_ns(copy);
  10683. soap_set_local_namespaces(copy);
  10684. copy->version = soap->version;
  10685. if (soap->nlist && soap->local_namespaces) {
  10686. struct soap_nlist *np = NULL, *nq;
  10687. /* copy reversed nlist */
  10688. for (nq = soap->nlist; nq; nq = nq->next) {
  10689. struct soap_nlist *nr = np;
  10690. size_t n = sizeof(struct soap_nlist) + strlen(nq->id);
  10691. np = (struct soap_nlist *) SOAP_MALLOC(copy, n);
  10692. if (!np) {
  10693. np = nr;
  10694. break;
  10695. }
  10696. (void) soap_memcpy((void *) np, n, (const void *) nq, n);
  10697. np->next = nr;
  10698. }
  10699. while (np) {
  10700. const char *s = np->ns;
  10701. copy->level = np->level; /* preserve element nesting level */
  10702. if (!s && np->index >= 0) {
  10703. s = soap->local_namespaces[np->index].out;
  10704. if (!s)
  10705. s = soap->local_namespaces[np->index].ns;
  10706. }
  10707. if (s)
  10708. (void) soap_push_namespace(copy, np->id, s);
  10709. nq = np;
  10710. np = np->next;
  10711. SOAP_FREE(copy, nq);
  10712. }
  10713. }
  10714. (void) soap_memcpy((void *) copy->tag, sizeof(copy->tag), (const void *) soap->tag, sizeof(soap->tag));
  10715. (void) soap_memcpy((void *) copy->id, sizeof(copy->id), (const void *) soap->id, sizeof(soap->id));
  10716. (void) soap_memcpy((void *) copy->href, sizeof(copy->href), (const void *) soap->href, sizeof(soap->href));
  10717. (void) soap_memcpy((void *) copy->type, sizeof(copy->type), (const void *) soap->type, sizeof(soap->type));
  10718. copy->other = soap->other;
  10719. copy->root = soap->root;
  10720. copy->null = soap->null;
  10721. copy->body = soap->body;
  10722. copy->part = soap->part;
  10723. copy->mustUnderstand = soap->mustUnderstand;
  10724. copy->level = soap->level;
  10725. copy->peeked = soap->peeked;
  10726. /* copy attributes */
  10727. for (tq = soap->attributes; tq; tq = tq->next) {
  10728. struct soap_attribute *tr = tp;
  10729. size_t n = sizeof(struct soap_attribute) + strlen(tq->name);
  10730. tp = (struct soap_attribute *) SOAP_MALLOC(copy, n);
  10731. (void) soap_memcpy((void *) tp, n, (const void *) tq, n);
  10732. if (tp->size) {
  10733. tp->value = (char *) SOAP_MALLOC(copy, tp->size);
  10734. if (tp->value)
  10735. (void) soap_memcpy((void *) tp->value, tp->size, (const void *) tq->value, tp->size);
  10736. }
  10737. tp->ns = NULL;
  10738. tp->next = tr;
  10739. }
  10740. copy->attributes = tp;
  10741. }
  10742. /******************************************************************************/
  10743. SOAP_FMAC1
  10744. void
  10745. SOAP_FMAC2
  10746. soap_free_stream(struct soap *soap) {
  10747. soap->socket = SOAP_INVALID_SOCKET;
  10748. soap->sendsk = SOAP_INVALID_SOCKET;
  10749. soap->recvsk = SOAP_INVALID_SOCKET;
  10750. #ifdef WITH_OPENSSL
  10751. soap->bio = NULL;
  10752. soap->ctx = NULL;
  10753. soap->ssl = NULL;
  10754. #endif
  10755. #ifdef WITH_GNUTLS
  10756. soap->xcred = NULL;
  10757. soap->acred = NULL;
  10758. soap->cache = NULL;
  10759. soap->session = NULL;
  10760. soap->dh_params = NULL;
  10761. soap->rsa_params = NULL;
  10762. #endif
  10763. #ifdef WITH_SYSTEMSSL
  10764. soap->ctx = (gsk_handle)NULL;
  10765. soap->ssl = (gsk_handle)NULL;
  10766. #endif
  10767. #ifdef WITH_ZLIB
  10768. if (soap->z_buf)
  10769. SOAP_FREE(soap, soap->z_buf);
  10770. soap->z_buf = NULL;
  10771. #endif
  10772. }
  10773. /******************************************************************************/
  10774. SOAP_FMAC1
  10775. void
  10776. SOAP_FMAC2
  10777. soap_initialize(struct soap *soap) {
  10778. soap_versioning(soap_init)(soap, SOAP_IO_DEFAULT, SOAP_IO_DEFAULT);
  10779. }
  10780. /******************************************************************************/
  10781. SOAP_FMAC1
  10782. void
  10783. SOAP_FMAC2
  10784. soap_versioning(soap_init)(struct soap *soap, soap_mode imode, soap_mode omode) {
  10785. size_t i;
  10786. soap->state = SOAP_INIT;
  10787. #ifdef SOAP_MEM_DEBUG
  10788. soap_init_mht(soap);
  10789. #endif
  10790. #ifdef SOAP_DEBUG
  10791. soap_init_logs(soap);
  10792. #endif
  10793. #ifdef TANDEM_NONSTOP
  10794. soap_set_test_logfile(soap, "TESTLOG");
  10795. soap_set_sent_logfile(soap, "SENTLOG");
  10796. soap_set_recv_logfile(soap, "RECVLOG");
  10797. #else
  10798. soap_set_test_logfile(soap, "TEST.log");
  10799. soap_set_sent_logfile(soap, "SENT.log");
  10800. soap_set_recv_logfile(soap, "RECV.log");
  10801. #endif
  10802. #ifdef WITH_SELF_PIPE
  10803. pipe(soap->pipe_fd);
  10804. SOAP_SOCKNONBLOCK(soap->pipe_fd[0])
  10805. SOAP_SOCKNONBLOCK(soap->pipe_fd[1])
  10806. #endif
  10807. soap->version = 0;
  10808. soap->imode = imode;
  10809. soap->omode = omode;
  10810. soap->mode = imode;
  10811. soap->plugins = NULL;
  10812. soap->user = NULL;
  10813. for (i = 0; i < sizeof(soap->data) / sizeof(*soap->data); i++)
  10814. soap->data[i] = NULL;
  10815. soap->bearer = NULL;
  10816. soap->userid = NULL;
  10817. soap->passwd = NULL;
  10818. soap->authrealm = NULL;
  10819. #ifdef WITH_NTLM
  10820. soap->ntlm_challenge = NULL;
  10821. #endif
  10822. #ifndef WITH_NOHTTP
  10823. soap->fpost = http_post;
  10824. soap->fget = http_get;
  10825. soap->fput = http_put;
  10826. soap->fpatch = http_patch;
  10827. soap->fdel = http_del;
  10828. soap->fopt = http_200;
  10829. soap->fhead = http_200;
  10830. soap->fform = NULL;
  10831. soap->fposthdr = http_post_header;
  10832. soap->fresponse = http_response;
  10833. soap->fparse = http_parse;
  10834. soap->fparsehdr = http_parse_header;
  10835. #endif
  10836. soap->fheader = NULL;
  10837. soap->fconnect = NULL;
  10838. soap->fdisconnect = NULL;
  10839. #ifndef WITH_NOIO
  10840. soap->ipv6_multicast_if = 0; /* in_addr_t value */
  10841. soap->ipv4_multicast_if = NULL; /* points to struct in_addr or in_addr_t */
  10842. soap->ipv4_multicast_ttl = 0; /* 0: use default */
  10843. soap->client_port = -1; /* client port to bind, -1 for none */
  10844. soap->client_interface = NULL; /* client interface address, NULL for none */
  10845. #ifndef WITH_IPV6
  10846. soap->fresolve = tcp_gethost;
  10847. #else
  10848. soap->fresolve = NULL;
  10849. #endif
  10850. soap->faccept = tcp_accept;
  10851. soap->fopen = tcp_connect;
  10852. soap->fclose = tcp_disconnect;
  10853. soap->fclosesocket = tcp_closesocket;
  10854. soap->fshutdownsocket = tcp_shutdownsocket;
  10855. soap->fsend = fsend;
  10856. soap->frecv = frecv;
  10857. soap->fpoll = soap_poll;
  10858. #else
  10859. soap->fopen = NULL;
  10860. soap->fclose = NULL;
  10861. soap->fpoll = NULL;
  10862. #endif
  10863. soap->fseterror = NULL;
  10864. soap->fignore = NULL;
  10865. soap->fserveloop = NULL;
  10866. soap->fplugin = fplugin;
  10867. #ifndef WITH_LEANER
  10868. soap->fsvalidate = NULL;
  10869. soap->fwvalidate = NULL;
  10870. soap->feltbegin = NULL;
  10871. soap->feltendin = NULL;
  10872. soap->feltbegout = NULL;
  10873. soap->feltendout = NULL;
  10874. soap->fprepareinitsend = NULL;
  10875. soap->fprepareinitrecv = NULL;
  10876. soap->fpreparesend = NULL;
  10877. soap->fpreparerecv = NULL;
  10878. soap->fpreparefinalsend = NULL;
  10879. soap->fpreparefinalrecv = NULL;
  10880. soap->ffiltersend = NULL;
  10881. soap->ffilterrecv = NULL;
  10882. soap->fdimereadopen = NULL;
  10883. soap->fdimewriteopen = NULL;
  10884. soap->fdimereadclose = NULL;
  10885. soap->fdimewriteclose = NULL;
  10886. soap->fdimeread = NULL;
  10887. soap->fdimewrite = NULL;
  10888. soap->fmimereadopen = NULL;
  10889. soap->fmimewriteopen = NULL;
  10890. soap->fmimereadclose = NULL;
  10891. soap->fmimewriteclose = NULL;
  10892. soap->fmimeread = NULL;
  10893. soap->fmimewrite = NULL;
  10894. #endif
  10895. soap->float_format = "%.9G"; /* Alternative: use "%G" */
  10896. soap->double_format = "%.17lG"; /* Alternative: use "%lG" */
  10897. soap->long_double_format = NULL; /* Defined in custom serializer custom/long_double.c */
  10898. soap->dime_id_format = "cid:id%d"; /* default DIME id format for int id index */
  10899. soap->recv_maxlength = 0x7FFFFFFF; /* default max length of messages received (2GB) */
  10900. soap->recv_timeout = 0;
  10901. soap->send_timeout = 0;
  10902. soap->transfer_timeout = 0;
  10903. soap->connect_timeout = 0;
  10904. soap->accept_timeout = 0;
  10905. soap->socket_flags = 0;
  10906. soap->connect_flags = 0;
  10907. soap->bind_flags = 0;
  10908. #ifdef WITH_IPV6_V6ONLY
  10909. soap->bind_inet6 = 1;
  10910. soap->bind_v6only = 1;
  10911. #else
  10912. soap->bind_inet6 = 0;
  10913. soap->bind_v6only = 0;
  10914. #endif
  10915. soap->accept_flags = 0;
  10916. #ifdef WIN32
  10917. soap->sndbuf = SOAP_BUFLEN + 1; /* this size speeds up windows xfer */
  10918. soap->rcvbuf = SOAP_BUFLEN + 1;
  10919. #else
  10920. soap->sndbuf = SOAP_BUFLEN;
  10921. soap->rcvbuf = SOAP_BUFLEN;
  10922. #endif
  10923. soap->linger_time = 0;
  10924. soap->maxlevel = SOAP_MAXLEVEL;
  10925. soap->maxlength = SOAP_MAXLENGTH;
  10926. soap->maxoccurs = SOAP_MAXOCCURS;
  10927. soap->http_version = "1.1";
  10928. soap->proxy_http_version = "1.0";
  10929. soap->http_content = NULL;
  10930. soap->http_extra_header = NULL;
  10931. soap->actor = NULL;
  10932. soap->lang = "en";
  10933. soap->keep_alive = 0;
  10934. soap->tcp_keep_alive = 0;
  10935. soap->tcp_keep_idle = 0;
  10936. soap->tcp_keep_intvl = 0;
  10937. soap->tcp_keep_cnt = 0;
  10938. soap->max_keep_alive = SOAP_MAXKEEPALIVE;
  10939. soap->ip = 0;
  10940. soap->ip6[0] = 0;
  10941. soap->ip6[1] = 0;
  10942. soap->ip6[2] = 0;
  10943. soap->ip6[3] = 0;
  10944. soap->labbuf = NULL;
  10945. soap->lablen = 0;
  10946. soap->labidx = 0;
  10947. soap->encodingStyle = NULL;
  10948. #ifndef WITH_NONAMESPACES
  10949. soap->namespaces = namespaces;
  10950. #else
  10951. soap->namespaces = NULL;
  10952. #endif
  10953. soap->local_namespaces = NULL;
  10954. soap->nlist = NULL;
  10955. soap->blist = NULL;
  10956. soap->clist = NULL;
  10957. soap->alist = NULL;
  10958. soap->shaky = 0;
  10959. soap->attributes = NULL;
  10960. soap->header = NULL;
  10961. soap->fault = NULL;
  10962. soap->master = SOAP_INVALID_SOCKET;
  10963. soap->socket = SOAP_INVALID_SOCKET;
  10964. soap->sendsk = SOAP_INVALID_SOCKET;
  10965. soap->recvsk = SOAP_INVALID_SOCKET;
  10966. soap->os = NULL;
  10967. soap->is = NULL;
  10968. #ifndef WITH_LEANER
  10969. soap->dom = NULL;
  10970. soap->dime.list = NULL;
  10971. soap->dime.first = NULL;
  10972. soap->dime.last = NULL;
  10973. soap->mime.list = NULL;
  10974. soap->mime.first = NULL;
  10975. soap->mime.last = NULL;
  10976. soap->mime.boundary = NULL;
  10977. soap->mime.start = NULL;
  10978. soap->xlist = NULL;
  10979. #endif
  10980. #ifndef UNDER_CE
  10981. soap->recvfd = 0;
  10982. soap->sendfd = 1;
  10983. #else
  10984. soap->recvfd = stdin;
  10985. soap->sendfd = stdout;
  10986. #endif
  10987. soap->tag[0] = '\0';
  10988. soap->id[0] = '\0';
  10989. soap->href[0] = '\0';
  10990. soap->type[0] = '\0';
  10991. soap->arrayType[0] = '\0';
  10992. soap->arraySize[0] = '\0';
  10993. soap->arrayOffset[0] = '\0';
  10994. soap->endpoint[0] = '\0';
  10995. soap->host[0] = '\0';
  10996. soap->path[0] = '\0';
  10997. soap->port = 0;
  10998. soap->override_host = NULL;
  10999. soap->override_port = 0;
  11000. soap->action = NULL;
  11001. soap->proxy_host = NULL;
  11002. soap->proxy_port = 8080;
  11003. soap->proxy_userid = NULL;
  11004. soap->proxy_passwd = NULL;
  11005. soap->proxy_from = NULL;
  11006. soap->origin = NULL;
  11007. soap->cors_origin = NULL;
  11008. soap->cors_allow = "*";
  11009. soap->cors_method = NULL;
  11010. soap->cors_header = NULL;
  11011. soap->cors_methods = NULL;
  11012. soap->cors_headers = NULL;
  11013. soap->x_frame_options = "SAMEORIGIN";
  11014. soap->prolog = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
  11015. soap->zlib_state = SOAP_ZLIB_NONE;
  11016. soap->zlib_in = SOAP_ZLIB_NONE;
  11017. soap->zlib_out = SOAP_ZLIB_NONE;
  11018. soap->d_stream = NULL;
  11019. soap->z_buf = NULL;
  11020. soap->z_level = 6;
  11021. soap->z_dict = NULL;
  11022. soap->z_dict_len = 0;
  11023. #ifndef WITH_LEAN
  11024. soap->wsuid = NULL;
  11025. soap->c14nexclude = NULL;
  11026. soap->c14ninclude = NULL;
  11027. soap->cookies = NULL;
  11028. soap->cookie_domain = NULL;
  11029. soap->cookie_path = NULL;
  11030. soap->cookie_max = 32;
  11031. #endif
  11032. #ifdef WMW_RPM_IO
  11033. soap->rpmreqid = NULL;
  11034. #endif
  11035. #ifndef WITH_NOIDREF
  11036. soap_init_iht(soap);
  11037. #endif
  11038. soap_init_pht(soap);
  11039. #ifdef WITH_OPENSSL
  11040. if (!soap_ssl_init_done)
  11041. soap_ssl_init();
  11042. soap->fsslauth = ssl_auth_init;
  11043. soap->fsslverify = NULL;
  11044. soap->bio = NULL;
  11045. soap->ssl = NULL;
  11046. soap->ctx = NULL;
  11047. soap->session = NULL;
  11048. soap->session_host[0] = '\0';
  11049. soap->session_port = 443;
  11050. soap->ssl_flags = SOAP_SSL_DEFAULT;
  11051. soap->keyfile = NULL;
  11052. soap->keyid = NULL;
  11053. soap->password = NULL;
  11054. soap->cafile = NULL;
  11055. soap->capath = NULL;
  11056. soap->crlfile = NULL;
  11057. soap->dhfile = NULL;
  11058. soap->randfile = NULL;
  11059. #endif
  11060. #ifdef WITH_GNUTLS
  11061. if (!soap_ssl_init_done)
  11062. soap_ssl_init();
  11063. soap->fsslauth = ssl_auth_init;
  11064. soap->fsslverify = NULL;
  11065. soap->xcred = NULL;
  11066. soap->acred = NULL;
  11067. soap->cache = NULL;
  11068. soap->session = NULL;
  11069. soap->ssl_flags = SOAP_SSL_DEFAULT;
  11070. soap->keyfile = NULL;
  11071. soap->keyid = NULL;
  11072. soap->password = NULL;
  11073. soap->cafile = NULL;
  11074. soap->capath = NULL;
  11075. soap->crlfile = NULL;
  11076. soap->dh_params = NULL;
  11077. soap->rsa_params = NULL;
  11078. #endif
  11079. #ifdef WITH_SYSTEMSSL
  11080. soap->fsslauth = ssl_auth_init;
  11081. soap->fsslverify = NULL;
  11082. soap->bio = NULL;
  11083. soap->ssl = (gsk_handle)NULL;
  11084. soap->ctx = (gsk_handle)NULL;
  11085. soap->session = NULL;
  11086. soap->ssl_flags = SOAP_SSL_DEFAULT;
  11087. soap->keyfile = NULL;
  11088. soap->keyid = NULL;
  11089. soap->password = NULL;
  11090. soap->cafile = NULL;
  11091. soap->capath = NULL;
  11092. soap->crlfile = NULL;
  11093. soap->dhfile = NULL;
  11094. soap->randfile = NULL;
  11095. #endif
  11096. soap->c_locale = NULL;
  11097. soap->buflen = 0;
  11098. soap->bufidx = 0;
  11099. #ifndef WITH_LEANER
  11100. soap->dime.chunksize = 0;
  11101. soap->dime.buflen = 0;
  11102. #endif
  11103. soap->other = 0;
  11104. soap->root = -1;
  11105. soap->null = 0;
  11106. soap->position = 0;
  11107. soap->encoding = 0;
  11108. soap->mustUnderstand = 0;
  11109. soap->ns = 0;
  11110. soap->part = SOAP_END;
  11111. soap->event = 0;
  11112. soap->evlev = 0;
  11113. soap->alloced = 0;
  11114. soap->count = 0;
  11115. soap->length = 0;
  11116. soap->cdata = 0;
  11117. soap->peeked = 0;
  11118. soap->ahead = 0;
  11119. soap->idnum = 0;
  11120. soap->level = 0;
  11121. soap->status = 0;
  11122. soap->error = SOAP_OK;
  11123. soap->errmode = 0;
  11124. soap->errnum = 0;
  11125. }
  11126. /******************************************************************************/
  11127. SOAP_FMAC1
  11128. void
  11129. SOAP_FMAC2
  11130. soap_begin(struct soap *soap) {
  11131. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Clean up for input/output\n"));
  11132. soap->error = SOAP_OK;
  11133. if (!soap->keep_alive) {
  11134. soap->buflen = 0;
  11135. soap->bufidx = 0;
  11136. }
  11137. soap->encoding = 0;
  11138. soap->mode = 0;
  11139. soap->part = SOAP_END;
  11140. soap->peeked = 0;
  11141. soap->ahead = 0;
  11142. soap->level = 0;
  11143. *soap->endpoint = '\0';
  11144. soap->encodingStyle = SOAP_STR_EOS;
  11145. soap_free_temp(soap);
  11146. }
  11147. /******************************************************************************/
  11148. SOAP_FMAC1
  11149. void
  11150. SOAP_FMAC2
  11151. soap_end(struct soap *soap) {
  11152. if (soap_check_state(soap))
  11153. return;
  11154. soap_free_temp(soap);
  11155. soap_dealloc(soap, NULL);
  11156. while (soap->clist) {
  11157. struct soap_clist *cp = soap->clist->next;
  11158. SOAP_FREE(soap, soap->clist);
  11159. soap->clist = cp;
  11160. }
  11161. soap_closesock(soap);
  11162. #ifdef SOAP_DEBUG
  11163. soap_close_logfiles(soap);
  11164. #endif
  11165. }
  11166. /******************************************************************************/
  11167. SOAP_FMAC1
  11168. void
  11169. SOAP_FMAC2
  11170. soap_set_version(struct soap *soap, short version) {
  11171. soap_set_local_namespaces(soap);
  11172. if (soap->version != version && soap->local_namespaces && soap->local_namespaces[0].id &&
  11173. soap->local_namespaces[1].id) {
  11174. if (version == 1) {
  11175. soap->local_namespaces[0].ns = soap_env1;
  11176. soap->local_namespaces[1].ns = soap_enc1;
  11177. } else if (version == 2) {
  11178. soap->local_namespaces[0].ns = soap_env2;
  11179. soap->local_namespaces[1].ns = soap_enc2;
  11180. }
  11181. soap->version = version;
  11182. }
  11183. if (version == 0)
  11184. soap->encodingStyle = SOAP_STR_EOS;
  11185. else
  11186. soap->encodingStyle = NULL;
  11187. }
  11188. /******************************************************************************/
  11189. static void
  11190. soap_version(struct soap *soap) {
  11191. struct Namespace *p = soap->local_namespaces;
  11192. if (p) {
  11193. const char *ns = p[0].out;
  11194. if (!ns)
  11195. ns = p[0].ns;
  11196. if (ns) {
  11197. if (!strcmp(ns, soap_env1)) {
  11198. soap->version = 1; /* make sure we use SOAP 1.1 */
  11199. if (p[1].out)
  11200. SOAP_FREE(soap, p[1].out);
  11201. p[1].out = (char *) SOAP_MALLOC(soap, sizeof(soap_enc1));
  11202. if (p[1].out)
  11203. (void) soap_memcpy(p[1].out, sizeof(soap_enc1), soap_enc1, sizeof(soap_enc1));
  11204. } else if (!strcmp(ns, soap_env2)) {
  11205. soap->version = 2; /* make sure we use SOAP 1.2 */
  11206. if (p[1].out)
  11207. SOAP_FREE(soap, p[1].out);
  11208. p[1].out = (char *) SOAP_MALLOC(soap, sizeof(soap_enc2));
  11209. if (p[1].out)
  11210. (void) soap_memcpy(p[1].out, sizeof(soap_enc2), soap_enc2, sizeof(soap_enc2));
  11211. }
  11212. }
  11213. }
  11214. }
  11215. /******************************************************************************/
  11216. SOAP_FMAC1
  11217. int
  11218. SOAP_FMAC2
  11219. soap_set_namespaces(struct soap *soap, const struct Namespace *p) {
  11220. struct Namespace *ns = soap->local_namespaces;
  11221. struct soap_nlist *np, *nq, *nr;
  11222. unsigned int level = soap->level;
  11223. soap->namespaces = p;
  11224. soap->local_namespaces = NULL;
  11225. soap_set_local_namespaces(soap);
  11226. /* reverse the namespace list */
  11227. np = soap->nlist;
  11228. soap->nlist = NULL;
  11229. if (np) {
  11230. nq = np->next;
  11231. np->next = NULL;
  11232. while (nq) {
  11233. nr = nq->next;
  11234. nq->next = np;
  11235. np = nq;
  11236. nq = nr;
  11237. }
  11238. }
  11239. /* then push on new stack */
  11240. while (np) {
  11241. const char *s;
  11242. soap->level = np->level; /* preserve element nesting level */
  11243. s = np->ns;
  11244. if (!s && np->index >= 0 && ns) {
  11245. s = ns[np->index].out;
  11246. if (!s)
  11247. s = ns[np->index].ns;
  11248. }
  11249. if (s)
  11250. (void) soap_push_namespace(soap, np->id, s);
  11251. nq = np;
  11252. np = np->next;
  11253. SOAP_FREE(soap, nq);
  11254. }
  11255. if (ns) {
  11256. int i;
  11257. for (i = 0; ns[i].id; i++) {
  11258. if (ns[i].out) {
  11259. SOAP_FREE(soap, ns[i].out);
  11260. ns[i].out = NULL;
  11261. }
  11262. }
  11263. SOAP_FREE(soap, ns);
  11264. }
  11265. soap->level = level; /* restore level */
  11266. return SOAP_OK;
  11267. }
  11268. /******************************************************************************/
  11269. SOAP_FMAC1
  11270. void
  11271. SOAP_FMAC2
  11272. soap_set_local_namespaces(struct soap *soap) {
  11273. if (soap->namespaces && !soap->local_namespaces) {
  11274. const struct Namespace *ns1;
  11275. struct Namespace *ns2;
  11276. size_t n = 1;
  11277. for (ns1 = soap->namespaces; ns1->id; ns1++)
  11278. n++;
  11279. n *= sizeof(struct Namespace);
  11280. ns2 = (struct Namespace *) SOAP_MALLOC(soap, n);
  11281. if (ns2) {
  11282. (void) soap_memcpy((void *) ns2, n, (const void *) soap->namespaces, n);
  11283. if (ns2[0].ns) {
  11284. if (!strcmp(ns2[0].ns, soap_env1))
  11285. soap->version = 1;
  11286. else if (!strcmp(ns2[0].ns, soap_env2))
  11287. soap->version = 2;
  11288. }
  11289. soap->local_namespaces = ns2;
  11290. for (; ns2->id; ns2++)
  11291. ns2->out = NULL;
  11292. }
  11293. }
  11294. }
  11295. /******************************************************************************/
  11296. #ifndef WITH_LEAN
  11297. SOAP_FMAC1
  11298. const char *
  11299. SOAP_FMAC2
  11300. soap_tagsearch(const char *big, const char *little) {
  11301. if (big && little) {
  11302. size_t n = strlen(little);
  11303. const char *s = big;
  11304. while (s) {
  11305. const char *t = s;
  11306. size_t i;
  11307. for (i = 0; i < n; i++, t++) {
  11308. if (*t != little[i])
  11309. break;
  11310. }
  11311. if (*t == '\0' || *t == ' ') {
  11312. if (i == n || (i > 0 && little[i - 1] == ':'))
  11313. return s;
  11314. }
  11315. s = strchr(t, ' ');
  11316. if (s)
  11317. s++;
  11318. }
  11319. }
  11320. return NULL;
  11321. }
  11322. #endif
  11323. /******************************************************************************/
  11324. SOAP_FMAC1
  11325. struct soap_nlist *
  11326. SOAP_FMAC2
  11327. soap_lookup_ns(struct soap *soap, const char *tag, size_t n) {
  11328. struct soap_nlist *np;
  11329. for (np = soap->nlist; np; np = np->next)
  11330. if (!strncmp(np->id, tag, n) && !np->id[n])
  11331. return np;
  11332. return NULL;
  11333. }
  11334. /******************************************************************************/
  11335. #ifndef WITH_LEAN
  11336. static struct soap_nlist *
  11337. soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized, short isearly) {
  11338. struct soap_nlist *np = NULL;
  11339. size_t n, k;
  11340. unsigned int level = soap->level + isearly;
  11341. if (soap_tagsearch(soap->c14nexclude, id))
  11342. return NULL;
  11343. if (!utilized) {
  11344. for (np = soap->nlist; np; np = np->next) {
  11345. if (!strcmp(np->id, id) && ((!np->ns && *id) || (np->ns && !strcmp(np->ns, ns))))
  11346. break;
  11347. }
  11348. if (np) {
  11349. if ((np->level < level || (!np->ns && *id)) && np->index == 1)
  11350. utilized = 1;
  11351. else
  11352. return NULL;
  11353. }
  11354. }
  11355. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", level, id,
  11356. ns ? ns : "(null)", utilized));
  11357. n = strlen(id);
  11358. if (ns)
  11359. k = strlen(ns) + 1;
  11360. else
  11361. k = 0;
  11362. if (sizeof(struct soap_nlist) + n + k > n &&
  11363. (SOAP_MAXALLOCSIZE <= 0 || sizeof(struct soap_nlist) + n + k <= SOAP_MAXALLOCSIZE))
  11364. np = (struct soap_nlist *) SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k);
  11365. if (!np) {
  11366. soap->error = SOAP_EOM;
  11367. return NULL;
  11368. }
  11369. np->next = soap->nlist;
  11370. soap->nlist = np;
  11371. soap_strcpy((char *) np->id, n + 1, id);
  11372. if (ns) {
  11373. np->ns = np->id + n + 1;
  11374. soap_strcpy((char *) np->ns, k, ns);
  11375. } else {
  11376. np->ns = NULL;
  11377. }
  11378. np->level = level;
  11379. np->index = utilized;
  11380. return np;
  11381. }
  11382. #endif
  11383. /******************************************************************************/
  11384. #ifndef WITH_LEAN
  11385. static void
  11386. soap_utilize_ns(struct soap *soap, const char *tag, short isearly) {
  11387. struct soap_nlist *np;
  11388. size_t n = 0;
  11389. if (!strncmp(tag, "xmlns:", 6)) {
  11390. tag += 6;
  11391. n = strlen(tag);
  11392. } else {
  11393. const char *t = strchr(tag, ':');
  11394. if (t)
  11395. n = t - tag;
  11396. }
  11397. np = soap_lookup_ns(soap, tag, n);
  11398. if (np) {
  11399. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing namespace of '%s' at level %u utilized=%d at level=%u\n", tag,
  11400. soap->level + isearly, np->index, np->level));
  11401. if (np->index <= 0) {
  11402. if (np->level == soap->level + isearly)
  11403. np->index = 1;
  11404. else
  11405. (void) soap_push_ns(soap, np->id, np->ns, 1, isearly);
  11406. }
  11407. } else if (strncmp(tag, "xml", 3)) {
  11408. DBGLOG(TEST,
  11409. SOAP_MESSAGE(fdebug, "Utilizing default namespace of '%s' at level %u\n", tag, soap->level + isearly));
  11410. (void) soap_strncpy(soap->tag, sizeof(soap->tag), tag, n);
  11411. (void) soap_push_ns(soap, soap->tag, NULL, 1, isearly);
  11412. }
  11413. }
  11414. #endif
  11415. /******************************************************************************/
  11416. SOAP_FMAC1
  11417. int
  11418. SOAP_FMAC2
  11419. soap_element(struct soap *soap, const char *tag, int id, const char *type) {
  11420. #ifndef WITH_LEAN
  11421. const char *s;
  11422. #endif
  11423. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' level='%u' id='%d' type='%s'\n", tag, soap->level, id,
  11424. type ? type : SOAP_STR_EOS));
  11425. #ifdef WITH_DOM
  11426. #ifndef WITH_LEAN
  11427. if (soap_tagsearch(soap->wsuid, tag))
  11428. {
  11429. size_t i;
  11430. for (s = tag, i = 0; *s && i < sizeof(soap->href) - 1; s++, i++)
  11431. soap->href[i] = *s == ':' ? '-' : *s;
  11432. soap->href[i] = '\0';
  11433. if (soap_set_attr(soap, "wsu:Id", soap->href, 1))
  11434. return soap->error;
  11435. }
  11436. #endif
  11437. #endif
  11438. soap->level++;
  11439. if (soap->level > soap->maxlevel)
  11440. return soap->error = SOAP_LEVEL;
  11441. #ifdef WITH_DOM
  11442. #ifndef WITH_LEAN
  11443. if ((soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_DOM_ASIS))
  11444. {
  11445. if (soap->evlev >= soap->level)
  11446. soap->evlev = 0;
  11447. if (soap->event == SOAP_SEC_BEGIN && !soap->evlev)
  11448. {
  11449. struct soap_nlist *np;
  11450. /* non-nested wsu:Id found: clear xmlns, re-emit them for exc-c14n */
  11451. for (np = soap->nlist; np; np = np->next)
  11452. {
  11453. int p = soap->c14ninclude ? *soap->c14ninclude == '+' || soap_tagsearch(soap->c14ninclude, np->id) != NULL : 0;
  11454. if (np->index == 2 || p)
  11455. {
  11456. struct soap_nlist *np1 = soap_push_ns(soap, np->id, np->ns, 1, 0);
  11457. if (np1 && !p)
  11458. np1->index = 0;
  11459. }
  11460. }
  11461. soap->evlev = soap->level;
  11462. }
  11463. }
  11464. #endif
  11465. if ((soap->mode & SOAP_XML_DOM))
  11466. {
  11467. struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
  11468. if (!elt)
  11469. return soap->error = SOAP_EOM;
  11470. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding DOM element tag='%s' %p (parent='%s' %p)\n", tag, elt, soap->dom ? soap->dom->name : "(null)", soap->dom));
  11471. elt->soap = soap;
  11472. elt->next = NULL;
  11473. elt->prnt = soap->dom;
  11474. elt->elts = NULL;
  11475. elt->atts = NULL;
  11476. elt->nstr = NULL;
  11477. elt->name = soap_strdup(soap, tag);
  11478. elt->lead = NULL;
  11479. elt->text = NULL;
  11480. elt->code = NULL;
  11481. elt->tail = NULL;
  11482. elt->node = NULL;
  11483. elt->type = 0;
  11484. if (soap->dom)
  11485. {
  11486. struct soap_dom_element *p = soap->dom->elts;
  11487. if (p)
  11488. {
  11489. while (p->next)
  11490. p = p->next;
  11491. p->next = elt;
  11492. }
  11493. else
  11494. {
  11495. soap->dom->elts = elt;
  11496. }
  11497. }
  11498. soap->dom = elt;
  11499. if (!elt->name)
  11500. return soap->error = SOAP_EOM;
  11501. }
  11502. else
  11503. {
  11504. #endif
  11505. #ifndef WITH_LEAN
  11506. if (!soap->ns) {
  11507. if (!(soap->mode & SOAP_XML_CANONICAL) && soap_send(soap, soap->prolog))
  11508. return soap->error;
  11509. } else if ((soap->mode & SOAP_XML_INDENT)) {
  11510. if (soap->ns == 1 &&
  11511. soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
  11512. return soap->error;
  11513. soap->body = 1;
  11514. }
  11515. if ((soap->mode & SOAP_XML_DEFAULTNS)) {
  11516. size_t n = 0;
  11517. s = strchr(tag, ':');
  11518. if (s)
  11519. n = s++ - tag;
  11520. else
  11521. s = tag;
  11522. if (soap_send_raw(soap, "<", 1)
  11523. || soap_send(soap, s))
  11524. return soap->error;
  11525. if (n) {
  11526. struct Namespace *ns = soap->local_namespaces;
  11527. for (; ns && ns->id; ns++) {
  11528. if (*ns->id && ns->ns && !strncmp(ns->id, tag, n) && !ns->id[n]) {
  11529. if (!soap->nlist || *soap->nlist->id || (soap->nlist->ns && strcmp(soap->nlist->ns, ns->ns))) {
  11530. (void) soap_push_ns(soap, SOAP_STR_EOS, ns->out ? ns->out : ns->ns, 0, 0);
  11531. if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns))
  11532. return soap->error;
  11533. }
  11534. break;
  11535. }
  11536. }
  11537. }
  11538. #ifndef WITH_NOEMPTYNAMESPACES
  11539. else if (!soap->nlist || *soap->nlist->id || (soap->nlist->ns && *soap->nlist->ns)) {
  11540. (void) soap_push_ns(soap, SOAP_STR_EOS, SOAP_STR_EOS, 0, 0);
  11541. if (soap_attribute(soap, "xmlns", SOAP_STR_EOS))
  11542. return soap->error;
  11543. }
  11544. #endif
  11545. } else
  11546. #endif
  11547. if (soap_send_raw(soap, "<", 1)
  11548. || soap_send(soap, tag))
  11549. return soap->error;
  11550. #ifdef WITH_DOM
  11551. }
  11552. #endif
  11553. if (!soap->ns) {
  11554. struct Namespace *ns = soap->local_namespaces;
  11555. int k = -1;
  11556. if (ns) {
  11557. while (k-- && ns->id) {
  11558. const char *t = ns->out;
  11559. if (!t)
  11560. t = ns->ns;
  11561. if (*ns->id && t && *t) {
  11562. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(ns->id) + 6), "xmlns:%s", ns->id);
  11563. if (soap_attribute(soap, soap->tmpbuf, t))
  11564. return soap->error;
  11565. }
  11566. ns++;
  11567. }
  11568. }
  11569. }
  11570. soap->ns = 1; /* namespace table control: ns = 0 or 2 to start, then 1 to stop dumping the table */
  11571. #ifndef WITH_LEAN
  11572. if ((soap->mode & SOAP_XML_CANONICAL)) {
  11573. if ((soap->mode & SOAP_XML_DEFAULTNS))
  11574. soap_utilize_ns(soap, SOAP_STR_EOS, 0);
  11575. else
  11576. soap_utilize_ns(soap, tag, 0);
  11577. }
  11578. #endif
  11579. if (id > 0) {
  11580. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), sizeof(SOAP_BASEREFNAME) + 20), SOAP_BASEREFNAME "%d", id);
  11581. if (soap->version == 2) {
  11582. if (soap_attribute(soap, "SOAP-ENC:id", soap->tmpbuf))
  11583. return soap->error;
  11584. } else if (soap_attribute(soap, "id", soap->tmpbuf)) {
  11585. return soap->error;
  11586. }
  11587. }
  11588. if (type && *type && !(soap->mode & SOAP_XML_NOTYPE)) {
  11589. #ifndef WITH_LEAN
  11590. if ((soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_XML_CANONICAL_NA))
  11591. soap_utilize_ns(soap, type, 0);
  11592. #endif
  11593. if (soap_attribute(soap, "xsi:type", type))
  11594. return soap->error;
  11595. }
  11596. if (soap->null && soap->position > 0 && soap->version == 1) {
  11597. int i;
  11598. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf) - 1, 20), "[%d", soap->positions[0]);
  11599. for (i = 1; i < soap->position; i++) {
  11600. size_t l = strlen(soap->tmpbuf);
  11601. (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l - 1, 20), ",%d", soap->positions[i]);
  11602. }
  11603. soap_strcat(soap->tmpbuf, sizeof(soap->tmpbuf), "]");
  11604. if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf))
  11605. return soap->error;
  11606. }
  11607. if (soap->mustUnderstand) {
  11608. if (soap->actor && *soap->actor) {
  11609. if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor))
  11610. return soap->error;
  11611. }
  11612. if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1"))
  11613. return soap->error;
  11614. soap->mustUnderstand = 0;
  11615. }
  11616. if (soap->encoding) {
  11617. if (soap->encodingStyle && soap->local_namespaces && soap->local_namespaces[0].id &&
  11618. soap->local_namespaces[1].id) {
  11619. if (!*soap->encodingStyle) {
  11620. if (soap->local_namespaces[1].out)
  11621. soap->encodingStyle = soap->local_namespaces[1].out;
  11622. else
  11623. soap->encodingStyle = soap->local_namespaces[1].ns;
  11624. }
  11625. if (soap->encodingStyle && soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle))
  11626. return soap->error;
  11627. } else {
  11628. soap->encodingStyle = NULL;
  11629. }
  11630. soap->encoding = 0;
  11631. }
  11632. soap->null = 0;
  11633. soap->position = 0;
  11634. return SOAP_OK;
  11635. }
  11636. /******************************************************************************/
  11637. SOAP_FMAC1
  11638. int
  11639. SOAP_FMAC2
  11640. soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type) {
  11641. if (*tag == '-')
  11642. return SOAP_OK;
  11643. #ifdef WITH_DOM
  11644. if (soap->feltbegout)
  11645. return soap->error = soap->feltbegout(soap, tag, id, type);
  11646. #endif
  11647. if (soap_element(soap, tag, id, type))
  11648. return soap->error;
  11649. return soap_element_start_end_out(soap, NULL);
  11650. }
  11651. /******************************************************************************/
  11652. #if _MSC_VER < 1400 && !defined(HAVE_STRLCAT)
  11653. /* concat string (truncating the result, strings must not be NULL) */
  11654. SOAP_FMAC1
  11655. void
  11656. SOAP_FMAC2
  11657. soap_strcat(char *t, size_t n, const char *s) {
  11658. size_t k = strlen(t);
  11659. if (k < n) {
  11660. t += k;
  11661. n -= k;
  11662. while (--n > 0 && *s)
  11663. *t++ = *s++;
  11664. *t = '\0';
  11665. }
  11666. }
  11667. #endif
  11668. /******************************************************************************/
  11669. #if _MSC_VER < 1400
  11670. /* concat string up to m chars (leaves destination intact on overrun and returns nonzero, zero if OK) */
  11671. SOAP_FMAC1
  11672. int
  11673. SOAP_FMAC2
  11674. soap_strncat(char *t, size_t n, const char *s, size_t m) {
  11675. size_t k;
  11676. if (!t || !s)
  11677. return 1;
  11678. k = strlen(t);
  11679. if (n <= k + m)
  11680. return 1;
  11681. t += k;
  11682. n -= k;
  11683. while (--n > 0 && *s)
  11684. *t++ = *s++;
  11685. *t = '\0';
  11686. return 0;
  11687. }
  11688. #endif
  11689. /******************************************************************************/
  11690. #ifndef HAVE_STRRCHR
  11691. SOAP_FMAC1
  11692. char*
  11693. SOAP_FMAC2
  11694. soap_strrchr(const char *s, int t)
  11695. {
  11696. char *r = NULL;
  11697. while (*s)
  11698. if (*s++ == t)
  11699. r = (char*)s - 1;
  11700. return r;
  11701. }
  11702. #endif
  11703. /******************************************************************************/
  11704. #ifndef HAVE_STRTOL
  11705. SOAP_FMAC1
  11706. long
  11707. SOAP_FMAC2
  11708. soap_strtol(const char *s, char **t, int b)
  11709. {
  11710. long n = 0;
  11711. int c;
  11712. while (*s > 0 && *s <= 32)
  11713. s++;
  11714. if (b == 10)
  11715. {
  11716. short neg = 0;
  11717. if (*s == '-')
  11718. {
  11719. s++;
  11720. neg = 1;
  11721. }
  11722. else if (*s == '+')
  11723. {
  11724. s++;
  11725. }
  11726. while ((c = *s) && c >= '0' && c <= '9')
  11727. {
  11728. if (n >= 214748364 && (n > 214748364 || c >= '8'))
  11729. {
  11730. if (neg && n == 214748364 && c == '8')
  11731. {
  11732. if (t)
  11733. *t = (char*)(s + 1);
  11734. return -2147483648;
  11735. }
  11736. break;
  11737. }
  11738. n *= 10;
  11739. n += c - '0';
  11740. s++;
  11741. }
  11742. if (neg)
  11743. n = -n;
  11744. }
  11745. else /* assume b == 16 and value is always positive */
  11746. {
  11747. while ((c = *s))
  11748. {
  11749. if (c >= '0' && c <= '9')
  11750. c -= '0';
  11751. else if (c >= 'A' && c <= 'F')
  11752. c -= 'A' - 10;
  11753. else if (c >= 'a' && c <= 'f')
  11754. c -= 'a' - 10;
  11755. if (n > 0x07FFFFFF)
  11756. break;
  11757. n <<= 4;
  11758. n += c;
  11759. s++;
  11760. }
  11761. }
  11762. if (t)
  11763. *t = (char*)s;
  11764. return n;
  11765. }
  11766. #endif
  11767. /******************************************************************************/
  11768. #ifndef HAVE_STRTOUL
  11769. SOAP_FMAC1
  11770. unsigned long
  11771. SOAP_FMAC2
  11772. soap_strtoul(const char *s, char **t, int b)
  11773. {
  11774. unsigned long n = 0;
  11775. int c;
  11776. while (*s > 0 && *s <= 32)
  11777. s++;
  11778. if (b == 10)
  11779. {
  11780. short neg = 0;
  11781. if (*s == '-')
  11782. {
  11783. s++;
  11784. neg = 1;
  11785. }
  11786. else if (*s == '+')
  11787. {
  11788. s++;
  11789. }
  11790. while ((c = *s) && c >= '0' && c <= '9')
  11791. {
  11792. if (n >= 429496729 && (n > 429496729 || c >= '6'))
  11793. break;
  11794. n *= 10;
  11795. n += c - '0';
  11796. s++;
  11797. }
  11798. if (neg && n > 0)
  11799. s--;
  11800. }
  11801. else /* b == 16 */
  11802. {
  11803. while ((c = *s))
  11804. {
  11805. if (c >= '0' && c <= '9')
  11806. c -= '0';
  11807. else if (c >= 'A' && c <= 'F')
  11808. c -= 'A' - 10;
  11809. else if (c >= 'a' && c <= 'f')
  11810. c -= 'a' - 10;
  11811. if (n > 0x0FFFFFFF)
  11812. break;
  11813. n <<= 4;
  11814. n += c;
  11815. s++;
  11816. }
  11817. }
  11818. if (t)
  11819. *t = (char*)s;
  11820. return n;
  11821. }
  11822. #endif
  11823. /******************************************************************************/
  11824. #ifndef soap_strtoll
  11825. SOAP_FMAC1
  11826. LONG64
  11827. SOAP_FMAC2
  11828. soap_strtoll(const char *s, char **t, int b)
  11829. {
  11830. LONG64 n = 0LL;
  11831. int c;
  11832. while (*s > 0 && *s <= 32)
  11833. s++;
  11834. if (b == 10)
  11835. {
  11836. short neg = 0;
  11837. if (*s == '-')
  11838. {
  11839. s++;
  11840. neg = 1;
  11841. }
  11842. else if (*s == '+')
  11843. {
  11844. s++;
  11845. }
  11846. while ((c = *s) && c >= '0' && c <= '9')
  11847. {
  11848. if (n >= 922337203685477580LL && (n > 922337203685477580LL || c >= '8'))
  11849. {
  11850. if (neg && n == 922337203685477580LL && c == '8')
  11851. {
  11852. if (t)
  11853. *t = (char*)(s + 1);
  11854. return -9223372036854775807LL - 1LL; /* appease compilers that complain */
  11855. }
  11856. break;
  11857. }
  11858. n *= 10LL;
  11859. n += c - '0';
  11860. s++;
  11861. }
  11862. if (neg)
  11863. n = -n;
  11864. }
  11865. else /* assume b == 16 and value is always positive */
  11866. {
  11867. while ((c = *s))
  11868. {
  11869. if (c >= '0' && c <= '9')
  11870. c -= '0';
  11871. else if (c >= 'A' && c <= 'F')
  11872. c -= 'A' - 10;
  11873. else if (c >= 'a' && c <= 'f')
  11874. c -= 'a' - 10;
  11875. if (n > 0x07FFFFFFFFFFFFFFLL)
  11876. break;
  11877. n <<= 4;
  11878. n += c;
  11879. s++;
  11880. }
  11881. }
  11882. if (t)
  11883. *t = (char*)s;
  11884. return n;
  11885. }
  11886. #endif
  11887. /******************************************************************************/
  11888. #ifndef soap_strtoull
  11889. SOAP_FMAC1
  11890. ULONG64
  11891. SOAP_FMAC2
  11892. soap_strtoull(const char *s, char **t, int b)
  11893. {
  11894. ULONG64 n = 0UL;
  11895. int c;
  11896. while (*s > 0 && *s <= 32)
  11897. s++;
  11898. if (b == 10)
  11899. {
  11900. short neg = 0;
  11901. if (*s == '-')
  11902. {
  11903. s++;
  11904. neg = 1;
  11905. }
  11906. else if (*s == '+')
  11907. {
  11908. s++;
  11909. }
  11910. while ((c = *s) && c >= '0' && c <= '9')
  11911. {
  11912. if (n >= 1844674407370955161ULL)
  11913. break;
  11914. n *= 10UL;
  11915. n += c - '0';
  11916. s++;
  11917. }
  11918. if (neg && n > 0UL)
  11919. s--;
  11920. }
  11921. else /* b == 16 */
  11922. {
  11923. while ((c = *s))
  11924. {
  11925. if (c >= '0' && c <= '9')
  11926. c -= '0';
  11927. else if (c >= 'A' && c <= 'F')
  11928. c -= 'A' - 10;
  11929. else if (c >= 'a' && c <= 'f')
  11930. c -= 'a' - 10;
  11931. if (n > 0x0FFFFFFFFFFFFFFFULL)
  11932. break;
  11933. n <<= 4;
  11934. n += c;
  11935. s++;
  11936. }
  11937. }
  11938. if (t)
  11939. *t = (char*)s;
  11940. return n;
  11941. }
  11942. #endif
  11943. /******************************************************************************/
  11944. SOAP_FMAC1
  11945. int
  11946. SOAP_FMAC2
  11947. soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset) {
  11948. if (!type || !*type || soap->version == 0)
  11949. return soap_element_begin_out(soap, tag, id, NULL);
  11950. if (soap_element(soap, tag, id, NULL))
  11951. return soap->error;
  11952. if (soap->version == 1) {
  11953. if (offset && soap_attribute(soap, "SOAP-ENC:offset", offset))
  11954. return soap->error;
  11955. if (soap_attribute(soap, "SOAP-ENC:arrayType", type))
  11956. return soap->error;
  11957. } else {
  11958. const char *s;
  11959. s = strchr(type, '[');
  11960. if (s && (size_t) (s - type) < sizeof(soap->tmpbuf)) {
  11961. (void) soap_strncpy(soap->tmpbuf, sizeof(soap->tmpbuf), type, s - type);
  11962. if (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))
  11963. return soap->error;
  11964. s++;
  11965. if (*s && *s != ']') {
  11966. soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), s);
  11967. soap->tmpbuf[strlen(soap->tmpbuf) - 1] = '\0';
  11968. if (soap_attribute(soap, "SOAP-ENC:arraySize", soap->tmpbuf))
  11969. return soap->error;
  11970. }
  11971. }
  11972. }
  11973. #ifndef WITH_LEAN
  11974. if ((soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_XML_CANONICAL_NA))
  11975. soap_utilize_ns(soap, type, 0);
  11976. #endif
  11977. return soap_element_start_end_out(soap, NULL);
  11978. }
  11979. /******************************************************************************/
  11980. SOAP_FMAC1
  11981. int
  11982. SOAP_FMAC2
  11983. soap_element_start_end_out(struct soap *soap, const char *tag) {
  11984. struct soap_attribute *tp;
  11985. #ifndef WITH_LEAN
  11986. if ((soap->mode & SOAP_XML_CANONICAL)) {
  11987. struct soap_nlist *np;
  11988. for (tp = soap->attributes; tp; tp = tp->next) {
  11989. if (tp->visible && *tp->name && strchr(tp->name, ':'))
  11990. soap_utilize_ns(soap, tp->name, 0);
  11991. }
  11992. if (soap->event == SOAP_SEC_BEGIN) {
  11993. for (np = soap->nlist; np; np = np->next)
  11994. if (soap_tagsearch(soap->c14ninclude, np->id))
  11995. (void) soap_push_ns(soap, np->id, np->ns, 1, 0);
  11996. soap->event = 0;
  11997. soap->evlev = 0;
  11998. }
  11999. for (np = soap->nlist; np; np = np->next) {
  12000. if (np->ns && np->index == 1) {
  12001. if (*np->id)
  12002. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(np->id) + 6), "xmlns:%s", np->id);
  12003. else
  12004. soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns");
  12005. DBGLOG(TEST, SOAP_MESSAGE(fdebug,
  12006. "Enabling utilized binding (level=%u) %s='%s' SEC-BEGIN=%d c14ninclude='%s'\n",
  12007. np->level, soap->tmpbuf, np->ns, soap->event == SOAP_SEC_BEGIN,
  12008. soap->c14ninclude ? soap->c14ninclude : "(null)"));
  12009. np->index = 2;
  12010. soap->level--;
  12011. if (*np->id || *np->ns || soap->level > 1)
  12012. if (soap_set_attr(soap, soap->tmpbuf, np->ns, 1))
  12013. return soap->error;
  12014. soap->level++;
  12015. } else {
  12016. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Binding (level=%u) %s='%s' utilized=%d\n", np->level, np->id, np->ns,
  12017. np->index));
  12018. }
  12019. }
  12020. }
  12021. #endif
  12022. #ifdef WITH_DOM
  12023. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  12024. {
  12025. struct soap_dom_attribute **att;
  12026. att = &soap->dom->atts;
  12027. for (tp = soap->attributes; tp; tp = tp->next)
  12028. {
  12029. if (tp->visible)
  12030. {
  12031. *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
  12032. if (!*att)
  12033. return soap->error;
  12034. (*att)->next = NULL;
  12035. (*att)->nstr = NULL;
  12036. (*att)->name = soap_strdup(soap, tp->name);
  12037. (*att)->text = soap_strdup(soap, tp->value);
  12038. (*att)->soap = soap;
  12039. if (!(*att)->name || (tp->value && !(*att)->text))
  12040. return soap->error = SOAP_EOM;
  12041. att = &(*att)->next;
  12042. tp->visible = 0;
  12043. }
  12044. }
  12045. return SOAP_OK;
  12046. }
  12047. #endif
  12048. for (tp = soap->attributes; tp; tp = tp->next) {
  12049. if (tp->visible) {
  12050. if (soap_send_raw(soap, " ", 1) || soap_send(soap, tp->name))
  12051. return soap->error;
  12052. if (tp->visible == 2 && tp->value) {
  12053. if (soap_send_raw(soap, "=\"", 2)
  12054. || soap_string_out(soap, tp->value, tp->flag)
  12055. || soap_send_raw(soap, "\"", 1))
  12056. return soap->error;
  12057. } else {
  12058. if (soap_send_raw(soap, "=\"\"", 3))
  12059. return soap->error;
  12060. }
  12061. tp->visible = 0;
  12062. }
  12063. }
  12064. if (tag) {
  12065. #ifndef WITH_LEAN
  12066. if ((soap->mode & SOAP_XML_CANONICAL)) {
  12067. if (soap_send_raw(soap, ">", 1)
  12068. || soap_element_end_out(soap, tag))
  12069. return soap->error;
  12070. return SOAP_OK;
  12071. }
  12072. #endif
  12073. if (soap->nlist)
  12074. soap_pop_namespace(soap);
  12075. soap->level--; /* decrement level just before /> */
  12076. soap->body = 0;
  12077. return soap_send_raw(soap, "/>", 2);
  12078. }
  12079. return soap_send_raw(soap, ">", 1);
  12080. }
  12081. /******************************************************************************/
  12082. SOAP_FMAC1
  12083. int
  12084. SOAP_FMAC2
  12085. soap_element_end_out(struct soap *soap, const char *tag) {
  12086. if (*tag == '-')
  12087. return SOAP_OK;
  12088. #ifdef WITH_DOM
  12089. if (soap->feltendout)
  12090. return soap->error = soap->feltendout(soap, tag);
  12091. #endif
  12092. return soap_element_end(soap, tag);
  12093. }
  12094. /******************************************************************************/
  12095. SOAP_FMAC1
  12096. int
  12097. SOAP_FMAC2
  12098. soap_element_end(struct soap *soap, const char *tag) {
  12099. #ifndef WITH_LEAN
  12100. const char *s;
  12101. #endif
  12102. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag));
  12103. #ifdef WITH_DOM
  12104. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  12105. {
  12106. if (soap->dom->prnt)
  12107. soap->dom = soap->dom->prnt;
  12108. return SOAP_OK;
  12109. }
  12110. #endif
  12111. #ifndef WITH_LEAN
  12112. if (soap->nlist)
  12113. soap_pop_namespace(soap);
  12114. if ((soap->mode & SOAP_XML_INDENT)) {
  12115. if (!soap->body) {
  12116. if (soap_send_raw(soap, soap_indent,
  12117. soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
  12118. return soap->error;
  12119. }
  12120. soap->body = 0;
  12121. }
  12122. if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':')) != NULL)
  12123. tag = s + 1;
  12124. #endif
  12125. if (soap_send_raw(soap, "</", 2)
  12126. || soap_send(soap, tag))
  12127. return soap->error;
  12128. soap->level--; /* decrement level just before > */
  12129. return soap_send_raw(soap, ">", 1);
  12130. }
  12131. /******************************************************************************/
  12132. SOAP_FMAC1
  12133. int
  12134. SOAP_FMAC2
  12135. soap_element_ref(struct soap *soap, const char *tag, int id, int href) {
  12136. const char *s = "ref";
  12137. int n = 1;
  12138. if (soap->version == 1) {
  12139. s = "href";
  12140. n = 0;
  12141. } else if (soap->version == 2) {
  12142. s = "SOAP-ENC:ref";
  12143. }
  12144. (SOAP_SNPRINTF(soap->href, sizeof(soap->href), sizeof(SOAP_BASEREFNAME) + 21), "#" SOAP_BASEREFNAME "%d", href);
  12145. return soap_element_href(soap, tag, id, s, soap->href + n);
  12146. }
  12147. /******************************************************************************/
  12148. SOAP_FMAC1
  12149. int
  12150. SOAP_FMAC2
  12151. soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val) {
  12152. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val));
  12153. if (soap_element(soap, tag, id, NULL)
  12154. || soap_attribute(soap, ref, val)
  12155. || soap_element_start_end_out(soap, tag))
  12156. return soap->error;
  12157. soap->body = 0;
  12158. return SOAP_OK;
  12159. }
  12160. /******************************************************************************/
  12161. SOAP_FMAC1
  12162. int
  12163. SOAP_FMAC2
  12164. soap_element_null(struct soap *soap, const char *tag, int id, const char *type) {
  12165. struct soap_attribute *tp = NULL;
  12166. for (tp = soap->attributes; tp; tp = tp->next)
  12167. if (tp->visible)
  12168. break;
  12169. if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL)) {
  12170. if (soap_element(soap, tag, id, type)
  12171. || (!tp && soap_attribute(soap, "xsi:nil", "true"))
  12172. || soap_element_start_end_out(soap, tag))
  12173. return soap->error;
  12174. soap->body = 0;
  12175. } else {
  12176. soap->null = 1;
  12177. soap->position = 0;
  12178. soap->mustUnderstand = 0;
  12179. }
  12180. return SOAP_OK;
  12181. }
  12182. /******************************************************************************/
  12183. SOAP_FMAC1
  12184. int
  12185. SOAP_FMAC2
  12186. soap_element_empty(struct soap *soap, const char *tag) {
  12187. if (soap_element(soap, tag, -1, NULL))
  12188. return soap->error;
  12189. return soap_element_start_end_out(soap, tag);
  12190. }
  12191. /******************************************************************************/
  12192. SOAP_FMAC1
  12193. int
  12194. SOAP_FMAC2
  12195. soap_element_nil(struct soap *soap, const char *tag) {
  12196. if (soap_element(soap, tag, -1, NULL)
  12197. || (soap_attribute(soap, "xsi:nil", "true")))
  12198. return soap->error;
  12199. return soap_element_start_end_out(soap, tag);
  12200. }
  12201. /******************************************************************************/
  12202. SOAP_FMAC1
  12203. int
  12204. SOAP_FMAC2
  12205. soap_element_id(struct soap *soap, const char *tag, int id, const void *p, const void *a, int n, const char *type,
  12206. int t, char **mark) {
  12207. (void) a;
  12208. (void) n;
  12209. if (!p) {
  12210. soap->error = soap_element_null(soap, tag, id, type);
  12211. return -1;
  12212. }
  12213. #ifndef WITH_NOIDREF
  12214. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element_id %p type=%d id=%d\n", p, t, id));
  12215. if ((!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) || (soap->mode & SOAP_XML_TREE))
  12216. return soap_check_and_mark(soap, p, t, mark);
  12217. if (mark)
  12218. *mark = NULL;
  12219. if (id < -1)
  12220. return soap_embed(soap, p, a, n, t);
  12221. else if (id <= 0) {
  12222. struct soap_plist *pp;
  12223. if (a)
  12224. id = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
  12225. else
  12226. id = soap_pointer_lookup(soap, p, t, &pp);
  12227. if (id) {
  12228. if (soap_is_embedded(soap, pp)) {
  12229. soap_element_ref(soap, tag, 0, id);
  12230. return -1;
  12231. }
  12232. if (soap_is_single(soap, pp))
  12233. return 0;
  12234. soap_set_embedded(soap, pp);
  12235. }
  12236. }
  12237. return id;
  12238. #else
  12239. return soap_check_and_mark(soap, p, t, mark);
  12240. #endif
  12241. }
  12242. /******************************************************************************/
  12243. SOAP_FMAC1
  12244. int
  12245. SOAP_FMAC2
  12246. soap_check_and_mark(struct soap *soap, const void *p, int t, char **mark) {
  12247. if (mark) {
  12248. struct soap_plist *pp;
  12249. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Check %p and mark %p\n", p, (void *) mark));
  12250. if (!soap_pointer_lookup(soap, p, t, &pp))
  12251. if (!soap_pointer_enter(soap, p, NULL, 0, t, &pp))
  12252. return -1;
  12253. if ((soap->mode & SOAP_IO_LENGTH)) {
  12254. if (pp->mark1 > 0)
  12255. return -1;
  12256. pp->mark1 = 1;
  12257. *mark = &pp->mark1;
  12258. } else {
  12259. if (pp->mark2 > 0)
  12260. return -1;
  12261. pp->mark2 = 1;
  12262. *mark = &pp->mark2;
  12263. }
  12264. }
  12265. return 0;
  12266. }
  12267. /******************************************************************************/
  12268. SOAP_FMAC1
  12269. void *
  12270. SOAP_FMAC2
  12271. soap_mark_lookup(struct soap *soap, const void *p, int t, struct soap_plist **ppp, char **mark) {
  12272. if (!soap)
  12273. return NULL;
  12274. if (mark || !(soap->mode & SOAP_XML_TREE)) {
  12275. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Mark lookup %p type=%d\n", p, t));
  12276. if (!soap_pointer_lookup(soap, p, t, ppp)) {
  12277. if (!soap_pointer_enter(soap, p, NULL, 0, t, ppp))
  12278. return NULL;
  12279. } else if (!(soap->mode & SOAP_XML_TREE)) {
  12280. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Mark found %p\n", (*ppp)->dup));
  12281. return (*ppp)->dup;
  12282. }
  12283. if (mark) {
  12284. if ((*ppp)->mark1 > 0)
  12285. (*ppp)->mark1 = 2; /* cycle */
  12286. else
  12287. (*ppp)->mark1 = 1; /* cycle detection */
  12288. *mark = &(*ppp)->mark1;
  12289. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Mark cycle %d\n", (*ppp)->mark1));
  12290. }
  12291. }
  12292. return NULL;
  12293. }
  12294. /******************************************************************************/
  12295. SOAP_FMAC1
  12296. int
  12297. SOAP_FMAC2
  12298. soap_mark_cycle(struct soap *soap, struct soap_plist *pp) {
  12299. (void) soap;
  12300. return pp && pp->mark1 == 2 && (soap->mode & SOAP_XML_TREE);
  12301. }
  12302. /******************************************************************************/
  12303. SOAP_FMAC1
  12304. void
  12305. SOAP_FMAC2
  12306. soap_mark_dup(struct soap *soap, void *a, struct soap_plist *pp) {
  12307. (void) soap;
  12308. if (pp)
  12309. pp->dup = a;
  12310. }
  12311. /******************************************************************************/
  12312. SOAP_FMAC1
  12313. void
  12314. SOAP_FMAC2
  12315. soap_unmark(struct soap *soap, char *mark) {
  12316. (void) soap;
  12317. if (mark)
  12318. *mark = 0; /* release detection */
  12319. }
  12320. /******************************************************************************/
  12321. SOAP_FMAC1
  12322. int
  12323. SOAP_FMAC2
  12324. soap_element_result(struct soap *soap, const char *tag) {
  12325. if (soap->version == 2 && soap->encodingStyle) {
  12326. if (soap_element(soap, "SOAP-RPC:result", 0, NULL)
  12327. || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc)
  12328. || soap_element_start_end_out(soap, NULL)
  12329. || soap_string_out(soap, tag, 0)
  12330. || soap_element_end_out(soap, "SOAP-RPC:result"))
  12331. return soap->error;
  12332. }
  12333. return SOAP_OK;
  12334. }
  12335. /******************************************************************************/
  12336. SOAP_FMAC1
  12337. void
  12338. SOAP_FMAC2
  12339. soap_check_result(struct soap *soap, const char *tag) {
  12340. (void) tag;
  12341. if (soap->version == 2 && soap->encodingStyle) {
  12342. soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1, NULL);
  12343. /* just ignore content for compliance reasons, but should compare tag to element's QName value? */
  12344. }
  12345. }
  12346. /******************************************************************************/
  12347. SOAP_FMAC1
  12348. int
  12349. SOAP_FMAC2
  12350. soap_attribute(struct soap *soap, const char *name, const char *value) {
  12351. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attribute '%s'='%s'\n", name, value));
  12352. #ifdef WITH_DOM
  12353. if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom)
  12354. {
  12355. struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
  12356. if (!a)
  12357. return soap->error;
  12358. a->next = soap->dom->atts;
  12359. a->nstr = NULL;
  12360. a->name = soap_strdup(soap, name);
  12361. a->text = soap_strdup(soap, value);
  12362. a->soap = soap;
  12363. soap->dom->atts = a;
  12364. if (!a->name || (value && !a->text))
  12365. return soap->error = SOAP_EOM;
  12366. return SOAP_OK;
  12367. }
  12368. #endif
  12369. #ifndef WITH_LEAN
  12370. if ((soap->mode & SOAP_XML_CANONICAL)) {
  12371. /* push namespace */
  12372. if (!strncmp(name, "xmlns", 5) && ((name[5] == ':') || name[5] == '\0')) {
  12373. if (name[5] == ':' && soap->c14ninclude &&
  12374. ((*soap->c14ninclude == '*' || soap_tagsearch(soap->c14ninclude, name + 6))))
  12375. soap_utilize_ns(soap, name, 0);
  12376. (void) soap_push_ns(soap, name + 5 + (name[5] == ':'), value, 0, 0);
  12377. } else {
  12378. soap->level--;
  12379. if (soap_set_attr(soap, name, value, 1))
  12380. return soap->error;
  12381. soap->level++;
  12382. }
  12383. } else
  12384. #endif
  12385. {
  12386. if (soap_send_raw(soap, " ", 1)
  12387. || soap_send(soap, name))
  12388. return soap->error;
  12389. if (value)
  12390. if (soap_send_raw(soap, "=\"", 2)
  12391. || soap_string_out(soap, value, 1)
  12392. || soap_send_raw(soap, "\"", 1))
  12393. return soap->error;
  12394. }
  12395. return SOAP_OK;
  12396. }
  12397. /******************************************************************************/
  12398. SOAP_FMAC1
  12399. int
  12400. SOAP_FMAC2
  12401. soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type) {
  12402. if (!soap_peek_element(soap)) {
  12403. if (soap->other)
  12404. return soap->error = SOAP_TAG_MISMATCH;
  12405. if (tag && *tag == '-')
  12406. return SOAP_OK;
  12407. soap->error = soap_match_tag(soap, soap->tag, tag);
  12408. if (!soap->error) {
  12409. if (type && *soap->type && soap_match_tag(soap, soap->type, type))
  12410. return soap->error = SOAP_TYPE;
  12411. soap->peeked = 0;
  12412. if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT))
  12413. return soap->error = SOAP_NULL;
  12414. if (soap->body) {
  12415. soap->level++;
  12416. if (soap->level > soap->maxlevel)
  12417. return soap->error = SOAP_LEVEL;
  12418. }
  12419. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin tag found (level=%u) '%s'='%s'\n", soap->level, soap->tag,
  12420. tag ? tag : SOAP_STR_EOS));
  12421. soap->error = SOAP_OK;
  12422. }
  12423. } else if (soap->error == SOAP_NO_TAG && tag && *tag == '-') {
  12424. soap->error = SOAP_OK;
  12425. }
  12426. return soap->error;
  12427. }
  12428. /******************************************************************************/
  12429. SOAP_FMAC1
  12430. int
  12431. SOAP_FMAC2
  12432. soap_element_end_in(struct soap *soap, const char *tag) {
  12433. soap_wchar c;
  12434. char *s = NULL;
  12435. int n = 0;
  12436. if (tag && *tag == '-')
  12437. return SOAP_OK;
  12438. if (soap->error == SOAP_NO_TAG)
  12439. soap->error = SOAP_OK;
  12440. #ifdef WITH_DOM
  12441. /* this whitespace or mixed content is significant for DOM "as-is" */
  12442. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  12443. {
  12444. const char *t = soap->dom->code; /* save XML code */
  12445. s = soap_string_in(soap, -1, -1, -1, NULL);
  12446. if (!soap->peeked && !s)
  12447. return soap->error;
  12448. if (soap->dom->prnt)
  12449. soap->dom = soap->dom->prnt;
  12450. if (s && (soap->mode & SOAP_XML_STRICT))
  12451. {
  12452. for (; *s; s++)
  12453. if (!soap_coblank((soap_wchar)*s))
  12454. return soap->error = SOAP_END_TAG; /* reject mixed content before ending tag */
  12455. }
  12456. soap->dom->code = t; /* restore XML code */
  12457. }
  12458. #endif
  12459. if (soap->peeked) {
  12460. if (*soap->tag)
  12461. n++;
  12462. soap->peeked = 0;
  12463. }
  12464. do {
  12465. while (((c = soap_get(soap)) != SOAP_TT)) {
  12466. if ((int) c == EOF)
  12467. return soap->error = SOAP_CHK_EOF;
  12468. if (!soap_coblank(c)) {
  12469. if ((soap->mode & SOAP_XML_STRICT))
  12470. return soap->error = SOAP_END_TAG; /* reject mixed content before ending tag */
  12471. if (c == SOAP_LT)
  12472. n++;
  12473. else if (c == '/') {
  12474. c = soap_get(soap);
  12475. if (c == SOAP_GT && n > 0)
  12476. n--;
  12477. else
  12478. soap_unget(soap, c);
  12479. }
  12480. }
  12481. }
  12482. } while (n-- > 0);
  12483. s = soap->tag;
  12484. n = sizeof(soap->tag);
  12485. while ((c = soap_get(soap)) > 32) {
  12486. if (n > 1) {
  12487. *s++ = (char) c;
  12488. n--;
  12489. }
  12490. }
  12491. *s = '\0';
  12492. if ((int) c == EOF)
  12493. return soap->error = SOAP_CHK_EOF;
  12494. while (soap_coblank(c))
  12495. c = soap_get(soap);
  12496. if (c != SOAP_GT)
  12497. return soap->error = SOAP_SYNTAX_ERROR;
  12498. #ifndef WITH_LEAN
  12499. #ifdef WITH_DOM
  12500. if (soap->feltendin)
  12501. {
  12502. int err = soap->error;
  12503. soap->error = soap->feltendin(soap, soap->tag, tag);
  12504. if (soap->error)
  12505. return soap->error;
  12506. if (err)
  12507. return soap->error = err; /* restore error */
  12508. }
  12509. #endif
  12510. #endif
  12511. if (tag && (soap->mode & SOAP_XML_STRICT)) {
  12512. soap_pop_namespace(soap);
  12513. if (soap_match_tag(soap, soap->tag, tag)) {
  12514. DBGLOG(TEST,
  12515. SOAP_MESSAGE(fdebug, "End tag '%s' does not match '%s'\n", soap->tag, tag ? tag : SOAP_STR_EOS));
  12516. return soap->error = SOAP_SYNTAX_ERROR;
  12517. }
  12518. }
  12519. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End tag found (level=%u) '%s'='%s'\n", soap->level, soap->tag,
  12520. tag ? tag : SOAP_STR_EOS));
  12521. soap->level--;
  12522. return SOAP_OK;
  12523. }
  12524. /******************************************************************************/
  12525. SOAP_FMAC1
  12526. const char *
  12527. SOAP_FMAC2
  12528. soap_attr_value(struct soap *soap, const char *name, int flag, int occurs) {
  12529. struct soap_attribute *tp;
  12530. if (*name == '-')
  12531. return SOAP_STR_EOS;
  12532. for (tp = soap->attributes; tp; tp = tp->next) {
  12533. if (tp->visible == 2 && !soap_match_att(soap, tp->name, name))
  12534. break;
  12535. }
  12536. if (tp) {
  12537. if (occurs == 4 || (occurs == 2 && (soap->mode & SOAP_XML_STRICT)))
  12538. soap->error = SOAP_PROHIBITED;
  12539. else if (flag >= 4)
  12540. return soap_collapse(soap, tp->value, flag, 1);
  12541. else
  12542. return tp->value;
  12543. } else if (occurs == 3 || (occurs == 1 && (soap->mode & SOAP_XML_STRICT))) {
  12544. soap->error = SOAP_REQUIRED;
  12545. } else {
  12546. soap->error = SOAP_OK;
  12547. }
  12548. return NULL;
  12549. }
  12550. /******************************************************************************/
  12551. SOAP_FMAC1
  12552. int
  12553. SOAP_FMAC2
  12554. soap_set_attr(struct soap *soap, const char *name, const char *value, int flag) {
  12555. struct soap_attribute *tp, *tq;
  12556. if (*name == '-')
  12557. return SOAP_OK;
  12558. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value ? value : SOAP_STR_EOS));
  12559. tq = NULL;
  12560. for (tp = soap->attributes; tp; tq = tp, tp = tp->next) {
  12561. if (!strcmp(tp->name, name))
  12562. break;
  12563. }
  12564. if (!tp) {
  12565. size_t l = strlen(name);
  12566. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name));
  12567. if (sizeof(struct soap_attribute) + l > l &&
  12568. (SOAP_MAXALLOCSIZE <= 0 || sizeof(struct soap_attribute) + l <= SOAP_MAXALLOCSIZE))
  12569. tp = (struct soap_attribute *) SOAP_MALLOC(soap, sizeof(struct soap_attribute) + l);
  12570. if (!tp)
  12571. return soap->error = SOAP_EOM;
  12572. tp->ns = NULL;
  12573. #ifndef WITH_LEAN
  12574. if ((soap->mode & SOAP_XML_CANONICAL)) {
  12575. struct soap_attribute **tpp = &soap->attributes;
  12576. const char *s = strchr(name, ':');
  12577. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name));
  12578. if (!strncmp(name, "xmlns", 5)) {
  12579. for (; *tpp; tpp = &(*tpp)->next)
  12580. if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0)
  12581. break;
  12582. } else if (!s) {
  12583. for (; *tpp; tpp = &(*tpp)->next)
  12584. if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0))
  12585. break;
  12586. } else {
  12587. struct soap_nlist *np = soap_lookup_ns(soap, name, s - name);
  12588. if (np) {
  12589. tp->ns = np->ns;
  12590. } else {
  12591. struct soap_attribute *tq;
  12592. for (tq = soap->attributes; tq; tq = tq->next) {
  12593. if (!strncmp(tq->name, "xmlns:", 6) && !strncmp(tq->name + 6, name, s - name) &&
  12594. !tq->name[6 + s - name]) {
  12595. tp->ns = tq->ns;
  12596. break;
  12597. }
  12598. }
  12599. }
  12600. for (; *tpp; tpp = &(*tpp)->next) {
  12601. int k;
  12602. if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns &&
  12603. ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0)))
  12604. break;
  12605. }
  12606. }
  12607. tp->next = *tpp;
  12608. *tpp = tp;
  12609. } else
  12610. #endif
  12611. if (tq) {
  12612. tq->next = tp;
  12613. tp->next = NULL;
  12614. } else {
  12615. tp->next = soap->attributes;
  12616. soap->attributes = tp;
  12617. }
  12618. soap_strcpy((char *) tp->name, l + 1, name);
  12619. tp->value = NULL;
  12620. } else if (tp->visible) {
  12621. return SOAP_OK;
  12622. } else if (value && tp->value && tp->size <= strlen(value)) {
  12623. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, (void *) tp->value));
  12624. SOAP_FREE(soap, tp->value);
  12625. tp->value = NULL;
  12626. tp->ns = NULL;
  12627. }
  12628. if (value) {
  12629. if (!tp->value) {
  12630. tp->size = strlen(value) + 1;
  12631. if (SOAP_MAXALLOCSIZE <= 0 || tp->size <= SOAP_MAXALLOCSIZE)
  12632. tp->value = (char *) SOAP_MALLOC(soap, tp->size);
  12633. if (!tp->value)
  12634. return soap->error = SOAP_EOM;
  12635. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value for %s (%p)\n", tp->name, (void *) tp->value));
  12636. }
  12637. soap_strcpy(tp->value, tp->size, value);
  12638. if (!strncmp(tp->name, "xmlns:", 6))
  12639. tp->ns = tp->value;
  12640. tp->visible = 2;
  12641. tp->flag = (short) flag;
  12642. #ifndef WITH_LEAN
  12643. if (!strcmp(name, "wsu:Id")) {
  12644. soap->event = SOAP_SEC_BEGIN;
  12645. soap_strcpy(soap->id, sizeof(soap->id), value);
  12646. }
  12647. if ((soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_XML_CANONICAL_NA)) {
  12648. const char *s = strchr(name, ':');
  12649. if (s && strchr(value, ':')) {
  12650. struct soap_nlist *np = soap_lookup_ns(soap, name, s - name);
  12651. if (np && np->ns && soap->local_namespaces) {
  12652. if ((!strcmp(s + 1, "type") && !strcmp(np->ns, soap->local_namespaces[2].ns)) /* xsi:type QName */
  12653. || ((!strcmp(s + 1, "arrayType") || !strcmp(s + 1, "itemType")) && !strcmp(np->ns,
  12654. soap->local_namespaces[1].ns))) /* SOAP-ENC:arrayType and SOAP-ENC:itemType QName */
  12655. soap_utilize_ns(soap, value, 1);
  12656. }
  12657. }
  12658. }
  12659. #endif
  12660. } else {
  12661. tp->visible = 1;
  12662. }
  12663. return SOAP_OK;
  12664. }
  12665. /******************************************************************************/
  12666. SOAP_FMAC1
  12667. void
  12668. SOAP_FMAC2
  12669. soap_clr_attr(struct soap *soap) {
  12670. struct soap_attribute *tp;
  12671. #ifndef WITH_LEAN
  12672. if ((soap->mode & SOAP_XML_CANONICAL)) {
  12673. while (soap->attributes) {
  12674. tp = soap->attributes->next;
  12675. if (soap->attributes->value)
  12676. SOAP_FREE(soap, soap->attributes->value);
  12677. SOAP_FREE(soap, soap->attributes);
  12678. soap->attributes = tp;
  12679. }
  12680. } else
  12681. #endif
  12682. {
  12683. for (tp = soap->attributes; tp; tp = tp->next)
  12684. tp->visible = 0;
  12685. }
  12686. }
  12687. /******************************************************************************/
  12688. static int
  12689. soap_getattrval(struct soap *soap, char *s, size_t *n, soap_wchar d) {
  12690. char buf[8];
  12691. size_t i;
  12692. size_t k = *n;
  12693. size_t m = 0;
  12694. char *t = buf;
  12695. for (i = 0; i < k; i++) {
  12696. soap_wchar c;
  12697. if (m) {
  12698. *s++ = *t++;
  12699. m--;
  12700. continue;
  12701. }
  12702. if ((soap->mode & SOAP_C_UTFSTRING)) {
  12703. c = soap_get(soap);
  12704. if ((c & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) {
  12705. t = buf;
  12706. c &= 0x7FFFFFFF;
  12707. if (c < 0x0800)
  12708. *t++ = (char) (0xC0 | ((c >> 6) & 0x1F));
  12709. else {
  12710. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  12711. if (!((c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF)))
  12712. c = SOAP_UNKNOWN_UNICODE_CHAR;
  12713. #endif
  12714. if (c < 0x010000) {
  12715. *t++ = (char) (0xE0 | ((c >> 12) & 0x0F));
  12716. } else {
  12717. if (c < 0x200000) {
  12718. *t++ = (char) (0xF0 | ((c >> 18) & 0x07));
  12719. } else {
  12720. if (c < 0x04000000) {
  12721. *t++ = (char) (0xF8 | ((c >> 24) & 0x03));
  12722. } else {
  12723. *t++ = (char) (0xFC | ((c >> 30) & 0x01));
  12724. *t++ = (char) (0x80 | ((c >> 24) & 0x3F));
  12725. }
  12726. *t++ = (char) (0x80 | ((c >> 18) & 0x3F));
  12727. }
  12728. *t++ = (char) (0x80 | ((c >> 12) & 0x3F));
  12729. }
  12730. *t++ = (char) (0x80 | ((c >> 6) & 0x3F));
  12731. }
  12732. *t++ = (char) (0x80 | (c & 0x3F));
  12733. m = t - buf - 1;
  12734. if (i + m >= k) {
  12735. soap_unget(soap, c | 0x80000000);
  12736. *n = i;
  12737. return soap->error = SOAP_EOM;
  12738. }
  12739. t = buf;
  12740. *s++ = *t++;
  12741. continue;
  12742. }
  12743. } else {
  12744. c = soap_getutf8(soap);
  12745. }
  12746. switch (c) {
  12747. case SOAP_TT:
  12748. *s++ = '<';
  12749. soap_unget(soap, '/');
  12750. break;
  12751. case SOAP_LT:
  12752. *s++ = '<';
  12753. break;
  12754. case SOAP_GT:
  12755. if (d == ' ') {
  12756. soap_unget(soap, c);
  12757. *s = '\0';
  12758. *n = i + 1;
  12759. return SOAP_OK;
  12760. }
  12761. *s++ = '>';
  12762. break;
  12763. case SOAP_QT:
  12764. if (c == d) {
  12765. *s = '\0';
  12766. *n = i + 1;
  12767. return SOAP_OK;
  12768. }
  12769. *s++ = '"';
  12770. break;
  12771. case SOAP_AP:
  12772. if (c == d) {
  12773. *s = '\0';
  12774. *n = i + 1;
  12775. return SOAP_OK;
  12776. }
  12777. *s++ = '\'';
  12778. break;
  12779. case '\t':
  12780. case '\n':
  12781. case '\r':
  12782. case ' ':
  12783. case '/':
  12784. if (d == ' ') {
  12785. soap_unget(soap, c);
  12786. *s = '\0';
  12787. *n = i + 1;
  12788. return SOAP_OK;
  12789. }
  12790. *s++ = (char) c;
  12791. break;
  12792. default:
  12793. if ((int) c == EOF) {
  12794. *s = '\0';
  12795. *n = i + 1;
  12796. return soap->error = SOAP_CHK_EOF;
  12797. }
  12798. *s++ = (char) c;
  12799. }
  12800. }
  12801. return soap->error = SOAP_EOM;
  12802. }
  12803. /******************************************************************************/
  12804. #ifdef WITH_FAST
  12805. SOAP_FMAC1
  12806. int
  12807. SOAP_FMAC2
  12808. soap_store_lab(struct soap *soap, const char *s, size_t n) {
  12809. soap->labidx = 0;
  12810. return soap_append_lab(soap, s, n);
  12811. }
  12812. #endif
  12813. /******************************************************************************/
  12814. #ifdef WITH_FAST
  12815. SOAP_FMAC1
  12816. int
  12817. SOAP_FMAC2
  12818. soap_append_lab(struct soap *soap, const char *s, size_t n) {
  12819. if (soap->labidx + n < soap->labidx)
  12820. return soap->error = SOAP_EOM;
  12821. if (soap->labidx + n >= soap->lablen) {
  12822. char *t = soap->labbuf;
  12823. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, size=%lu\n",
  12824. (unsigned long) soap->lablen));
  12825. if (soap->lablen == 0)
  12826. soap->lablen = SOAP_LABLEN;
  12827. while (soap->labidx + n >= soap->lablen) {
  12828. if (soap->lablen << 1 < soap->lablen)
  12829. return soap->error = SOAP_EOM;
  12830. soap->lablen <<= 1;
  12831. }
  12832. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New look-aside buffer size=%lu\n", (unsigned long) soap->lablen));
  12833. if (SOAP_MAXALLOCSIZE > 0 && soap->lablen > SOAP_MAXALLOCSIZE)
  12834. return soap->error = SOAP_EOM;
  12835. soap->labbuf = (char *) SOAP_MALLOC(soap, soap->lablen);
  12836. if (!soap->labbuf) {
  12837. if (t)
  12838. SOAP_FREE(soap, t);
  12839. return soap->error = SOAP_EOM;
  12840. }
  12841. if (t) {
  12842. (void) soap_memcpy((void *) soap->labbuf, soap->lablen, (const void *) t, soap->labidx);
  12843. SOAP_FREE(soap, t);
  12844. }
  12845. }
  12846. if (s) {
  12847. (void) soap_memcpy((void *) (soap->labbuf + soap->labidx), soap->lablen - soap->labidx, (const void *) s, n);
  12848. soap->labidx += n;
  12849. }
  12850. return SOAP_OK;
  12851. }
  12852. #endif
  12853. /******************************************************************************/
  12854. SOAP_FMAC1
  12855. int
  12856. SOAP_FMAC2
  12857. soap_peek_element(struct soap *soap) {
  12858. #ifdef WITH_DOM
  12859. struct soap_dom_attribute **att = NULL;
  12860. char *lead = NULL;
  12861. #endif
  12862. struct soap_attribute *tp, *tq = NULL;
  12863. const char *t;
  12864. char *s;
  12865. soap_wchar c;
  12866. int i;
  12867. if (soap->peeked) {
  12868. if (!*soap->tag)
  12869. return soap->error = SOAP_NO_TAG;
  12870. return SOAP_OK;
  12871. }
  12872. soap->peeked = 1;
  12873. soap->id[0] = '\0';
  12874. soap->href[0] = '\0';
  12875. soap->type[0] = '\0';
  12876. soap->arrayType[0] = '\0';
  12877. soap->arraySize[0] = '\0';
  12878. soap->arrayOffset[0] = '\0';
  12879. soap->other = 0;
  12880. soap->root = -1;
  12881. soap->position = 0;
  12882. soap->null = 0;
  12883. soap->mustUnderstand = 0;
  12884. /* UTF-8 BOM? */
  12885. c = soap_getchar(soap);
  12886. if (c == 0xEF && soap_get0(soap) == 0xBB) {
  12887. soap_get1(soap);
  12888. c = soap_get1(soap);
  12889. if (c == 0xBF)
  12890. soap->mode &= ~SOAP_ENC_LATIN;
  12891. else
  12892. soap_unget(soap, (0x0F << 12) | (0xBB << 6) | (c & 0x3F)); /* UTF-8 */
  12893. } else if ((c == 0xFE && soap_get0(soap) == 0xFF) /* UTF-16 BE */
  12894. || (c == 0xFF && soap_get0(soap) == 0xFE)) /* UTF-16 LE */
  12895. {
  12896. return soap->error = SOAP_UTF_ERROR;
  12897. } else {
  12898. soap_unget(soap, c);
  12899. }
  12900. c = soap_get(soap);
  12901. #ifdef WITH_DOM
  12902. /* whitespace leading up to the start tag is significant for DOM as-is (but comments and PIs are removed from this lead) */
  12903. if (soap_coblank(c))
  12904. {
  12905. soap->labidx = 0;
  12906. do
  12907. {
  12908. if (soap_append_lab(soap, NULL, 0))
  12909. return soap->error;
  12910. s = soap->labbuf + soap->labidx;
  12911. i = soap->lablen - soap->labidx;
  12912. soap->labidx = soap->lablen;
  12913. while (soap_coblank(c) && i-- > 0)
  12914. {
  12915. *s++ = c;
  12916. c = soap_get(soap);
  12917. }
  12918. } while (soap_coblank(c) || i == 0);
  12919. *s = '\0';
  12920. lead = soap->labbuf;
  12921. }
  12922. #else
  12923. /* skip space */
  12924. while (soap_coblank(c)) {
  12925. c = soap_get(soap);
  12926. }
  12927. #endif
  12928. if (c != SOAP_LT) {
  12929. *soap->tag = '\0';
  12930. if ((int) c == EOF)
  12931. return soap->error = SOAP_CHK_EOF;
  12932. soap_unget(soap, c);
  12933. #ifdef WITH_DOM
  12934. /* whitespace leading up to the end tag is significant for DOM as-is */
  12935. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  12936. {
  12937. if (lead && *lead)
  12938. soap->dom->tail = soap_strdup(soap, lead);
  12939. else
  12940. soap->dom->tail = SOAP_STR_EOS; /* body with closing tag instead of <tag/> */
  12941. }
  12942. #endif
  12943. return soap->error = SOAP_NO_TAG;
  12944. }
  12945. do {
  12946. c = soap_get1(soap);
  12947. } while (soap_coblank(c));
  12948. s = soap->tag;
  12949. i = sizeof(soap->tag);
  12950. while (c != '>' && c != '/' && c > 32 && (int) c != EOF) {
  12951. if (i > 1) {
  12952. *s++ = (char) c;
  12953. i--;
  12954. }
  12955. c = soap_get1(soap);
  12956. }
  12957. *s = '\0';
  12958. while (soap_coblank(c))
  12959. c = soap_get1(soap);
  12960. #ifdef WITH_DOM
  12961. if ((soap->mode & SOAP_XML_DOM))
  12962. {
  12963. struct soap_dom_element *elt;
  12964. elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
  12965. if (!elt)
  12966. return soap->error;
  12967. elt->next = NULL;
  12968. elt->prnt = soap->dom;
  12969. elt->elts = NULL;
  12970. elt->atts = NULL;
  12971. elt->nstr = NULL;
  12972. elt->name = soap_strdup(soap, soap->tag);
  12973. elt->text = NULL;
  12974. elt->code = NULL;
  12975. elt->tail = NULL;
  12976. elt->node = NULL;
  12977. elt->type = 0;
  12978. if (lead && *lead)
  12979. elt->lead = soap_strdup(soap, lead);
  12980. else
  12981. elt->lead = NULL;
  12982. elt->soap = soap;
  12983. if (soap->dom)
  12984. {
  12985. struct soap_dom_element *p = soap->dom->elts;
  12986. if (p)
  12987. {
  12988. while (p->next)
  12989. p = p->next;
  12990. p->next = elt;
  12991. }
  12992. else
  12993. {
  12994. soap->dom->elts = elt;
  12995. }
  12996. }
  12997. soap->dom = elt;
  12998. att = &elt->atts;
  12999. if (!elt->name)
  13000. return soap->error = SOAP_EOM;
  13001. }
  13002. #endif
  13003. soap_pop_namespace(soap);
  13004. for (tp = soap->attributes; tp; tp = tp->next)
  13005. tp->visible = 0;
  13006. while ((int) c != EOF && c != '>' && c != '/') {
  13007. s = soap->tmpbuf;
  13008. i = sizeof(soap->tmpbuf);
  13009. while (c != '=' && c != '>' && c != '/' && c > 32 && (int) c != EOF) {
  13010. if (i > 1) {
  13011. *s++ = (char) c;
  13012. i--;
  13013. }
  13014. c = soap_get1(soap);
  13015. }
  13016. *s = '\0';
  13017. if (i == sizeof(soap->tmpbuf))
  13018. return soap->error = SOAP_SYNTAX_ERROR;
  13019. #ifdef WITH_DOM
  13020. /* add attribute name to dom */
  13021. if (att)
  13022. {
  13023. *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
  13024. if (!*att)
  13025. return soap->error;
  13026. (*att)->next = NULL;
  13027. (*att)->nstr = NULL;
  13028. (*att)->name = soap_strdup(soap, soap->tmpbuf);
  13029. (*att)->text = NULL;
  13030. (*att)->soap = soap;
  13031. if (!(*att)->name)
  13032. return soap->error = SOAP_EOM;
  13033. }
  13034. #endif
  13035. if (!strncmp(soap->tmpbuf, "xmlns", 5)) {
  13036. if (soap->tmpbuf[5] == ':')
  13037. t = soap->tmpbuf + 6;
  13038. else if (soap->tmpbuf[5])
  13039. t = NULL;
  13040. else
  13041. t = SOAP_STR_EOS;
  13042. } else {
  13043. t = NULL;
  13044. }
  13045. tq = NULL;
  13046. for (tp = soap->attributes; tp; tq = tp, tp = tp->next) {
  13047. if (!SOAP_STRCMP(tp->name, soap->tmpbuf))
  13048. break;
  13049. }
  13050. if (!tp) {
  13051. size_t l = strlen(soap->tmpbuf);
  13052. tp = (struct soap_attribute *) SOAP_MALLOC(soap, sizeof(struct soap_attribute) + l);
  13053. if (!tp)
  13054. return soap->error = SOAP_EOM;
  13055. (void) soap_memcpy((char *) tp->name, l + 1, soap->tmpbuf, l + 1);
  13056. tp->value = NULL;
  13057. tp->size = 0;
  13058. tp->ns = NULL;
  13059. tp->visible = 0;
  13060. /* append attribute to the end of the list */
  13061. if (tq) {
  13062. tq->next = tp;
  13063. tp->next = NULL;
  13064. } else {
  13065. tp->next = soap->attributes;
  13066. soap->attributes = tp;
  13067. }
  13068. }
  13069. while (soap_coblank(c))
  13070. c = soap_get1(soap);
  13071. if (c == '=') {
  13072. size_t k;
  13073. do {
  13074. c = soap_getutf8(soap);
  13075. } while (soap_coblank(c));
  13076. if (c != SOAP_QT && c != SOAP_AP) {
  13077. soap_unget(soap, c);
  13078. c = ' '; /* blank delimiter */
  13079. }
  13080. k = tp->size;
  13081. if (soap_getattrval(soap, tp->value, &k, c)) {
  13082. #ifdef WITH_FAST
  13083. if (soap->error != SOAP_EOM)
  13084. return soap->error;
  13085. soap->error = SOAP_OK;
  13086. if (soap_store_lab(soap, tp->value, k))
  13087. return soap->error;
  13088. if (tp->value)
  13089. SOAP_FREE(soap, tp->value);
  13090. tp->value = NULL;
  13091. for (;;) {
  13092. k = soap->lablen - soap->labidx;
  13093. if (soap_getattrval(soap, soap->labbuf + soap->labidx, &k, c)) {
  13094. if (soap->error != SOAP_EOM)
  13095. return soap->error;
  13096. soap->error = SOAP_OK;
  13097. soap->labidx = soap->lablen;
  13098. if (soap_append_lab(soap, NULL, 0))
  13099. return soap->error;
  13100. } else {
  13101. break;
  13102. }
  13103. }
  13104. if (soap->labidx) {
  13105. tp->size = soap->lablen;
  13106. } else {
  13107. tp->size = strlen(soap->labbuf) + 1;
  13108. if (tp->size < SOAP_LABLEN)
  13109. tp->size = SOAP_LABLEN;
  13110. }
  13111. tp->value = (char *) SOAP_MALLOC(soap, tp->size);
  13112. if (!tp->value)
  13113. return soap->error = SOAP_EOM;
  13114. soap_strcpy(tp->value, tp->size, soap->labbuf);
  13115. #else
  13116. tp->size = k;
  13117. if (soap->error != SOAP_EOM)
  13118. return soap->error;
  13119. soap->error = SOAP_OK;
  13120. if (soap_alloc_block(soap) == NULL)
  13121. return soap->error;
  13122. for (;;)
  13123. {
  13124. s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN);
  13125. if (!s)
  13126. return soap->error;
  13127. k = SOAP_BLKLEN;
  13128. if (soap_getattrval(soap, s, &k, c))
  13129. {
  13130. if (soap->error != SOAP_EOM)
  13131. return soap->error;
  13132. soap->error = SOAP_OK;
  13133. soap_size_block(soap, NULL, k);
  13134. }
  13135. else
  13136. {
  13137. break;
  13138. }
  13139. }
  13140. k = tp->size + soap->blist->size;
  13141. if (SOAP_MAXALLOCSIZE > 0 && k > SOAP_MAXALLOCSIZE)
  13142. return soap->error = SOAP_EOM;
  13143. s = (char*)SOAP_MALLOC(soap, k);
  13144. if (!s)
  13145. return soap->error = SOAP_EOM;
  13146. if (tp->value)
  13147. {
  13148. (void)soap_memcpy((void*)s, k, (const void*)tp->value, tp->size);
  13149. SOAP_FREE(soap, tp->value);
  13150. }
  13151. soap_save_block(soap, NULL, s + tp->size, 0);
  13152. tp->value = s;
  13153. tp->size = k;
  13154. #endif
  13155. }
  13156. if (tp->visible) {
  13157. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Duplicate attribute in %s\n", soap->tag));
  13158. return soap->error = SOAP_SYNTAX_ERROR; /* redefined (duplicate) attribute */
  13159. }
  13160. tp->visible = 2; /* seen this attribute w/ value */
  13161. do {
  13162. c = soap_get1(soap);
  13163. } while (soap_coblank(c));
  13164. #ifdef WITH_DOM
  13165. if (att && tp->value)
  13166. {
  13167. (*att)->text = soap_strdup(soap, tp->value);
  13168. if (!(*att)->text)
  13169. return soap->error = SOAP_EOM;
  13170. }
  13171. #endif
  13172. } else {
  13173. tp->visible = 1; /* seen this attribute w/o value */
  13174. }
  13175. #ifdef WITH_DOM
  13176. if (att)
  13177. att = &(*att)->next;
  13178. #endif
  13179. if (t && tp->value) {
  13180. if (soap_push_namespace(soap, t, tp->value) == NULL)
  13181. return soap->error;
  13182. }
  13183. }
  13184. #ifdef WITH_DOM
  13185. if (att)
  13186. {
  13187. soap->dom->nstr = soap_current_namespace_tag(soap, soap->tag);
  13188. for (att = &soap->dom->atts; *att; att = &(*att)->next)
  13189. (*att)->nstr = soap_current_namespace_att(soap, (*att)->name);
  13190. }
  13191. #endif
  13192. if ((int) c == EOF)
  13193. return soap->error = SOAP_CHK_EOF;
  13194. soap->body = (c != '/');
  13195. if (!soap->body) {
  13196. do {
  13197. c = soap_get1(soap);
  13198. } while (soap_coblank(c));
  13199. }
  13200. #ifdef WITH_DOM
  13201. if ((soap->mode & SOAP_XML_DOM))
  13202. {
  13203. if (!soap->body && soap->dom->prnt)
  13204. soap->dom = soap->dom->prnt;
  13205. }
  13206. #endif
  13207. for (tp = soap->attributes; tp; tp = tp->next) {
  13208. if (tp->visible && tp->value) {
  13209. #ifndef WITH_NOIDREF
  13210. if (!strcmp(tp->name, "id")) {
  13211. if ((soap->version > 0 && !(soap->imode & SOAP_XML_TREE))
  13212. || (soap->mode & SOAP_XML_GRAPH)) {
  13213. *soap->id = '#';
  13214. soap_strcpy(soap->id + 1, sizeof(soap->id) - 1, tp->value);
  13215. }
  13216. } else if (!strcmp(tp->name, "href")) {
  13217. if ((soap->version == 1 && !(soap->imode & SOAP_XML_TREE))
  13218. || (soap->mode & SOAP_XML_GRAPH)
  13219. || ((soap->mode & (SOAP_ENC_MTOM | SOAP_ENC_DIME)) && *tp->value != '#'))
  13220. soap_strcpy(soap->href, sizeof(soap->href), tp->value);
  13221. } else if (!strcmp(tp->name, "ref")) {
  13222. if ((soap->version == 2 && !(soap->imode & SOAP_XML_TREE))
  13223. || (soap->mode & SOAP_XML_GRAPH)) {
  13224. *soap->href = '#';
  13225. soap_strcpy(soap->href + (*tp->value != '#'), sizeof(soap->href) - 1, tp->value);
  13226. }
  13227. }
  13228. #else
  13229. if (!strcmp(tp->name, "href"))
  13230. {
  13231. if ((soap->mode & (SOAP_ENC_MTOM | SOAP_ENC_DIME)) && *tp->value != '#')
  13232. soap_strcpy(soap->href, sizeof(soap->href), tp->value);
  13233. }
  13234. #endif
  13235. else if (!soap_match_tag(soap, tp->name, "xsi:type")) {
  13236. soap_strcpy(soap->type, sizeof(soap->type), tp->value);
  13237. } else if ((!soap_match_tag(soap, tp->name, "xsi:null")
  13238. || !soap_match_tag(soap, tp->name, "xsi:nil"))
  13239. && (!strcmp(tp->value, "1")
  13240. || !strcmp(tp->value, "true"))) {
  13241. soap->null = 1;
  13242. } else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:encodingStyle")) {
  13243. if (!soap->encodingStyle)
  13244. soap->encodingStyle = SOAP_STR_EOS;
  13245. soap_version(soap);
  13246. } else if (soap->version == 1) {
  13247. if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType")) {
  13248. s = soap_strrchr(tp->value, '[');
  13249. if (s && (size_t) (s - tp->value) < sizeof(soap->arrayType)) {
  13250. (void) soap_strncpy(soap->arrayType, sizeof(soap->arrayType), tp->value, s - tp->value);
  13251. soap_strcpy(soap->arraySize, sizeof(soap->arraySize), s);
  13252. } else
  13253. soap_strcpy(soap->arrayType, sizeof(soap->arrayType), tp->value);
  13254. } else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:offset")) {
  13255. soap_strcpy(soap->arrayOffset, sizeof(soap->arrayOffset), tp->value);
  13256. } else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:position")) {
  13257. soap->position = soap_getposition(tp->value, soap->positions);
  13258. } else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:root")) {
  13259. soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true")));
  13260. } else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
  13261. && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) {
  13262. soap->mustUnderstand = 1;
  13263. } else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor")) {
  13264. if ((!soap->actor || strcmp(soap->actor, tp->value))
  13265. && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next"))
  13266. soap->other = 1;
  13267. }
  13268. } else if (soap->version == 2) {
  13269. #ifndef WITH_NOIDREF
  13270. if (!soap_match_tag(soap, tp->name, "SOAP-ENC:id")) {
  13271. *soap->id = '#';
  13272. soap_strcpy(soap->id + 1, sizeof(soap->id) - 1, tp->value);
  13273. } else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:ref")) {
  13274. *soap->href = '#';
  13275. soap_strcpy(soap->href + (*tp->value != '#'), sizeof(soap->href) - 1, tp->value);
  13276. } else
  13277. #endif
  13278. if (!soap_match_tag(soap, tp->name, "SOAP-ENC:itemType")) {
  13279. soap_strcpy(soap->arrayType, sizeof(soap->arrayType), tp->value);
  13280. } else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize")) {
  13281. soap_strcpy(soap->arraySize, sizeof(soap->arraySize), tp->value);
  13282. } else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
  13283. && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) {
  13284. soap->mustUnderstand = 1;
  13285. } else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:role")) {
  13286. if ((!soap->actor || strcmp(soap->actor, tp->value))
  13287. && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next"))
  13288. soap->other = 1;
  13289. }
  13290. } else {
  13291. if (!soap_match_tag(soap, tp->name, "wsdl:required") && !strcmp(tp->value, "true"))
  13292. soap->mustUnderstand = 1;
  13293. }
  13294. }
  13295. }
  13296. #ifdef WITH_DOM
  13297. if (soap->feltbegin)
  13298. return soap->error = soap->feltbegin(soap, soap->tag);
  13299. #endif
  13300. return soap->error = SOAP_OK;
  13301. }
  13302. /******************************************************************************/
  13303. SOAP_FMAC1
  13304. void
  13305. SOAP_FMAC2
  13306. soap_retry(struct soap *soap) {
  13307. soap->error = SOAP_OK;
  13308. soap_revert(soap);
  13309. }
  13310. /******************************************************************************/
  13311. SOAP_FMAC1
  13312. void
  13313. SOAP_FMAC2
  13314. soap_revert(struct soap *soap) {
  13315. if (!soap->peeked) {
  13316. soap->peeked = 1;
  13317. if (soap->body)
  13318. soap->level--;
  13319. }
  13320. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting to last element '%s' (level=%u)\n", soap->tag, soap->level));
  13321. }
  13322. /******************************************************************************/
  13323. SOAP_FMAC1
  13324. int
  13325. SOAP_FMAC2
  13326. soap_ignore(struct soap *soap) {
  13327. int n = 0;
  13328. soap_wchar c;
  13329. soap->level++;
  13330. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Ignoring XML content at level=%u\n", soap->level));
  13331. #ifdef WITH_DOM
  13332. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  13333. {
  13334. if (!soap_string_in(soap, -1, -1, -1, NULL))
  13335. return soap->error;
  13336. }
  13337. else
  13338. #endif
  13339. {
  13340. for (;;) {
  13341. c = soap_get(soap);
  13342. switch (c) {
  13343. case SOAP_TT:
  13344. if (n == 0)
  13345. goto end;
  13346. n--;
  13347. break;
  13348. case SOAP_LT:
  13349. n++;
  13350. break;
  13351. case '/':
  13352. if (n > 0) {
  13353. c = soap_get0(soap);
  13354. if (c == '>')
  13355. n--;
  13356. }
  13357. break;
  13358. default:
  13359. if ((int) c == EOF)
  13360. return soap->error = SOAP_EOF;
  13361. }
  13362. }
  13363. end:
  13364. soap_unget(soap, c);
  13365. }
  13366. return soap_element_end_in(soap, NULL);
  13367. }
  13368. /******************************************************************************/
  13369. SOAP_FMAC1
  13370. int
  13371. SOAP_FMAC2
  13372. soap_string_out(struct soap *soap, const char *s, int flag) {
  13373. const char *t;
  13374. soap_wchar c;
  13375. soap_wchar mask = (soap_wchar) 0xFFFFFF80UL;
  13376. #ifdef WITH_DOM
  13377. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  13378. {
  13379. soap->dom->text = soap_strdup(soap, s);
  13380. if (!soap->dom->text)
  13381. return soap->error = SOAP_EOM;
  13382. return SOAP_OK;
  13383. }
  13384. #endif
  13385. if (flag == 2 || (soap->mode & SOAP_C_UTFSTRING))
  13386. mask = 0;
  13387. t = s;
  13388. while ((c = *t++)) {
  13389. switch (c) {
  13390. case 0x09:
  13391. if (flag) {
  13392. if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#x9;", 5))
  13393. return soap->error;
  13394. s = t;
  13395. }
  13396. break;
  13397. case 0x0A:
  13398. if (flag || !(soap->mode & SOAP_XML_CANONICAL)) {
  13399. if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#xA;", 5))
  13400. return soap->error;
  13401. s = t;
  13402. }
  13403. break;
  13404. case '&':
  13405. if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&amp;", 5))
  13406. return soap->error;
  13407. s = t;
  13408. break;
  13409. case '<':
  13410. if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&lt;", 4))
  13411. return soap->error;
  13412. s = t;
  13413. break;
  13414. case '>':
  13415. if (!flag) {
  13416. if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&gt;", 4))
  13417. return soap->error;
  13418. s = t;
  13419. }
  13420. break;
  13421. case '"':
  13422. if (flag) {
  13423. if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&quot;", 6))
  13424. return soap->error;
  13425. s = t;
  13426. }
  13427. break;
  13428. case 0x7F:
  13429. if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#x7F;", 6))
  13430. return soap->error;
  13431. s = t;
  13432. break;
  13433. default:
  13434. #ifndef WITH_LEANER
  13435. #ifdef HAVE_MBTOWC
  13436. if ((soap->mode & SOAP_C_MBSTRING)) {
  13437. wchar_t wc;
  13438. int m = mbtowc(&wc, t - 1, MB_CUR_MAX);
  13439. if (m > 0 && !((soap_wchar) wc == c && m == 1 && c < 0x80)) {
  13440. if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned long) wc))
  13441. return soap->error;
  13442. s = t += m - 1;
  13443. continue;
  13444. }
  13445. }
  13446. #endif
  13447. #endif
  13448. #ifndef WITH_NOSTRINGTOUTF8
  13449. if ((c & mask) || !(c & 0xFFFFFFE0UL)) {
  13450. if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char) c))
  13451. return soap->error;
  13452. s = t;
  13453. }
  13454. #endif
  13455. }
  13456. }
  13457. return soap_send_raw(soap, s, t - s - 1);
  13458. }
  13459. /******************************************************************************/
  13460. SOAP_FMAC1
  13461. char *
  13462. SOAP_FMAC2
  13463. soap_string_in(struct soap *soap, int flag, long minlen, long maxlen, const char *pattern) {
  13464. char *s;
  13465. char *t = NULL;
  13466. size_t i;
  13467. ULONG64 l = 0;
  13468. int n = 0, f = 0, m = 0;
  13469. soap_wchar c;
  13470. #if !defined(WITH_LEANER) && defined(HAVE_WCTOMB)
  13471. char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8];
  13472. #else
  13473. char buf[8];
  13474. #endif
  13475. if (maxlen < 0 && soap->maxlength > 0)
  13476. maxlen = soap->maxlength;
  13477. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reading string content, flag=%d\n", flag));
  13478. if (flag <= 0 && soap->peeked && *soap->tag) {
  13479. #ifndef WITH_LEAN
  13480. struct soap_attribute *tp;
  13481. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String content includes tag '%s' and attributes\n", soap->tag));
  13482. t = soap->tmpbuf;
  13483. *t = '<';
  13484. soap_strcpy(t + 1, sizeof(soap->tmpbuf) - 1, soap->tag);
  13485. t += strlen(t);
  13486. for (tp = soap->attributes; tp; tp = tp->next) {
  13487. if (tp->visible) {
  13488. size_t k = strlen(tp->name);
  13489. if (t + k + 1 >= soap->tmpbuf + sizeof(soap->tmpbuf))
  13490. break; /* too many or attribute values to large */
  13491. *t++ = ' ';
  13492. (void) soap_strncpy(t, sizeof(soap->tmpbuf) - (t - soap->tmpbuf), tp->name, k);
  13493. t += k;
  13494. if (tp->value) {
  13495. k = strlen(tp->value);
  13496. if (t + k + 3 >= soap->tmpbuf + sizeof(soap->tmpbuf))
  13497. break; /* too many or attribute values to large */
  13498. *t++ = '=';
  13499. *t++ = '"';
  13500. (void) soap_strncpy(t, sizeof(soap->tmpbuf) - (t - soap->tmpbuf), tp->value, k);
  13501. t += k;
  13502. *t++ = '"';
  13503. }
  13504. }
  13505. }
  13506. if (!soap->body)
  13507. *t++ = '/';
  13508. *t++ = '>';
  13509. *t = '\0';
  13510. t = soap->tmpbuf;
  13511. m = (int) strlen(soap->tmpbuf);
  13512. #endif
  13513. if (soap->body)
  13514. n = 1;
  13515. f = 1;
  13516. soap->peeked = 0;
  13517. }
  13518. #ifdef WITH_CDATA
  13519. if (flag <= 0) {
  13520. int state = 0;
  13521. #ifdef WITH_FAST
  13522. soap->labidx = 0; /* use look-aside buffer */
  13523. #else
  13524. if (soap_alloc_block(soap) == NULL)
  13525. return NULL;
  13526. #endif
  13527. for (;;) {
  13528. #ifdef WITH_FAST
  13529. size_t k;
  13530. if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
  13531. return NULL;
  13532. s = soap->labbuf + soap->labidx; /* space to populate */
  13533. k = soap->lablen - soap->labidx; /* number of bytes available */
  13534. soap->labidx = soap->lablen; /* claim this space */
  13535. #else
  13536. size_t k = SOAP_BLKLEN;
  13537. s = (char*)soap_push_block(soap, NULL, k);
  13538. if (!s)
  13539. return NULL;
  13540. #endif
  13541. for (i = 0; i < k; i++) {
  13542. if (m > 0) {
  13543. *s++ = *t++; /* copy multibyte characters */
  13544. m--;
  13545. continue;
  13546. }
  13547. c = soap_getchar(soap);
  13548. if ((int) c == EOF)
  13549. goto end;
  13550. if ((c >= 0x80 || c < SOAP_AP) && state != 1 && !(soap->mode & SOAP_ENC_LATIN)) {
  13551. if ((c & 0x7FFFFFFF) >= 0x80) {
  13552. soap_unget(soap, c);
  13553. c = soap_getutf8(soap);
  13554. }
  13555. if ((c & 0x7FFFFFFF) >= 0x80 && (flag <= 0 || (soap->mode & SOAP_C_UTFSTRING))) {
  13556. c &= 0x7FFFFFFF;
  13557. t = buf;
  13558. if (c < 0x0800)
  13559. *t++ = (char) (0xC0 | ((c >> 6) & 0x1F));
  13560. else {
  13561. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  13562. if (!((c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF)))
  13563. c = SOAP_UNKNOWN_UNICODE_CHAR;
  13564. #endif
  13565. if (c < 0x010000) {
  13566. *t++ = (char) (0xE0 | ((c >> 12) & 0x0F));
  13567. } else {
  13568. if (c < 0x200000) {
  13569. *t++ = (char) (0xF0 | ((c >> 18) & 0x07));
  13570. } else {
  13571. if (c < 0x04000000) {
  13572. *t++ = (char) (0xF8 | ((c >> 24) & 0x03));
  13573. } else {
  13574. *t++ = (char) (0xFC | ((c >> 30) & 0x01));
  13575. *t++ = (char) (0x80 | ((c >> 24) & 0x3F));
  13576. }
  13577. *t++ = (char) (0x80 | ((c >> 18) & 0x3F));
  13578. }
  13579. *t++ = (char) (0x80 | ((c >> 12) & 0x3F));
  13580. }
  13581. *t++ = (char) (0x80 | ((c >> 6) & 0x3F));
  13582. }
  13583. *t++ = (char) (0x80 | (c & 0x3F));
  13584. m = (int) (t - buf) - 1;
  13585. t = buf;
  13586. *s++ = *t++;
  13587. continue;
  13588. }
  13589. }
  13590. switch (state) {
  13591. case 1:
  13592. if (c == ']')
  13593. state = 4;
  13594. *s++ = (char) c;
  13595. continue;
  13596. case 2:
  13597. if (c == '-')
  13598. state = 6;
  13599. *s++ = (char) c;
  13600. continue;
  13601. case 3:
  13602. if (c == '?')
  13603. state = 8;
  13604. *s++ = (char) c;
  13605. continue;
  13606. /* CDATA */
  13607. case 4:
  13608. if (c == ']')
  13609. state = 5;
  13610. else
  13611. state = 1;
  13612. *s++ = (char) c;
  13613. continue;
  13614. case 5:
  13615. if (c == '>')
  13616. state = 0;
  13617. else if (c != ']')
  13618. state = 1;
  13619. *s++ = (char) c;
  13620. continue;
  13621. /* comment */
  13622. case 6:
  13623. if (c == '-')
  13624. state = 7;
  13625. else
  13626. state = 2;
  13627. *s++ = (char) c;
  13628. continue;
  13629. case 7:
  13630. if (c == '>')
  13631. state = 0;
  13632. else if (c != '-')
  13633. state = 2;
  13634. *s++ = (char) c;
  13635. continue;
  13636. /* PI */
  13637. case 8:
  13638. if (c == '>')
  13639. state = 0;
  13640. else if (c != '?')
  13641. state = 3;
  13642. *s++ = (char) c;
  13643. continue;
  13644. }
  13645. switch (c) {
  13646. case SOAP_TT:
  13647. if (n == 0)
  13648. goto end;
  13649. n--;
  13650. *s++ = '<';
  13651. t = (char *) "/";
  13652. m = 1;
  13653. break;
  13654. case SOAP_LT:
  13655. if (flag == 3 || (f && n == 0))
  13656. goto end;
  13657. n++;
  13658. *s++ = '<';
  13659. break;
  13660. case SOAP_GT:
  13661. *s++ = '>';
  13662. break;
  13663. case SOAP_QT:
  13664. *s++ = '"';
  13665. break;
  13666. case SOAP_AP:
  13667. *s++ = '\'';
  13668. break;
  13669. case '/':
  13670. if (n > 0) {
  13671. c = soap_getchar(soap);
  13672. if (c == '>')
  13673. n--;
  13674. soap_unget(soap, c);
  13675. }
  13676. *s++ = '/';
  13677. break;
  13678. case '<':
  13679. c = soap_getchar(soap);
  13680. if (c == '/') {
  13681. if (n == 0) {
  13682. c = SOAP_TT;
  13683. goto end;
  13684. }
  13685. n--;
  13686. } else if (c == '!') {
  13687. c = soap_getchar(soap);
  13688. if (c == '[') {
  13689. do {
  13690. c = soap_getchar(soap);
  13691. } while ((int) c != EOF && c != '[');
  13692. if ((int) c == EOF)
  13693. goto end;
  13694. t = (char *) "![CDATA[";
  13695. m = 8;
  13696. state = 1;
  13697. } else if (c == '-') {
  13698. c = soap_getchar(soap);
  13699. if (c == '-')
  13700. state = 2;
  13701. t = (char *) "!-";
  13702. m = 2;
  13703. soap_unget(soap, c);
  13704. } else {
  13705. t = (char *) "!";
  13706. m = 1;
  13707. soap_unget(soap, c);
  13708. }
  13709. *s++ = '<';
  13710. break;
  13711. } else if (c == '?') {
  13712. state = 3;
  13713. } else if (flag == 3 || (f && n == 0)) {
  13714. soap_revget1(soap);
  13715. c = '<';
  13716. goto end;
  13717. } else
  13718. n++;
  13719. soap_unget(soap, c);
  13720. *s++ = '<';
  13721. break;
  13722. case '>':
  13723. *s++ = '>';
  13724. break;
  13725. case '"':
  13726. *s++ = '"';
  13727. break;
  13728. default:
  13729. #ifndef WITH_LEANER
  13730. #ifdef HAVE_WCTOMB
  13731. if ((soap->mode & SOAP_C_MBSTRING)) {
  13732. #if defined(WIN32) && !defined(CYGWIN) && !defined(__MINGW32__) && !defined(__MINGW64__) && !defined(__BORLANDC__)
  13733. m = 0;
  13734. wctomb_s(&m, buf, sizeof(buf), (wchar_t)(c & 0x7FFFFFFF));
  13735. #else
  13736. m = wctomb(buf, (wchar_t) (c & 0x7FFFFFFF));
  13737. #endif
  13738. if (m >= 1 && m <= (int) MB_CUR_MAX) {
  13739. t = buf;
  13740. *s++ = *t++;
  13741. m--;
  13742. } else {
  13743. *s++ = SOAP_UNKNOWN_CHAR;
  13744. m = 0;
  13745. }
  13746. } else
  13747. #endif
  13748. #endif
  13749. *s++ = (char) (c & 0xFF);
  13750. }
  13751. l++;
  13752. if (maxlen >= 0 && l > (size_t) maxlen) {
  13753. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
  13754. soap->error = SOAP_LENGTH;
  13755. return NULL;
  13756. }
  13757. }
  13758. }
  13759. }
  13760. #endif
  13761. #ifdef WITH_FAST
  13762. soap->labidx = 0; /* use look-aside buffer */
  13763. #else
  13764. if (soap_alloc_block(soap) == NULL)
  13765. return NULL;
  13766. #endif
  13767. for (;;) {
  13768. #ifdef WITH_FAST
  13769. size_t k;
  13770. if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
  13771. return NULL;
  13772. s = soap->labbuf + soap->labidx; /* space to populate */
  13773. k = soap->lablen - soap->labidx; /* number of bytes available */
  13774. soap->labidx = soap->lablen; /* claim this space */
  13775. #else
  13776. size_t k = SOAP_BLKLEN;
  13777. s = (char*)soap_push_block(soap, NULL, k);
  13778. if (!s)
  13779. return NULL;
  13780. #endif
  13781. for (i = 0; i < k; i++) {
  13782. if (m > 0) {
  13783. *s++ = *t++; /* copy multibyte characters */
  13784. m--;
  13785. continue;
  13786. }
  13787. #ifndef WITH_CDATA
  13788. if (flag <= 0)
  13789. c = soap_getchar(soap);
  13790. else
  13791. #endif
  13792. {
  13793. c = soap_getutf8(soap);
  13794. if ((soap->mode & SOAP_C_UTFSTRING)) {
  13795. if (c >= 0x80 || (c < SOAP_AP && c >= -0x7FFFFF80)) {
  13796. c &= 0x7FFFFFFF;
  13797. t = buf;
  13798. if (c < 0x0800) {
  13799. *t++ = (char) (0xC0 | ((c >> 6) & 0x1F));
  13800. } else {
  13801. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  13802. if (!((c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF)))
  13803. c = SOAP_UNKNOWN_UNICODE_CHAR;
  13804. #endif
  13805. if (c < 0x010000) {
  13806. *t++ = (char) (0xE0 | ((c >> 12) & 0x0F));
  13807. } else {
  13808. if (c < 0x200000) {
  13809. *t++ = (char) (0xF0 | ((c >> 18) & 0x07));
  13810. } else {
  13811. if (c < 0x04000000) {
  13812. *t++ = (char) (0xF8 | ((c >> 24) & 0x03));
  13813. } else {
  13814. *t++ = (char) (0xFC | ((c >> 30) & 0x01));
  13815. *t++ = (char) (0x80 | ((c >> 24) & 0x3F));
  13816. }
  13817. *t++ = (char) (0x80 | ((c >> 18) & 0x3F));
  13818. }
  13819. *t++ = (char) (0x80 | ((c >> 12) & 0x3F));
  13820. }
  13821. *t++ = (char) (0x80 | ((c >> 6) & 0x3F));
  13822. }
  13823. *t++ = (char) (0x80 | (c & 0x3F));
  13824. m = (int) (t - buf) - 1;
  13825. t = buf;
  13826. *s++ = *t++;
  13827. l++;
  13828. if (maxlen >= 0 && l > (size_t) maxlen) {
  13829. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
  13830. soap->error = SOAP_LENGTH;
  13831. return NULL;
  13832. }
  13833. continue;
  13834. }
  13835. }
  13836. }
  13837. switch (c) {
  13838. case SOAP_TT:
  13839. if (n == 0)
  13840. goto end;
  13841. n--;
  13842. *s++ = '<';
  13843. t = (char *) "/";
  13844. m = 1;
  13845. break;
  13846. case SOAP_LT:
  13847. if (flag == 3 || (f && n == 0))
  13848. goto end;
  13849. n++;
  13850. *s++ = '<';
  13851. break;
  13852. case SOAP_GT:
  13853. *s++ = '>';
  13854. break;
  13855. case SOAP_QT:
  13856. *s++ = '"';
  13857. break;
  13858. case SOAP_AP:
  13859. *s++ = '\'';
  13860. break;
  13861. case '/':
  13862. if (n > 0) {
  13863. if (flag > 0) {
  13864. c = soap_get(soap);
  13865. if (c == SOAP_GT)
  13866. n--;
  13867. } else {
  13868. c = soap_getchar(soap);
  13869. if (c == '>')
  13870. n--;
  13871. }
  13872. soap_unget(soap, c);
  13873. }
  13874. *s++ = '/';
  13875. break;
  13876. case (soap_wchar) ('<' | 0x80000000):
  13877. if (flag > 0) {
  13878. *s++ = '<';
  13879. } else {
  13880. *s++ = '&';
  13881. t = (char *) "lt;";
  13882. m = 3;
  13883. }
  13884. break;
  13885. case (soap_wchar) ('>' | 0x80000000):
  13886. if (flag > 0) {
  13887. *s++ = '>';
  13888. } else {
  13889. *s++ = '&';
  13890. t = (char *) "gt;";
  13891. m = 3;
  13892. }
  13893. break;
  13894. case (soap_wchar) ('&' | 0x80000000):
  13895. if (flag > 0) {
  13896. *s++ = '&';
  13897. } else {
  13898. *s++ = '&';
  13899. t = (char *) "amp;";
  13900. m = 4;
  13901. }
  13902. break;
  13903. case (soap_wchar) ('"' | 0x80000000):
  13904. if (flag > 0) {
  13905. *s++ = '"';
  13906. } else {
  13907. *s++ = '&';
  13908. t = (char *) "quot;";
  13909. m = 5;
  13910. }
  13911. break;
  13912. case (soap_wchar) ('\'' | 0x80000000):
  13913. if (flag > 0) {
  13914. *s++ = '\'';
  13915. } else {
  13916. *s++ = '&';
  13917. t = (char *) "apos;";
  13918. m = 5;
  13919. }
  13920. break;
  13921. default:
  13922. if ((int) c == EOF)
  13923. goto end;
  13924. #ifndef WITH_CDATA
  13925. if (c == '<')
  13926. {
  13927. c = soap_getchar(soap);
  13928. soap_unget(soap, c);
  13929. if (c == '/')
  13930. {
  13931. c = SOAP_TT;
  13932. if (n == 0)
  13933. goto end;
  13934. n--;
  13935. }
  13936. else
  13937. {
  13938. n++;
  13939. }
  13940. *s++ = '<';
  13941. }
  13942. else
  13943. #endif
  13944. #ifndef WITH_LEANER
  13945. #ifdef HAVE_WCTOMB
  13946. if ((soap->mode & SOAP_C_MBSTRING)) {
  13947. #if defined(WIN32) && !defined(CYGWIN) && !defined(__MINGW32__) && !defined(__MINGW64__) && !defined(__BORLANDC__)
  13948. m = 0;
  13949. wctomb_s(&m, buf, sizeof(buf), (wchar_t)(c & 0x7FFFFFFF));
  13950. #else
  13951. m = wctomb(buf, (wchar_t) (c & 0x7FFFFFFF));
  13952. #endif
  13953. if (m >= 1 && m <= (int) MB_CUR_MAX) {
  13954. t = buf;
  13955. *s++ = *t++;
  13956. m--;
  13957. } else {
  13958. *s++ = SOAP_UNKNOWN_CHAR;
  13959. m = 0;
  13960. }
  13961. } else
  13962. #endif
  13963. #endif
  13964. *s++ = (char) (c & 0xFF);
  13965. }
  13966. l++;
  13967. if (maxlen >= 0 && l > (size_t) maxlen) {
  13968. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
  13969. soap->error = SOAP_LENGTH;
  13970. return NULL;
  13971. }
  13972. }
  13973. }
  13974. end:
  13975. soap_unget(soap, c);
  13976. *s = '\0';
  13977. #ifdef WITH_FAST
  13978. t = soap_strdup(soap, soap->labbuf);
  13979. if (!t)
  13980. return NULL;
  13981. #else
  13982. soap_size_block(soap, NULL, i + 1);
  13983. t = soap_save_block(soap, NULL, NULL, 0);
  13984. #endif
  13985. if (minlen > 0 && l < (size_t) minlen) {
  13986. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too short: %lu chars, minlen=%ld\n", (unsigned long) l, minlen));
  13987. soap->error = SOAP_LENGTH;
  13988. return NULL;
  13989. }
  13990. #ifdef WITH_DOM
  13991. if ((soap->mode & SOAP_XML_DOM) && soap->dom && *t)
  13992. {
  13993. if (flag > 0)
  13994. soap->dom->text = t;
  13995. else
  13996. soap->dom->code = t;
  13997. }
  13998. #endif
  13999. if (flag == 2) {
  14000. if (soap_s2QName(soap, t, &t, minlen, maxlen, pattern))
  14001. return NULL;
  14002. } else if (flag >= 4 && t) {
  14003. t = soap_collapse(soap, t, flag, 1);
  14004. }
  14005. #ifndef WITH_LEANER
  14006. else if (pattern && soap->fsvalidate) {
  14007. soap->error = soap->fsvalidate(soap, pattern, t);
  14008. if (soap->error)
  14009. return NULL;
  14010. }
  14011. #endif
  14012. return t;
  14013. }
  14014. /******************************************************************************/
  14015. #ifndef WITH_LEANER
  14016. SOAP_FMAC1
  14017. int
  14018. SOAP_FMAC2
  14019. soap_wstring_out(struct soap *soap, const wchar_t *s, int flag) {
  14020. const char *t;
  14021. char tmp;
  14022. soap_wchar c;
  14023. #ifdef WITH_DOM
  14024. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  14025. {
  14026. soap->dom->text = soap_wchar2s(soap, s);
  14027. return SOAP_OK;
  14028. }
  14029. #endif
  14030. while ((c = *s++)) {
  14031. switch (c) {
  14032. case 0x09:
  14033. if (flag)
  14034. t = "&#x9;";
  14035. else
  14036. t = "\t";
  14037. break;
  14038. case 0x0A:
  14039. if (flag || !(soap->mode & SOAP_XML_CANONICAL))
  14040. t = "&#xA;";
  14041. else
  14042. t = "\n";
  14043. break;
  14044. case 0x0D:
  14045. t = "&#xD;";
  14046. break;
  14047. case '&':
  14048. t = "&amp;";
  14049. break;
  14050. case '<':
  14051. t = "&lt;";
  14052. break;
  14053. case '>':
  14054. if (flag)
  14055. t = ">";
  14056. else
  14057. t = "&gt;";
  14058. break;
  14059. case '"':
  14060. if (flag)
  14061. t = "&quot;";
  14062. else
  14063. t = "\"";
  14064. break;
  14065. default:
  14066. if (c >= 0x20 && c < 0x80) {
  14067. tmp = (char) c;
  14068. if (soap_send_raw(soap, &tmp, 1))
  14069. return soap->error;
  14070. } else {
  14071. /* check for UTF16 encoding when wchar_t is too small to hold UCS */
  14072. if (sizeof(wchar_t) < 4 && (c & 0xFC00) == 0xD800) {
  14073. soap_wchar d = *s;
  14074. if ((d & 0xFC00) == 0xDC00) {
  14075. c = ((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000;
  14076. s++;
  14077. }
  14078. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  14079. else
  14080. {
  14081. c = SOAP_UNKNOWN_UNICODE_CHAR; /* Malformed UTF-16 */
  14082. }
  14083. #endif
  14084. }
  14085. if (soap_pututf8(soap, (unsigned long) c))
  14086. return soap->error;
  14087. }
  14088. continue;
  14089. }
  14090. if (soap_send(soap, t))
  14091. return soap->error;
  14092. }
  14093. return SOAP_OK;
  14094. }
  14095. #endif
  14096. /******************************************************************************/
  14097. #ifndef WITH_LEANER
  14098. SOAP_FMAC1
  14099. wchar_t *
  14100. SOAP_FMAC2
  14101. soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen, const char *pattern) {
  14102. wchar_t *s;
  14103. int i, n = 0, f = 0;
  14104. ULONG64 l = 0;
  14105. soap_wchar c;
  14106. char *t = NULL;
  14107. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reading wide string content\n"));
  14108. if (maxlen < 0 && soap->maxlength > 0)
  14109. maxlen = soap->maxlength;
  14110. if (flag <= 0 && soap->peeked && *soap->tag) {
  14111. #ifndef WITH_LEAN
  14112. struct soap_attribute *tp;
  14113. t = soap->tmpbuf;
  14114. *t = '<';
  14115. soap_strcpy(t + 1, sizeof(soap->tmpbuf) - 1, soap->tag);
  14116. t += strlen(t);
  14117. for (tp = soap->attributes; tp; tp = tp->next) {
  14118. if (tp->visible) {
  14119. size_t k = strlen(tp->name);
  14120. if (t + k + 1 >= soap->tmpbuf + sizeof(soap->tmpbuf))
  14121. break;
  14122. *t++ = ' ';
  14123. (void) soap_strncpy(t, sizeof(soap->tmpbuf) - (t - soap->tmpbuf), tp->name, k);
  14124. t += k;
  14125. if (tp->value) {
  14126. k = strlen(tp->value);
  14127. if (t + k + 3 >= soap->tmpbuf + sizeof(soap->tmpbuf))
  14128. break;
  14129. *t++ = '=';
  14130. *t++ = '"';
  14131. (void) soap_strncpy(t, sizeof(soap->tmpbuf) - (t - soap->tmpbuf), tp->value, k);
  14132. t += k;
  14133. *t++ = '"';
  14134. }
  14135. }
  14136. }
  14137. if (!soap->body)
  14138. *t++ = '/';
  14139. *t++ = '>';
  14140. *t = '\0';
  14141. t = soap->tmpbuf;
  14142. #endif
  14143. if (soap->body)
  14144. n = 1;
  14145. f = 1;
  14146. soap->peeked = 0;
  14147. }
  14148. if (soap_alloc_block(soap) == NULL)
  14149. return NULL;
  14150. for (;;) {
  14151. s = (wchar_t *) soap_push_block(soap, NULL, sizeof(wchar_t) * SOAP_BLKLEN);
  14152. if (!s)
  14153. return NULL;
  14154. for (i = 0; i < SOAP_BLKLEN; i++) {
  14155. if (t) {
  14156. *s++ = (wchar_t) *t++;
  14157. if (!*t)
  14158. t = NULL;
  14159. continue;
  14160. }
  14161. c = soap_getutf8(soap);
  14162. switch (c) {
  14163. case SOAP_TT:
  14164. if (n == 0)
  14165. goto end;
  14166. n--;
  14167. *s++ = L'<';
  14168. soap_unget(soap, '/');
  14169. break;
  14170. case SOAP_LT:
  14171. if (flag == 3 || (f && n == 0))
  14172. goto end;
  14173. n++;
  14174. *s++ = L'<';
  14175. break;
  14176. case SOAP_GT:
  14177. *s++ = L'>';
  14178. break;
  14179. case SOAP_QT:
  14180. *s++ = L'"';
  14181. break;
  14182. case SOAP_AP:
  14183. *s++ = L'\'';
  14184. break;
  14185. case '/':
  14186. if (n > 0) {
  14187. c = soap_getutf8(soap);
  14188. if (c == SOAP_GT)
  14189. n--;
  14190. soap_unget(soap, c);
  14191. }
  14192. *s++ = L'/';
  14193. break;
  14194. case '<':
  14195. if (flag > 0) {
  14196. *s++ = L'<';
  14197. } else {
  14198. *s++ = L'&';
  14199. t = (char *) "lt;";
  14200. }
  14201. break;
  14202. case '>':
  14203. if (flag > 0) {
  14204. *s++ = L'>';
  14205. } else {
  14206. *s++ = (wchar_t) '&';
  14207. t = (char *) "gt;";
  14208. }
  14209. break;
  14210. case '"':
  14211. if (flag > 0) {
  14212. *s++ = L'"';
  14213. } else {
  14214. *s++ = L'&';
  14215. t = (char *) "quot;";
  14216. }
  14217. break;
  14218. default:
  14219. if ((int) c == EOF)
  14220. goto end;
  14221. /* use UTF16 encoding when wchar_t is too small to hold UCS */
  14222. if (sizeof(wchar_t) < 4 && c > 0xFFFF) {
  14223. soap_wchar c1, c2;
  14224. c1 = 0xD800 - (0x10000 >> 10) + (c >> 10);
  14225. c2 = 0xDC00 + (c & 0x3FF);
  14226. c = c1;
  14227. soap_unget(soap, c2);
  14228. }
  14229. *s++ = (wchar_t) (c & 0x7FFFFFFF);
  14230. }
  14231. l++;
  14232. if (maxlen >= 0 && l > (size_t) maxlen) {
  14233. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
  14234. soap->error = SOAP_LENGTH;
  14235. return NULL;
  14236. }
  14237. }
  14238. }
  14239. end:
  14240. soap_unget(soap, c);
  14241. *s = L'\0';
  14242. soap_size_block(soap, NULL, sizeof(wchar_t) * (i + 1));
  14243. if (minlen > 0 && l < (size_t) minlen) {
  14244. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too short: %lu chars, minlen=%ld\n", (unsigned long) l, minlen));
  14245. soap->error = SOAP_LENGTH;
  14246. return NULL;
  14247. }
  14248. s = (wchar_t *) soap_save_block(soap, NULL, NULL, 0);
  14249. #ifndef WITH_LEAN
  14250. if (flag >= 4 && s)
  14251. s = soap_wcollapse(soap, s, flag, 1);
  14252. #endif
  14253. #ifndef WITH_LEANER
  14254. if (pattern && soap->fwvalidate) {
  14255. soap->error = soap->fwvalidate(soap, pattern, s);
  14256. if (soap->error)
  14257. return NULL;
  14258. }
  14259. #endif
  14260. #ifdef WITH_DOM
  14261. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  14262. soap->dom->text = soap_wchar2s(soap, s);
  14263. #endif
  14264. return s;
  14265. }
  14266. #endif
  14267. /******************************************************************************/
  14268. SOAP_FMAC1
  14269. const char *
  14270. SOAP_FMAC2
  14271. soap_int2s(struct soap *soap, int n) {
  14272. return soap_long2s(soap, (long) n);
  14273. }
  14274. /******************************************************************************/
  14275. SOAP_FMAC1
  14276. int
  14277. SOAP_FMAC2
  14278. soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n) {
  14279. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  14280. || soap_string_out(soap, soap_long2s(soap, (long) *p), 0))
  14281. return soap->error;
  14282. return soap_element_end_out(soap, tag);
  14283. }
  14284. /******************************************************************************/
  14285. SOAP_FMAC1
  14286. int
  14287. SOAP_FMAC2
  14288. soap_s2int(struct soap *soap, const char *s, int *p) {
  14289. if (s) {
  14290. long n;
  14291. char *r;
  14292. if (!*s)
  14293. return soap->error = SOAP_EMPTY;
  14294. #ifndef WITH_NOIO
  14295. #ifndef WITH_LEAN
  14296. soap_reset_errno;
  14297. #endif
  14298. #endif
  14299. n = soap_strtol(s, &r, 10);
  14300. if (s == r || *r
  14301. #ifndef WITH_LEAN
  14302. || n != (int) n
  14303. #endif
  14304. #ifndef WITH_NOIO
  14305. #ifndef WITH_LEAN
  14306. || soap_errno == SOAP_ERANGE
  14307. #endif
  14308. #endif
  14309. )
  14310. soap->error = SOAP_TYPE;
  14311. *p = (int) n;
  14312. }
  14313. return soap->error;
  14314. }
  14315. /******************************************************************************/
  14316. SOAP_FMAC1
  14317. int *
  14318. SOAP_FMAC2
  14319. soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t) {
  14320. if (soap_element_begin_in(soap, tag, 0, NULL))
  14321. return NULL;
  14322. #ifndef WITH_LEAN
  14323. if (*soap->type
  14324. && soap_match_tag(soap, soap->type, type)
  14325. && soap_match_tag(soap, soap->type, ":int")
  14326. && soap_match_tag(soap, soap->type, ":short")
  14327. && soap_match_tag(soap, soap->type, ":byte")) {
  14328. soap->error = SOAP_TYPE;
  14329. soap_revert(soap);
  14330. return NULL;
  14331. }
  14332. #else
  14333. (void)type;
  14334. #endif
  14335. p = (int *) soap_id_enter(soap, soap->id, p, t, sizeof(int), NULL, NULL, NULL, NULL);
  14336. if (!p)
  14337. return NULL;
  14338. if (*soap->href != '#') {
  14339. int err = soap_s2int(soap, soap_value(soap), p);
  14340. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  14341. return NULL;
  14342. } else {
  14343. p = (int *) soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(int), 0, NULL, NULL);
  14344. if (soap->body && soap_element_end_in(soap, tag))
  14345. return NULL;
  14346. }
  14347. return p;
  14348. }
  14349. /******************************************************************************/
  14350. SOAP_FMAC1
  14351. const char *
  14352. SOAP_FMAC2
  14353. soap_long2s(struct soap *soap, long n) {
  14354. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), "%ld", n);
  14355. return soap->tmpbuf;
  14356. }
  14357. /******************************************************************************/
  14358. SOAP_FMAC1
  14359. int
  14360. SOAP_FMAC2
  14361. soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n) {
  14362. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  14363. || soap_string_out(soap, soap_long2s(soap, *p), 0))
  14364. return soap->error;
  14365. return soap_element_end_out(soap, tag);
  14366. }
  14367. /******************************************************************************/
  14368. SOAP_FMAC1
  14369. int
  14370. SOAP_FMAC2
  14371. soap_s2long(struct soap *soap, const char *s, long *p) {
  14372. if (s) {
  14373. char *r;
  14374. if (!*s)
  14375. return soap->error = SOAP_EMPTY;
  14376. #ifndef WITH_NOIO
  14377. #ifndef WITH_LEAN
  14378. soap_reset_errno;
  14379. #endif
  14380. #endif
  14381. *p = soap_strtol(s, &r, 10);
  14382. if (s == r || *r
  14383. #ifndef WITH_NOIO
  14384. #ifndef WITH_LEAN
  14385. || soap_errno == SOAP_ERANGE
  14386. #endif
  14387. #endif
  14388. )
  14389. soap->error = SOAP_TYPE;
  14390. }
  14391. return soap->error;
  14392. }
  14393. /******************************************************************************/
  14394. SOAP_FMAC1
  14395. long *
  14396. SOAP_FMAC2
  14397. soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t) {
  14398. if (soap_element_begin_in(soap, tag, 0, NULL))
  14399. return NULL;
  14400. #ifndef WITH_LEAN
  14401. if (*soap->type
  14402. && soap_match_tag(soap, soap->type, type)
  14403. && soap_match_tag(soap, soap->type, ":int")
  14404. && soap_match_tag(soap, soap->type, ":short")
  14405. && soap_match_tag(soap, soap->type, ":byte")) {
  14406. soap->error = SOAP_TYPE;
  14407. soap_revert(soap);
  14408. return NULL;
  14409. }
  14410. #else
  14411. (void)type;
  14412. #endif
  14413. p = (long *) soap_id_enter(soap, soap->id, p, t, sizeof(long), NULL, NULL, NULL, NULL);
  14414. if (!p)
  14415. return NULL;
  14416. if (*soap->href != '#') {
  14417. int err = soap_s2long(soap, soap_value(soap), p);
  14418. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  14419. return NULL;
  14420. } else {
  14421. p = (long *) soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(long), 0, NULL, NULL);
  14422. if (soap->body && soap_element_end_in(soap, tag))
  14423. return NULL;
  14424. }
  14425. return p;
  14426. }
  14427. /******************************************************************************/
  14428. SOAP_FMAC1
  14429. const char *
  14430. SOAP_FMAC2
  14431. soap_LONG642s(struct soap *soap, LONG64 n) {
  14432. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), SOAP_LONG_FORMAT, n);
  14433. return soap->tmpbuf;
  14434. }
  14435. /******************************************************************************/
  14436. SOAP_FMAC1
  14437. int
  14438. SOAP_FMAC2
  14439. soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n) {
  14440. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  14441. || soap_string_out(soap, soap_LONG642s(soap, *p), 0))
  14442. return soap->error;
  14443. return soap_element_end_out(soap, tag);
  14444. }
  14445. /******************************************************************************/
  14446. SOAP_FMAC1
  14447. int
  14448. SOAP_FMAC2
  14449. soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p) {
  14450. if (s) {
  14451. char *r;
  14452. if (!*s)
  14453. return soap->error = SOAP_EMPTY;
  14454. #ifndef WITH_NOIO
  14455. #ifndef WITH_LEAN
  14456. soap_reset_errno;
  14457. #endif
  14458. #endif
  14459. *p = soap_strtoll(s, &r, 10);
  14460. if (s == r || *r
  14461. #ifndef WITH_NOIO
  14462. #ifndef WITH_LEAN
  14463. || soap_errno == SOAP_ERANGE
  14464. #endif
  14465. #endif
  14466. )
  14467. soap->error = SOAP_TYPE;
  14468. }
  14469. return soap->error;
  14470. }
  14471. /******************************************************************************/
  14472. SOAP_FMAC1
  14473. LONG64 *
  14474. SOAP_FMAC2
  14475. soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t) {
  14476. if (soap_element_begin_in(soap, tag, 0, NULL))
  14477. return NULL;
  14478. #ifndef WITH_LEAN
  14479. if (*soap->type
  14480. && soap_match_tag(soap, soap->type, type)
  14481. && soap_match_tag(soap, soap->type, ":integer")
  14482. && soap_match_tag(soap, soap->type, ":positiveInteger")
  14483. && soap_match_tag(soap, soap->type, ":negativeInteger")
  14484. && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
  14485. && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
  14486. && soap_match_tag(soap, soap->type, ":long")
  14487. && soap_match_tag(soap, soap->type, ":int")
  14488. && soap_match_tag(soap, soap->type, ":short")
  14489. && soap_match_tag(soap, soap->type, ":byte")) {
  14490. soap->error = SOAP_TYPE;
  14491. soap_revert(soap);
  14492. return NULL;
  14493. }
  14494. #else
  14495. (void)type;
  14496. #endif
  14497. p = (LONG64 *) soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), NULL, NULL, NULL, NULL);
  14498. if (!p)
  14499. return NULL;
  14500. if (*soap->href != '#') {
  14501. int err = soap_s2LONG64(soap, soap_value(soap), p);
  14502. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  14503. return NULL;
  14504. } else {
  14505. p = (LONG64 *) soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(LONG64), 0, NULL, NULL);
  14506. if (soap->body && soap_element_end_in(soap, tag))
  14507. return NULL;
  14508. }
  14509. return p;
  14510. }
  14511. /******************************************************************************/
  14512. SOAP_FMAC1
  14513. const char *
  14514. SOAP_FMAC2
  14515. soap_byte2s(struct soap *soap, char n) {
  14516. return soap_long2s(soap, (long) n);
  14517. }
  14518. /******************************************************************************/
  14519. SOAP_FMAC1
  14520. int
  14521. SOAP_FMAC2
  14522. soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n) {
  14523. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  14524. || soap_string_out(soap, soap_long2s(soap, (long) *p), 0))
  14525. return soap->error;
  14526. return soap_element_end_out(soap, tag);
  14527. }
  14528. /******************************************************************************/
  14529. SOAP_FMAC1
  14530. int
  14531. SOAP_FMAC2
  14532. soap_s2byte(struct soap *soap, const char *s, char *p) {
  14533. if (s) {
  14534. long n;
  14535. char *r;
  14536. if (!*s)
  14537. return soap->error = SOAP_EMPTY;
  14538. n = soap_strtol(s, &r, 10);
  14539. if (s == r || *r || n < -128 || n > 127)
  14540. soap->error = SOAP_TYPE;
  14541. *p = (char) n;
  14542. }
  14543. return soap->error;
  14544. }
  14545. /******************************************************************************/
  14546. SOAP_FMAC1
  14547. char *
  14548. SOAP_FMAC2
  14549. soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t) {
  14550. if (soap_element_begin_in(soap, tag, 0, NULL))
  14551. return NULL;
  14552. #ifndef WITH_LEAN
  14553. if (*soap->type
  14554. && soap_match_tag(soap, soap->type, type)
  14555. && soap_match_tag(soap, soap->type, ":byte")) {
  14556. soap->error = SOAP_TYPE;
  14557. soap_revert(soap);
  14558. return NULL;
  14559. }
  14560. #else
  14561. (void)type;
  14562. #endif
  14563. p = (char *) soap_id_enter(soap, soap->id, p, t, sizeof(char), NULL, NULL, NULL, NULL);
  14564. if (!p)
  14565. return NULL;
  14566. if (*soap->href != '#') {
  14567. int err = soap_s2byte(soap, soap_value(soap), p);
  14568. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  14569. return NULL;
  14570. } else {
  14571. p = (char *) soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(char), 0, NULL, NULL);
  14572. if (soap->body && soap_element_end_in(soap, tag))
  14573. return NULL;
  14574. }
  14575. return p;
  14576. }
  14577. /******************************************************************************/
  14578. SOAP_FMAC1
  14579. const char *
  14580. SOAP_FMAC2
  14581. soap_short2s(struct soap *soap, short n) {
  14582. return soap_long2s(soap, (long) n);
  14583. }
  14584. /******************************************************************************/
  14585. SOAP_FMAC1
  14586. int
  14587. SOAP_FMAC2
  14588. soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n) {
  14589. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  14590. || soap_string_out(soap, soap_long2s(soap, (long) *p), 0))
  14591. return soap->error;
  14592. return soap_element_end_out(soap, tag);
  14593. }
  14594. /******************************************************************************/
  14595. SOAP_FMAC1
  14596. int
  14597. SOAP_FMAC2
  14598. soap_s2short(struct soap *soap, const char *s, short *p) {
  14599. if (s) {
  14600. long n;
  14601. char *r;
  14602. if (!*s)
  14603. return soap->error = SOAP_EMPTY;
  14604. n = soap_strtol(s, &r, 10);
  14605. if (s == r || *r || n < -32768 || n > 32767)
  14606. soap->error = SOAP_TYPE;
  14607. *p = (short) n;
  14608. }
  14609. return soap->error;
  14610. }
  14611. /******************************************************************************/
  14612. SOAP_FMAC1
  14613. short *
  14614. SOAP_FMAC2
  14615. soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t) {
  14616. if (soap_element_begin_in(soap, tag, 0, NULL))
  14617. return NULL;
  14618. #ifndef WITH_LEAN
  14619. if (*soap->type
  14620. && soap_match_tag(soap, soap->type, type)
  14621. && soap_match_tag(soap, soap->type, ":short")
  14622. && soap_match_tag(soap, soap->type, ":byte")) {
  14623. soap->error = SOAP_TYPE;
  14624. soap_revert(soap);
  14625. return NULL;
  14626. }
  14627. #else
  14628. (void)type;
  14629. #endif
  14630. p = (short *) soap_id_enter(soap, soap->id, p, t, sizeof(short), NULL, NULL, NULL, NULL);
  14631. if (!p)
  14632. return NULL;
  14633. if (*soap->href != '#') {
  14634. int err = soap_s2short(soap, soap_value(soap), p);
  14635. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  14636. return NULL;
  14637. } else {
  14638. p = (short *) soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(short), 0, NULL, NULL);
  14639. if (soap->body && soap_element_end_in(soap, tag))
  14640. return NULL;
  14641. }
  14642. return p;
  14643. }
  14644. /******************************************************************************/
  14645. SOAP_FMAC1
  14646. const char *
  14647. SOAP_FMAC2
  14648. soap_float2s(struct soap *soap, float n) {
  14649. #if defined(WITH_C_LOCALE)
  14650. # if !defined(WIN32)
  14651. SOAP_LOCALE_T locale;
  14652. # endif
  14653. #else
  14654. char *s;
  14655. #endif
  14656. if (soap_isnan((double) n))
  14657. return "NaN";
  14658. if (soap_ispinff(n))
  14659. return "INF";
  14660. if (soap_isninff(n))
  14661. return "-INF";
  14662. #if defined(WITH_C_LOCALE)
  14663. # ifdef WIN32
  14664. _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->float_format, SOAP_LOCALE(soap), n);
  14665. # else
  14666. locale = uselocale(SOAP_LOCALE(soap));
  14667. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), soap->float_format, n);
  14668. uselocale(locale);
  14669. # endif
  14670. #else
  14671. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), soap->float_format, n);
  14672. s = strchr(soap->tmpbuf, ','); /* convert decimal comma to DP */
  14673. if (s)
  14674. *s = '.';
  14675. #endif
  14676. return soap->tmpbuf;
  14677. }
  14678. /******************************************************************************/
  14679. SOAP_FMAC1
  14680. int
  14681. SOAP_FMAC2
  14682. soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n) {
  14683. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  14684. || soap_string_out(soap, soap_float2s(soap, *p), 0))
  14685. return soap->error;
  14686. return soap_element_end_out(soap, tag);
  14687. }
  14688. /******************************************************************************/
  14689. SOAP_FMAC1
  14690. int
  14691. SOAP_FMAC2
  14692. soap_s2float(struct soap *soap, const char *s, float *p) {
  14693. if (s) {
  14694. if (!*s)
  14695. return soap->error = SOAP_EMPTY;
  14696. if (!soap_tag_cmp(s, "INF")) {
  14697. *p = FLT_PINFTY;
  14698. } else if (!soap_tag_cmp(s, "+INF")) {
  14699. *p = FLT_PINFTY;
  14700. } else if (!soap_tag_cmp(s, "-INF")) {
  14701. *p = FLT_NINFTY;
  14702. } else if (!soap_tag_cmp(s, "NaN")) {
  14703. *p = FLT_NAN;
  14704. } else {
  14705. /* On some systems strtof requires -std=c99 or does not even link: so we try strtod first */
  14706. #if defined(WITH_C_LOCALE)
  14707. # if defined(HAVE_STRTOD_L)
  14708. char *r;
  14709. # ifdef WIN32
  14710. *p = (float)_strtod_l(s, &r, SOAP_LOCALE(soap));
  14711. # else
  14712. *p = (float) strtod_l(s, &r, SOAP_LOCALE(soap));
  14713. # endif
  14714. if (*r)
  14715. soap->error = SOAP_TYPE;
  14716. # elif defined(HAVE_STRTOF_L)
  14717. char *r;
  14718. *p = strtof_l((char*)s, &r, SOAP_LOCALE(soap));
  14719. if (*r)
  14720. soap->error = SOAP_TYPE;
  14721. # elif defined(HAVE_SSCANF_L)
  14722. double n;
  14723. if (sscanf_l(s, SOAP_LOCALE(soap), "%lf", &n) != 1)
  14724. soap->error = SOAP_TYPE;
  14725. *p = (float)n;
  14726. # elif defined(HAVE_STRTOD)
  14727. char *r;
  14728. SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap));
  14729. *p = (float)strtod((char*)s, &r);
  14730. uselocale(locale);
  14731. if (*r)
  14732. soap->error = SOAP_TYPE;
  14733. # elif defined(HAVE_STRTOF)
  14734. char *r;
  14735. SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap));
  14736. *p = strtof((char*)s, &r);
  14737. uselocale(locale);
  14738. if (*r)
  14739. soap->error = SOAP_TYPE;
  14740. # elif defined(HAVE_SSCANF)
  14741. double n;
  14742. SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap));
  14743. if (sscanf(s, "%lf", &n) != 1)
  14744. soap->error = SOAP_TYPE;
  14745. uselocale(locale);
  14746. *p = (float)n;
  14747. # else
  14748. soap->error = SOAP_TYPE;
  14749. # endif
  14750. #elif defined(HAVE_STRTOD)
  14751. char *r;
  14752. *p = (float)strtod(s, &r);
  14753. if (*r)
  14754. soap->error = SOAP_TYPE;
  14755. #elif defined(HAVE_STRTOF)
  14756. char *r;
  14757. *p = strtof((char*)s, &r);
  14758. if (*r)
  14759. soap->error = SOAP_TYPE;
  14760. #elif defined(HAVE_SSCANF)
  14761. double n;
  14762. if (sscanf(s, "%lf", &n) != 1)
  14763. soap->error = SOAP_TYPE;
  14764. *p = (float)n;
  14765. #else
  14766. soap->error = SOAP_TYPE;
  14767. #endif
  14768. }
  14769. }
  14770. return soap->error;
  14771. }
  14772. /******************************************************************************/
  14773. #ifndef WITH_LEAN
  14774. static int soap_isnumeric(struct soap *soap, const char *type) {
  14775. if (soap_match_tag(soap, soap->type, type)
  14776. && soap_match_tag(soap, soap->type, ":float")
  14777. && soap_match_tag(soap, soap->type, ":double")
  14778. && soap_match_tag(soap, soap->type, ":decimal")
  14779. && soap_match_tag(soap, soap->type, ":integer")
  14780. && soap_match_tag(soap, soap->type, ":positiveInteger")
  14781. && soap_match_tag(soap, soap->type, ":negativeInteger")
  14782. && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
  14783. && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
  14784. && soap_match_tag(soap, soap->type, ":long")
  14785. && soap_match_tag(soap, soap->type, ":int")
  14786. && soap_match_tag(soap, soap->type, ":short")
  14787. && soap_match_tag(soap, soap->type, ":byte")
  14788. && soap_match_tag(soap, soap->type, ":unsignedLong")
  14789. && soap_match_tag(soap, soap->type, ":unsignedInt")
  14790. && soap_match_tag(soap, soap->type, ":unsignedShort")
  14791. && soap_match_tag(soap, soap->type, ":unsignedByte")) {
  14792. soap->error = SOAP_TYPE;
  14793. soap_revert(soap);
  14794. return SOAP_ERR;
  14795. }
  14796. return SOAP_OK;
  14797. }
  14798. #endif
  14799. /******************************************************************************/
  14800. SOAP_FMAC1
  14801. float *
  14802. SOAP_FMAC2
  14803. soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t) {
  14804. if (soap_element_begin_in(soap, tag, 0, NULL))
  14805. return NULL;
  14806. #ifndef WITH_LEAN
  14807. if (*soap->type != '\0' && soap_isnumeric(soap, type))
  14808. return NULL;
  14809. #else
  14810. (void)type;
  14811. #endif
  14812. p = (float *) soap_id_enter(soap, soap->id, p, t, sizeof(float), NULL, NULL, NULL, NULL);
  14813. if (!p)
  14814. return NULL;
  14815. if (*soap->href != '#') {
  14816. int err = soap_s2float(soap, soap_value(soap), p);
  14817. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  14818. return NULL;
  14819. } else {
  14820. p = (float *) soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(float), 0, NULL, NULL);
  14821. if (soap->body && soap_element_end_in(soap, tag))
  14822. return NULL;
  14823. }
  14824. return p;
  14825. }
  14826. /******************************************************************************/
  14827. SOAP_FMAC1
  14828. const char *
  14829. SOAP_FMAC2
  14830. soap_double2s(struct soap *soap, double n) {
  14831. #if defined(WITH_C_LOCALE)
  14832. # if !defined(WIN32)
  14833. SOAP_LOCALE_T locale;
  14834. # endif
  14835. #else
  14836. char *s;
  14837. #endif
  14838. if (soap_isnan(n))
  14839. return "NaN";
  14840. if (soap_ispinfd(n))
  14841. return "INF";
  14842. if (soap_isninfd(n))
  14843. return "-INF";
  14844. #if defined(WITH_C_LOCALE)
  14845. # ifdef WIN32
  14846. _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->double_format, SOAP_LOCALE(soap), n);
  14847. # else
  14848. locale = uselocale(SOAP_LOCALE(soap));
  14849. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 40), soap->double_format, n);
  14850. uselocale(locale);
  14851. # endif
  14852. #else
  14853. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 40), soap->double_format, n);
  14854. s = strchr(soap->tmpbuf, ','); /* convert decimal comma to DP */
  14855. if (s)
  14856. *s = '.';
  14857. #endif
  14858. return soap->tmpbuf;
  14859. }
  14860. /******************************************************************************/
  14861. SOAP_FMAC1
  14862. int
  14863. SOAP_FMAC2
  14864. soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n) {
  14865. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  14866. || soap_string_out(soap, soap_double2s(soap, *p), 0))
  14867. return soap->error;
  14868. return soap_element_end_out(soap, tag);
  14869. }
  14870. /******************************************************************************/
  14871. SOAP_FMAC1
  14872. int
  14873. SOAP_FMAC2
  14874. soap_s2double(struct soap *soap, const char *s, double *p) {
  14875. if (s) {
  14876. if (!*s)
  14877. return soap->error = SOAP_EMPTY;
  14878. if (!soap_tag_cmp(s, "INF")) {
  14879. *p = DBL_PINFTY;
  14880. } else if (!soap_tag_cmp(s, "+INF")) {
  14881. *p = DBL_PINFTY;
  14882. } else if (!soap_tag_cmp(s, "-INF")) {
  14883. *p = DBL_NINFTY;
  14884. } else if (!soap_tag_cmp(s, "NaN")) {
  14885. *p = DBL_NAN;
  14886. } else {
  14887. #if defined(WITH_C_LOCALE)
  14888. # if defined(HAVE_STRTOD_L)
  14889. char *r;
  14890. # ifdef WIN32
  14891. *p = _strtod_l(s, &r, SOAP_LOCALE(soap));
  14892. # else
  14893. *p = strtod_l(s, &r, SOAP_LOCALE(soap));
  14894. # endif
  14895. if (*r)
  14896. soap->error = SOAP_TYPE;
  14897. # elif defined(HAVE_STRTOD)
  14898. char *r;
  14899. SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap));
  14900. *p = strtod(s, &r);
  14901. uselocale(locale);
  14902. if (*r)
  14903. soap->error = SOAP_TYPE;
  14904. # elif defined(HAVE_SSCANF_L)
  14905. SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap));
  14906. if (sscanf_l(s, SOAP_LOCALE(soap), "%lf", p) != 1)
  14907. soap->error = SOAP_TYPE;
  14908. uselocale(locale);
  14909. # else
  14910. soap->error = SOAP_TYPE;
  14911. # endif
  14912. #elif defined(HAVE_STRTOD)
  14913. char *r;
  14914. *p = strtod(s, &r);
  14915. if (*r)
  14916. soap->error = SOAP_TYPE;
  14917. #elif defined(HAVE_SSCANF)
  14918. if (sscanf(s, "%lf", p) != 1)
  14919. soap->error = SOAP_TYPE;
  14920. #else
  14921. soap->error = SOAP_TYPE;
  14922. #endif
  14923. }
  14924. }
  14925. return soap->error;
  14926. }
  14927. /******************************************************************************/
  14928. SOAP_FMAC1
  14929. double *
  14930. SOAP_FMAC2
  14931. soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t) {
  14932. if (soap_element_begin_in(soap, tag, 0, NULL))
  14933. return NULL;
  14934. #ifndef WITH_LEAN
  14935. if (*soap->type != '\0' && soap_isnumeric(soap, type))
  14936. return NULL;
  14937. #else
  14938. (void)type;
  14939. #endif
  14940. p = (double *) soap_id_enter(soap, soap->id, p, t, sizeof(double), NULL, NULL, NULL, NULL);
  14941. if (!p)
  14942. return NULL;
  14943. if (*soap->href != '#') {
  14944. int err = soap_s2double(soap, soap_value(soap), p);
  14945. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  14946. return NULL;
  14947. } else {
  14948. p = (double *) soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(double), 0, NULL, NULL);
  14949. if (soap->body && soap_element_end_in(soap, tag))
  14950. return NULL;
  14951. }
  14952. return p;
  14953. }
  14954. /******************************************************************************/
  14955. SOAP_FMAC1
  14956. const char *
  14957. SOAP_FMAC2
  14958. soap_unsignedByte2s(struct soap *soap, unsigned char n) {
  14959. return soap_unsignedLong2s(soap, (unsigned long) n);
  14960. }
  14961. /******************************************************************************/
  14962. SOAP_FMAC1
  14963. int
  14964. SOAP_FMAC2
  14965. soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n) {
  14966. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  14967. || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long) *p), 0))
  14968. return soap->error;
  14969. return soap_element_end_out(soap, tag);
  14970. }
  14971. /******************************************************************************/
  14972. SOAP_FMAC1
  14973. int
  14974. SOAP_FMAC2
  14975. soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p) {
  14976. if (s) {
  14977. long n;
  14978. char *r;
  14979. if (!*s)
  14980. return soap->error = SOAP_EMPTY;
  14981. n = soap_strtol(s, &r, 10);
  14982. if (s == r || *r || n < 0 || n > 255)
  14983. soap->error = SOAP_TYPE;
  14984. *p = (unsigned char) n;
  14985. }
  14986. return soap->error;
  14987. }
  14988. /******************************************************************************/
  14989. SOAP_FMAC1
  14990. unsigned char *
  14991. SOAP_FMAC2
  14992. soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t) {
  14993. if (soap_element_begin_in(soap, tag, 0, NULL))
  14994. return NULL;
  14995. #ifndef WITH_LEAN
  14996. if (*soap->type
  14997. && soap_match_tag(soap, soap->type, type)
  14998. && soap_match_tag(soap, soap->type, ":unsignedByte")) {
  14999. soap->error = SOAP_TYPE;
  15000. soap_revert(soap);
  15001. return NULL;
  15002. }
  15003. #else
  15004. (void)type;
  15005. #endif
  15006. p = (unsigned char *) soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), NULL, NULL, NULL, NULL);
  15007. if (!p)
  15008. return NULL;
  15009. if (*soap->href != '#') {
  15010. int err = soap_s2unsignedByte(soap, soap_value(soap), p);
  15011. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  15012. return NULL;
  15013. } else {
  15014. p = (unsigned char *) soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(unsigned char), 0, NULL, NULL);
  15015. if (soap->body && soap_element_end_in(soap, tag))
  15016. return NULL;
  15017. }
  15018. return p;
  15019. }
  15020. /******************************************************************************/
  15021. SOAP_FMAC1
  15022. const char *
  15023. SOAP_FMAC2
  15024. soap_unsignedShort2s(struct soap *soap, unsigned short n) {
  15025. return soap_unsignedLong2s(soap, (unsigned long) n);
  15026. }
  15027. /******************************************************************************/
  15028. SOAP_FMAC1
  15029. int
  15030. SOAP_FMAC2
  15031. soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n) {
  15032. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  15033. || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long) *p), 0))
  15034. return soap->error;
  15035. return soap_element_end_out(soap, tag);
  15036. }
  15037. /******************************************************************************/
  15038. SOAP_FMAC1
  15039. int
  15040. SOAP_FMAC2
  15041. soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p) {
  15042. if (s) {
  15043. long n;
  15044. char *r;
  15045. if (!*s)
  15046. return soap->error = SOAP_EMPTY;
  15047. n = soap_strtol(s, &r, 10);
  15048. if (s == r || *r || n < 0 || n > 65535)
  15049. soap->error = SOAP_TYPE;
  15050. *p = (unsigned short) n;
  15051. }
  15052. return soap->error;
  15053. }
  15054. /******************************************************************************/
  15055. SOAP_FMAC1
  15056. unsigned short *
  15057. SOAP_FMAC2
  15058. soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t) {
  15059. if (soap_element_begin_in(soap, tag, 0, NULL))
  15060. return NULL;
  15061. #ifndef WITH_LEAN
  15062. if (*soap->type
  15063. && soap_match_tag(soap, soap->type, type)
  15064. && soap_match_tag(soap, soap->type, ":unsignedShort")
  15065. && soap_match_tag(soap, soap->type, ":unsignedByte")) {
  15066. soap->error = SOAP_TYPE;
  15067. soap_revert(soap);
  15068. return NULL;
  15069. }
  15070. #else
  15071. (void)type;
  15072. #endif
  15073. p = (unsigned short *) soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), NULL, NULL, NULL, NULL);
  15074. if (!p)
  15075. return NULL;
  15076. if (*soap->href != '#') {
  15077. int err = soap_s2unsignedShort(soap, soap_value(soap), p);
  15078. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  15079. return NULL;
  15080. } else {
  15081. p = (unsigned short *) soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(unsigned short), 0, NULL, NULL);
  15082. if (soap->body && soap_element_end_in(soap, tag))
  15083. return NULL;
  15084. }
  15085. return p;
  15086. }
  15087. /******************************************************************************/
  15088. SOAP_FMAC1
  15089. const char *
  15090. SOAP_FMAC2
  15091. soap_unsignedInt2s(struct soap *soap, unsigned int n) {
  15092. return soap_unsignedLong2s(soap, (unsigned long) n);
  15093. }
  15094. /******************************************************************************/
  15095. SOAP_FMAC1
  15096. int
  15097. SOAP_FMAC2
  15098. soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n) {
  15099. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  15100. || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long) *p), 0))
  15101. return soap->error;
  15102. return soap_element_end_out(soap, tag);
  15103. }
  15104. /******************************************************************************/
  15105. SOAP_FMAC1
  15106. int
  15107. SOAP_FMAC2
  15108. soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p) {
  15109. if (s) {
  15110. char *r;
  15111. if (!*s)
  15112. return soap->error = SOAP_EMPTY;
  15113. #ifndef WITH_NOIO
  15114. #ifndef WITH_LEAN
  15115. soap_reset_errno;
  15116. #endif
  15117. #endif
  15118. *p = (unsigned int) soap_strtoul(s, &r, 10);
  15119. if (s == r || *r
  15120. #ifndef WITH_NOIO
  15121. #ifndef WITH_LEAN
  15122. || soap_errno == SOAP_ERANGE
  15123. #endif
  15124. #endif
  15125. )
  15126. soap->error = SOAP_TYPE;
  15127. #ifdef HAVE_STRTOUL
  15128. if (*p > 0 && strchr(s, '-'))
  15129. return soap->error = SOAP_TYPE;
  15130. #endif
  15131. }
  15132. return soap->error;
  15133. }
  15134. /******************************************************************************/
  15135. SOAP_FMAC1
  15136. unsigned int *
  15137. SOAP_FMAC2
  15138. soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t) {
  15139. if (soap_element_begin_in(soap, tag, 0, NULL))
  15140. return NULL;
  15141. #ifndef WITH_LEAN
  15142. if (*soap->type
  15143. && soap_match_tag(soap, soap->type, type)
  15144. && soap_match_tag(soap, soap->type, ":unsignedInt")
  15145. && soap_match_tag(soap, soap->type, ":unsignedShort")
  15146. && soap_match_tag(soap, soap->type, ":unsignedByte")) {
  15147. soap->error = SOAP_TYPE;
  15148. soap_revert(soap);
  15149. return NULL;
  15150. }
  15151. #else
  15152. (void)type;
  15153. #endif
  15154. p = (unsigned int *) soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), NULL, NULL, NULL, NULL);
  15155. if (!p)
  15156. return NULL;
  15157. if (*soap->href != '#') {
  15158. int err = soap_s2unsignedInt(soap, soap_value(soap), p);
  15159. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  15160. return NULL;
  15161. } else {
  15162. p = (unsigned int *) soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(unsigned int), 0, NULL, NULL);
  15163. if (soap->body && soap_element_end_in(soap, tag))
  15164. return NULL;
  15165. }
  15166. return p;
  15167. }
  15168. /******************************************************************************/
  15169. SOAP_FMAC1
  15170. const char *
  15171. SOAP_FMAC2
  15172. soap_unsignedLong2s(struct soap *soap, unsigned long n) {
  15173. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), "%lu", n);
  15174. return soap->tmpbuf;
  15175. }
  15176. /******************************************************************************/
  15177. SOAP_FMAC1
  15178. int
  15179. SOAP_FMAC2
  15180. soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n) {
  15181. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  15182. || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0))
  15183. return soap->error;
  15184. return soap_element_end_out(soap, tag);
  15185. }
  15186. /******************************************************************************/
  15187. SOAP_FMAC1
  15188. int
  15189. SOAP_FMAC2
  15190. soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p) {
  15191. if (s) {
  15192. char *r;
  15193. if (!*s)
  15194. return soap->error = SOAP_EMPTY;
  15195. #ifndef WITH_NOIO
  15196. #ifndef WITH_LEAN
  15197. soap_reset_errno;
  15198. #endif
  15199. #endif
  15200. *p = soap_strtoul(s, &r, 10);
  15201. if (s == r || *r
  15202. #ifndef WITH_NOIO
  15203. #ifndef WITH_LEAN
  15204. || soap_errno == SOAP_ERANGE
  15205. #endif
  15206. #endif
  15207. )
  15208. soap->error = SOAP_TYPE;
  15209. #ifdef HAVE_STRTOUL
  15210. if (*p > 0 && strchr(s, '-'))
  15211. return soap->error = SOAP_TYPE;
  15212. #endif
  15213. }
  15214. return soap->error;
  15215. }
  15216. /******************************************************************************/
  15217. SOAP_FMAC1
  15218. unsigned long *
  15219. SOAP_FMAC2
  15220. soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t) {
  15221. if (soap_element_begin_in(soap, tag, 0, NULL))
  15222. return NULL;
  15223. #ifndef WITH_LEAN
  15224. if (*soap->type
  15225. && soap_match_tag(soap, soap->type, type)
  15226. && soap_match_tag(soap, soap->type, ":unsignedInt")
  15227. && soap_match_tag(soap, soap->type, ":unsignedShort")
  15228. && soap_match_tag(soap, soap->type, ":unsignedByte")) {
  15229. soap->error = SOAP_TYPE;
  15230. soap_revert(soap);
  15231. return NULL;
  15232. }
  15233. #else
  15234. (void)type;
  15235. #endif
  15236. p = (unsigned long *) soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), NULL, NULL, NULL, NULL);
  15237. if (!p)
  15238. return NULL;
  15239. if (*soap->href != '#') {
  15240. int err = soap_s2unsignedLong(soap, soap_value(soap), p);
  15241. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  15242. return NULL;
  15243. } else {
  15244. p = (unsigned long *) soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(unsigned long), 0, NULL, NULL);
  15245. if (soap->body && soap_element_end_in(soap, tag))
  15246. return NULL;
  15247. }
  15248. return p;
  15249. }
  15250. /******************************************************************************/
  15251. SOAP_FMAC1
  15252. const char *
  15253. SOAP_FMAC2
  15254. soap_ULONG642s(struct soap *soap, ULONG64 n) {
  15255. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), SOAP_ULONG_FORMAT, n);
  15256. return soap->tmpbuf;
  15257. }
  15258. /******************************************************************************/
  15259. SOAP_FMAC1
  15260. int
  15261. SOAP_FMAC2
  15262. soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n) {
  15263. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  15264. || soap_string_out(soap, soap_ULONG642s(soap, *p), 0))
  15265. return soap->error;
  15266. return soap_element_end_out(soap, tag);
  15267. }
  15268. /******************************************************************************/
  15269. SOAP_FMAC1
  15270. int
  15271. SOAP_FMAC2
  15272. soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p) {
  15273. if (s) {
  15274. char *r;
  15275. if (!*s)
  15276. return soap->error = SOAP_EMPTY;
  15277. #ifndef WITH_NOIO
  15278. #ifndef WITH_LEAN
  15279. soap_reset_errno;
  15280. #endif
  15281. #endif
  15282. *p = soap_strtoull(s, &r, 10);
  15283. if (s == r || *r
  15284. #ifndef WITH_NOIO
  15285. #ifndef WITH_LEAN
  15286. || soap_errno == SOAP_ERANGE
  15287. #endif
  15288. #endif
  15289. )
  15290. soap->error = SOAP_TYPE;
  15291. if (*p > 0 && strchr(s, '-'))
  15292. return soap->error = SOAP_TYPE;
  15293. }
  15294. return soap->error;
  15295. }
  15296. /******************************************************************************/
  15297. SOAP_FMAC1
  15298. ULONG64 *
  15299. SOAP_FMAC2
  15300. soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t) {
  15301. if (soap_element_begin_in(soap, tag, 0, NULL))
  15302. return NULL;
  15303. #ifndef WITH_LEAN
  15304. if (*soap->type
  15305. && soap_match_tag(soap, soap->type, type)
  15306. && soap_match_tag(soap, soap->type, ":positiveInteger")
  15307. && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
  15308. && soap_match_tag(soap, soap->type, ":unsignedLong")
  15309. && soap_match_tag(soap, soap->type, ":unsignedInt")
  15310. && soap_match_tag(soap, soap->type, ":unsignedShort")
  15311. && soap_match_tag(soap, soap->type, ":unsignedByte")) {
  15312. soap->error = SOAP_TYPE;
  15313. soap_revert(soap);
  15314. return NULL;
  15315. }
  15316. #else
  15317. (void)type;
  15318. #endif
  15319. p = (ULONG64 *) soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), NULL, NULL, NULL, NULL);
  15320. if (!p)
  15321. return NULL;
  15322. if (*soap->href != '#') {
  15323. int err = soap_s2ULONG64(soap, soap_value(soap), p);
  15324. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  15325. return NULL;
  15326. } else {
  15327. p = (ULONG64 *) soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(ULONG64), 0, NULL, NULL);
  15328. if (soap->body && soap_element_end_in(soap, tag))
  15329. return NULL;
  15330. }
  15331. return p;
  15332. }
  15333. /******************************************************************************/
  15334. SOAP_FMAC1
  15335. int
  15336. SOAP_FMAC2
  15337. soap_s2char(struct soap *soap, const char *s, char **t, int flag, long minlen, long maxlen, const char *pattern) {
  15338. if (s) {
  15339. const char *r = soap_string(soap, s, flag, minlen, maxlen, pattern);
  15340. if (r && (*t = soap_strdup(soap, r)) == NULL)
  15341. return soap->error = SOAP_EOM;
  15342. }
  15343. return soap->error;
  15344. }
  15345. /******************************************************************************/
  15346. #ifndef WITH_COMPAT
  15347. #ifdef __cplusplus
  15348. SOAP_FMAC1
  15349. int
  15350. SOAP_FMAC2
  15351. soap_s2stdchar(struct soap *soap, const char *s, std::string *t, int flag, long minlen, long maxlen,
  15352. const char *pattern) {
  15353. if (s) {
  15354. const char *r = soap_string(soap, s, flag, minlen, maxlen, pattern);
  15355. if (r)
  15356. t->assign(r);
  15357. }
  15358. return soap->error;
  15359. }
  15360. #endif
  15361. #endif
  15362. /******************************************************************************/
  15363. static const char *
  15364. soap_string(struct soap *soap, const char *s, int flag, long minlen, long maxlen, const char *pattern) {
  15365. if (s) {
  15366. if (maxlen < 0 && soap->maxlength > 0)
  15367. maxlen = soap->maxlength;
  15368. if (minlen > 0 || maxlen >= 0) {
  15369. size_t l;
  15370. if ((soap->mode & SOAP_C_UTFSTRING))
  15371. l = soap_utf8len(s);
  15372. else
  15373. l = strlen(s);
  15374. if ((maxlen >= 0 && l > (size_t) maxlen) || (minlen > 0 && l < (size_t) minlen)) {
  15375. soap->error = SOAP_LENGTH;
  15376. return NULL;
  15377. }
  15378. }
  15379. if (flag >= 4)
  15380. s = soap_collapse(soap, (char *) s, flag, 0);
  15381. #ifndef WITH_LEANER
  15382. if (pattern && soap->fsvalidate) {
  15383. soap->error = soap->fsvalidate(soap, pattern, s);
  15384. if (soap->error)
  15385. return NULL;
  15386. }
  15387. #else
  15388. (void)pattern;
  15389. #endif
  15390. }
  15391. return s;
  15392. }
  15393. /******************************************************************************/
  15394. static char *
  15395. soap_collapse(struct soap *soap, char *s, int flag, int insitu) {
  15396. /* flag 4=normalizedString (replace), 5=token (collapse) */
  15397. char *t;
  15398. size_t n;
  15399. if (!s)
  15400. return NULL;
  15401. if (flag == 4) {
  15402. for (t = s; *t && (!soap_coblank((soap_wchar) *t) || *t == 32); t++)
  15403. continue;
  15404. if (*t) {
  15405. /* replace white space and control chars by blanks */
  15406. if (!insitu)
  15407. s = soap_strdup(soap, s);
  15408. for (t = s; *t; t++)
  15409. if (soap_coblank((soap_wchar) *t))
  15410. *t = ' ';
  15411. }
  15412. return s;
  15413. }
  15414. /* collapse white space */
  15415. for (t = s; *t && soap_coblank((soap_wchar) *t); t++)
  15416. continue;
  15417. n = strlen(t);
  15418. if (insitu && s < t)
  15419. (void) soap_memmove(s, n + 1, t, n + 1);
  15420. else
  15421. s = t;
  15422. if (n > 0) {
  15423. if (!soap_coblank((soap_wchar) s[n - 1])) {
  15424. for (t = s; (*t && !soap_coblank((soap_wchar) *t)) ||
  15425. (*t == 32 && (!t[1] || !soap_coblank((soap_wchar) t[1]))); t++)
  15426. continue;
  15427. if (!*t)
  15428. return s;
  15429. }
  15430. if (!insitu)
  15431. s = soap_strdup(soap, s);
  15432. for (t = s; *t; t++) {
  15433. if (soap_coblank((soap_wchar) *t)) {
  15434. char *r;
  15435. *t = ' ';
  15436. for (r = t + 1; *r && soap_coblank((soap_wchar) *r); r++)
  15437. continue;
  15438. if (r > t + 1)
  15439. (void) soap_memmove(t + 1, n - (t - s), r, n - (r - s) + 1);
  15440. }
  15441. }
  15442. t--;
  15443. if (t >= s && *t == 32)
  15444. *t = '\0';
  15445. }
  15446. return s;
  15447. }
  15448. /******************************************************************************/
  15449. SOAP_FMAC1
  15450. int
  15451. SOAP_FMAC2
  15452. soap_s2QName(struct soap *soap, const char *s, char **t, long minlen, long maxlen, const char *pattern) {
  15453. *t = NULL;
  15454. if (s) {
  15455. const char *r = soap_QName(soap, s, minlen, maxlen, pattern);
  15456. if (r && (*t = soap_strdup(soap, r)) == NULL)
  15457. return soap->error = SOAP_EOM;
  15458. }
  15459. return soap->error;
  15460. }
  15461. /******************************************************************************/
  15462. #ifndef WITH_COMPAT
  15463. #ifdef __cplusplus
  15464. SOAP_FMAC1
  15465. int
  15466. SOAP_FMAC2
  15467. soap_s2stdQName(struct soap *soap, const char *s, std::string *t, long minlen, long maxlen, const char *pattern) {
  15468. t->clear();
  15469. if (s) {
  15470. const char *r = soap_QName(soap, s, minlen, maxlen, pattern);
  15471. if (r)
  15472. t->assign(r);
  15473. }
  15474. return soap->error;
  15475. }
  15476. #endif
  15477. #endif
  15478. /******************************************************************************/
  15479. static const char *
  15480. soap_QName(struct soap *soap, const char *s, long minlen, long maxlen, const char *pattern) {
  15481. if (s) {
  15482. char *b;
  15483. if (maxlen < 0 && soap->maxlength > 0)
  15484. maxlen = soap->maxlength;
  15485. if (minlen > 0 || maxlen >= 0) {
  15486. size_t l;
  15487. if ((soap->mode & SOAP_C_UTFSTRING))
  15488. l = soap_utf8len(s);
  15489. else
  15490. l = strlen(s);
  15491. if ((maxlen >= 0 && l > (size_t) maxlen) || (minlen > 0 && l < (size_t) minlen)) {
  15492. soap->error = SOAP_LENGTH;
  15493. return NULL;
  15494. }
  15495. }
  15496. #ifdef WITH_FAST
  15497. soap->labidx = 0;
  15498. #else
  15499. if (soap_alloc_block(soap) == NULL)
  15500. return NULL;
  15501. #endif
  15502. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Normalized namespace(s) of QNames '%s'", s));
  15503. /* convert (by prefix normalize prefix) all QNames in s */
  15504. for (;;) {
  15505. size_t n;
  15506. struct soap_nlist *np;
  15507. const char *p = NULL;
  15508. short flag = 0;
  15509. const char *r = NULL;
  15510. size_t m = 0;
  15511. #ifndef WITH_FAST
  15512. size_t k = 0;
  15513. #endif
  15514. /* skip blanks */
  15515. while (*s && soap_coblank((soap_wchar) *s))
  15516. s++;
  15517. if (!*s)
  15518. break;
  15519. /* find next QName */
  15520. n = 1;
  15521. while (s[n] && !soap_coblank((soap_wchar) s[n]))
  15522. n++;
  15523. np = soap->nlist;
  15524. /* if there is no namespace stack, or prefix is "#" or "xml" then copy string */
  15525. if (!np || *s == '#' || !strncmp(s, "xml:", 4)) {
  15526. r = s;
  15527. m = n;
  15528. } else /* we normalize the QName by replacing its prefix */
  15529. {
  15530. const char *q;
  15531. for (p = s; *p && p < s + n; p++)
  15532. if (*p == ':')
  15533. break;
  15534. if (*p == ':') {
  15535. size_t k = p - s;
  15536. while (np && (strncmp(np->id, s, k) || np->id[k]))
  15537. np = np->next;
  15538. p++;
  15539. } else {
  15540. while (np && *np->id)
  15541. np = np->next;
  15542. p = s;
  15543. }
  15544. /* replace prefix */
  15545. if (np) {
  15546. if (np->index >= 0 && soap->local_namespaces &&
  15547. (q = soap->local_namespaces[np->index].id) != NULL) {
  15548. size_t k = strlen(q);
  15549. if (q[k - 1] != '_') {
  15550. r = q;
  15551. m = k;
  15552. } else {
  15553. flag = 1;
  15554. r = soap->local_namespaces[np->index].ns;
  15555. m = strlen(r);
  15556. }
  15557. } else if (np->ns) {
  15558. flag = 1;
  15559. r = np->ns;
  15560. m = strlen(r);
  15561. } else {
  15562. DBGLOG(TEST,
  15563. SOAP_MESSAGE(fdebug, "\nNamespace prefix of '%s' not defined (index=%d, URI='%s')\n", s,
  15564. np->index, np->ns ? np->ns : SOAP_STR_EOS));
  15565. soap->error = SOAP_NAMESPACE;
  15566. return NULL;
  15567. }
  15568. } else if (s[n]) /* no namespace, part of string */
  15569. {
  15570. r = s;
  15571. m = n;
  15572. } else /* no namespace: assume "" namespace */
  15573. {
  15574. flag = 1;
  15575. }
  15576. }
  15577. #ifdef WITH_FAST
  15578. if ((flag && soap_append_lab(soap, "\"", 1))
  15579. || (m && soap_append_lab(soap, r, m))
  15580. || (flag && soap_append_lab(soap, "\"", 1))
  15581. || (p && (soap_append_lab(soap, ":", 1) || soap_append_lab(soap, p, n - (p - s)))))
  15582. return NULL;
  15583. #else
  15584. k = 2*flag + m + (p ? n - (p-s) + 1 : 0) + (s[n] != '\0');
  15585. b = (char*)soap_push_block(soap, NULL, k);
  15586. if (!b)
  15587. return NULL;
  15588. if (flag)
  15589. *b++ = '"';
  15590. if (m)
  15591. {
  15592. if (soap_memcpy((void*)b, k, (const void*)r, m))
  15593. {
  15594. soap->error = SOAP_EOM;
  15595. return NULL;
  15596. }
  15597. b += m;
  15598. }
  15599. if (flag)
  15600. *b++ = '"';
  15601. if (p)
  15602. {
  15603. *b++ = ':';
  15604. if (soap_memcpy((void*)b, k - m - flag - 1, (const void*)p, n - (p-s)))
  15605. {
  15606. soap->error = SOAP_EOM;
  15607. return NULL;
  15608. }
  15609. b += n - (p-s);
  15610. }
  15611. #endif
  15612. /* advance to next and add spacing */
  15613. s += n;
  15614. while (*s && soap_coblank(*s))
  15615. s++;
  15616. if (*s) {
  15617. #ifdef WITH_FAST
  15618. if (soap_append_lab(soap, " ", 1))
  15619. return NULL;
  15620. #else
  15621. *b = ' ';
  15622. #endif
  15623. }
  15624. }
  15625. #ifdef WITH_FAST
  15626. if (soap_append_lab(soap, SOAP_STR_EOS, 1))
  15627. return NULL;
  15628. b = soap->labbuf;
  15629. #else
  15630. b = (char*)soap_push_block(soap, NULL, 1);
  15631. if (!b)
  15632. return NULL;
  15633. *b = '\0';
  15634. b = (char*)soap_save_block(soap, NULL, NULL, 0);
  15635. #endif
  15636. #ifndef WITH_LEANER
  15637. if (pattern && soap->fsvalidate) {
  15638. soap->error = soap->fsvalidate(soap, pattern, b);
  15639. if (soap->error)
  15640. return NULL;
  15641. }
  15642. #else
  15643. (void)pattern;
  15644. #endif
  15645. return b;
  15646. }
  15647. return NULL;
  15648. }
  15649. /******************************************************************************/
  15650. SOAP_FMAC1
  15651. const char *
  15652. SOAP_FMAC2
  15653. soap_QName2s(struct soap *soap, const char *s) {
  15654. const char *t = NULL;
  15655. if (s) {
  15656. #ifdef WITH_FAST
  15657. soap_store_lab(soap, SOAP_STR_EOS, 1);
  15658. soap->labidx = 0;
  15659. #else
  15660. char *b = NULL;
  15661. if (soap_alloc_block(soap) == NULL)
  15662. return NULL;
  15663. #endif
  15664. for (;;) {
  15665. size_t n;
  15666. const char *q = NULL;
  15667. const char *r = NULL;
  15668. size_t m = 0;
  15669. #ifndef WITH_FAST
  15670. size_t k = 0;
  15671. #endif
  15672. /* skip blanks */
  15673. while (*s && soap_coblank((soap_wchar) *s))
  15674. s++;
  15675. if (!*s) {
  15676. #ifdef WITH_FAST
  15677. soap->labbuf[soap->labidx > 0 ? soap->labidx - 1 : 0] = '\0';
  15678. #else
  15679. if (!b)
  15680. return soap_strdup(soap, SOAP_STR_EOS);
  15681. --b;
  15682. *b = '\0';
  15683. #endif
  15684. break;
  15685. }
  15686. /* find next QName */
  15687. n = 0;
  15688. while (s[n] && !soap_coblank((soap_wchar) s[n])) {
  15689. if (s[n] == ':')
  15690. r = s;
  15691. n++;
  15692. }
  15693. if (*s != '"') /* non-quoted: pass string as is */
  15694. {
  15695. #ifndef WITH_LEAN
  15696. if (r && (soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_XML_CANONICAL_NA))
  15697. soap_utilize_ns(soap, s, 1);
  15698. #endif
  15699. r = s;
  15700. m = n + 1;
  15701. } else /* prefix quoted URI-based string */
  15702. {
  15703. q = strchr(s + 1, '"');
  15704. if (q) {
  15705. struct Namespace *p = soap->local_namespaces;
  15706. if (p) {
  15707. for (; p->id; p++) {
  15708. if (p->ns)
  15709. if (!soap_tag_cmp(s + 1, p->ns))
  15710. break;
  15711. if (p->in)
  15712. if (!soap_tag_cmp(s + 1, p->in))
  15713. break;
  15714. }
  15715. }
  15716. q++;
  15717. /* URL is in the namespace table? */
  15718. if (p && p->id) {
  15719. r = p->id;
  15720. m = strlen(r);
  15721. } else /* not in namespace table: create xmlns binding */
  15722. {
  15723. char *x = soap_strdup(soap, s + 1);
  15724. if (!x)
  15725. return NULL;
  15726. x[q - s - 2] = '\0';
  15727. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 27), "xmlns:_%d", soap->idnum++);
  15728. soap_set_attr(soap, soap->tmpbuf, x, 1);
  15729. r = soap->tmpbuf + 6;
  15730. m = strlen(r);
  15731. }
  15732. }
  15733. }
  15734. /* copy normalized QName into buffer, including the ending blank or NUL */
  15735. #ifdef WITH_FAST
  15736. if ((m && soap_append_lab(soap, r, m))
  15737. || (q && soap_append_lab(soap, q, n - (q - s) + 1)))
  15738. return NULL;
  15739. #else
  15740. k = m + (q ? n - (q - s) + 1 : 0);
  15741. b = (char*)soap_push_block(soap, NULL, k);
  15742. if (!b)
  15743. {
  15744. soap->error = SOAP_EOM;
  15745. return NULL;
  15746. }
  15747. if (soap_memcpy((void*)b, k, (const void*)r, m))
  15748. {
  15749. soap->error = SOAP_EOM;
  15750. return NULL;
  15751. }
  15752. b += m;
  15753. if (q)
  15754. {
  15755. if (soap_memcpy((void*)b, k - m, (const void*)q, n - (q - s) + 1))
  15756. {
  15757. soap->error = SOAP_EOM;
  15758. return NULL;
  15759. }
  15760. b += n - (q - s) + 1;
  15761. }
  15762. #endif
  15763. /* advance to next */
  15764. s += n;
  15765. }
  15766. #ifdef WITH_FAST
  15767. t = soap_strdup(soap, soap->labbuf);
  15768. if (!t)
  15769. soap->error = SOAP_EOM;
  15770. #else
  15771. t = (char*)soap_save_block(soap, NULL, NULL, 0);
  15772. #endif
  15773. }
  15774. return t;
  15775. }
  15776. /******************************************************************************/
  15777. #ifndef WITH_LEAN
  15778. SOAP_FMAC1
  15779. int
  15780. SOAP_FMAC2
  15781. soap_s2wchar(struct soap *soap, const char *s, wchar_t **t, int flag, long minlen, long maxlen, const char *pattern) {
  15782. if (s) {
  15783. const wchar_t *r = soap_wstring(soap, s, flag, minlen, maxlen, pattern);
  15784. if (r && (*t = soap_wstrdup(soap, r)) == NULL)
  15785. return soap->error = SOAP_EOM;
  15786. }
  15787. return soap->error;
  15788. }
  15789. #endif
  15790. /******************************************************************************/
  15791. #ifndef WITH_COMPAT
  15792. #ifdef __cplusplus
  15793. #ifndef WITH_LEAN
  15794. SOAP_FMAC1
  15795. int
  15796. SOAP_FMAC2
  15797. soap_s2stdwchar(struct soap *soap, const char *s, std::wstring *t, int flag, long minlen, long maxlen,
  15798. const char *pattern) {
  15799. if (s) {
  15800. const wchar_t *r = soap_wstring(soap, s, flag, minlen, maxlen, pattern);
  15801. if (r)
  15802. t->assign(r);
  15803. }
  15804. return soap->error;
  15805. }
  15806. #endif
  15807. #endif
  15808. #endif
  15809. /******************************************************************************/
  15810. #ifndef WITH_LEAN
  15811. static const wchar_t *
  15812. soap_wstring(struct soap *soap, const char *s, int flag, long minlen, long maxlen, const char *pattern) {
  15813. if (s) {
  15814. size_t l;
  15815. soap_wchar c;
  15816. wchar_t *t;
  15817. if (maxlen < 0 && soap->maxlength > 0)
  15818. maxlen = soap->maxlength;
  15819. soap->labidx = 0;
  15820. if ((soap->mode & SOAP_ENC_LATIN)) {
  15821. wchar_t *r;
  15822. if (soap_append_lab(soap, NULL, sizeof(wchar_t) * (strlen(s) + 1)))
  15823. return NULL;
  15824. r = (wchar_t *) soap->labbuf;
  15825. while (*s)
  15826. *r++ = (wchar_t) *s++;
  15827. } else {
  15828. /* Convert UTF8 to wchar_t */
  15829. while (*s) {
  15830. c = (unsigned char) *s++;
  15831. if (c >= 0x80) {
  15832. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  15833. soap_wchar c1, c2, c3;
  15834. c1 = (unsigned char)*s;
  15835. if (c <= 0xC1 || (c1 & 0xC0) != 0x80)
  15836. {
  15837. c = SOAP_UNKNOWN_UNICODE_CHAR;
  15838. }
  15839. else
  15840. {
  15841. ++s;
  15842. c1 &= 0x3F;
  15843. if (c < 0xE0)
  15844. {
  15845. c = (((c & 0x1F) << 6) | c1);
  15846. }
  15847. else
  15848. {
  15849. c2 = (unsigned char)*s;
  15850. if ((c == 0xE0 && c1 < 0x20) || (c2 & 0xC0) != 0x80)
  15851. {
  15852. c = SOAP_UNKNOWN_UNICODE_CHAR;
  15853. }
  15854. else
  15855. {
  15856. ++s;
  15857. c2 &= 0x3F;
  15858. if (c < 0xF0)
  15859. {
  15860. c = (((c & 0x0F) << 12) | (c1 << 6) | c2);
  15861. }
  15862. else
  15863. {
  15864. c3 = (unsigned char)*s;
  15865. if ((c == 0xF0 && c1 < 0x10) || (c == 0xF4 && c1 >= 0x10) || c >= 0xF5 || (c3 & 0xC0) != 0x80)
  15866. {
  15867. c = SOAP_UNKNOWN_UNICODE_CHAR;
  15868. }
  15869. else
  15870. {
  15871. ++s;
  15872. c = (((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | (c3 & 0x3F));
  15873. }
  15874. }
  15875. }
  15876. }
  15877. }
  15878. #else
  15879. soap_wchar c1, c2, c3, c4;
  15880. c1 = (unsigned char) *s;
  15881. if (c1) {
  15882. s++;
  15883. c1 &= 0x3F;
  15884. if (c < 0xE0) {
  15885. c = (wchar_t) (((soap_wchar) (c & 0x1F) << 6) | c1);
  15886. } else {
  15887. c2 = (unsigned char) *s;
  15888. if (c2) {
  15889. s++;
  15890. c2 &= 0x3F;
  15891. if (c < 0xF0) {
  15892. c = (wchar_t) (((soap_wchar) (c & 0x0F) << 12) | (c1 << 6) | c2);
  15893. } else {
  15894. c3 = (unsigned char) *s;
  15895. if (c3) {
  15896. s++;
  15897. c3 &= 0x3F;
  15898. if (c < 0xF8) {
  15899. c = (wchar_t) (((soap_wchar) (c & 0x07) << 18) | (c1 << 12) | (c2 << 6) |
  15900. c3);
  15901. } else {
  15902. c4 = (unsigned char) *s;
  15903. if (c4) {
  15904. s++;
  15905. c4 &= 0x3F;
  15906. if (c < 0xFC) {
  15907. c = (wchar_t) (((soap_wchar) (c & 0x03) << 24) | (c1 << 18) |
  15908. (c2 << 12) | (c3 << 6) | c4);
  15909. } else {
  15910. c = (wchar_t) (((soap_wchar) (c & 0x01) << 30) | (c1 << 24) |
  15911. (c2 << 18) | (c3 << 12) | (c4 << 6) |
  15912. (unsigned char) (*s & 0x3F));
  15913. if (*s)
  15914. s++;
  15915. }
  15916. }
  15917. }
  15918. }
  15919. }
  15920. }
  15921. }
  15922. }
  15923. #endif
  15924. }
  15925. /* use UTF16 encoding when wchar_t is too small to hold UCS */
  15926. if (sizeof(wchar_t) < 4 && c > 0xFFFF) {
  15927. wchar_t c1, c2;
  15928. c1 = 0xD800 - (0x10000 >> 10) + (c >> 10);
  15929. c2 = 0xDC00 + (c & 0x3FF);
  15930. if (soap_append_lab(soap, (const char *) &c1, sizeof(wchar_t)) ||
  15931. soap_append_lab(soap, (const char *) &c2, sizeof(wchar_t)))
  15932. return NULL;
  15933. } else if (soap_append_lab(soap, (const char *) &c, sizeof(wchar_t))) {
  15934. return NULL;
  15935. }
  15936. }
  15937. }
  15938. l = soap->labidx / sizeof(wchar_t);
  15939. c = L'\0';
  15940. if (soap_append_lab(soap, (const char *) &c, sizeof(wchar_t)))
  15941. return NULL;
  15942. if ((maxlen >= 0 && l > (size_t) maxlen) || (minlen > 0 && l < (size_t) minlen)) {
  15943. soap->error = SOAP_LENGTH;
  15944. return NULL;
  15945. }
  15946. t = (wchar_t *) soap->labbuf;
  15947. #ifndef WITH_LEAN
  15948. if (flag >= 4 && t)
  15949. t = soap_wcollapse(soap, t, flag, 1);
  15950. #endif
  15951. #ifndef WITH_LEANER
  15952. if (pattern && soap->fwvalidate) {
  15953. soap->error = soap->fwvalidate(soap, pattern, t);
  15954. if (soap->error)
  15955. return NULL;
  15956. }
  15957. #endif
  15958. return t;
  15959. }
  15960. return NULL;
  15961. }
  15962. #endif
  15963. /******************************************************************************/
  15964. #ifndef WITH_LEAN
  15965. static wchar_t *
  15966. soap_wcollapse(struct soap *soap, wchar_t *s, int flag, int insitu) {
  15967. /* flag 4=normalizedString (replace), 5=token (collapse) */
  15968. wchar_t *t;
  15969. size_t n;
  15970. if (!s)
  15971. return NULL;
  15972. if (flag == 4) {
  15973. for (t = s; *t && (!soap_coblank((soap_wchar) *t) || *t == 32); t++)
  15974. continue;
  15975. if (*t) {
  15976. /* replace blanks and control char by space */
  15977. if (!insitu)
  15978. s = soap_wstrdup(soap, s);
  15979. if (s)
  15980. for (t = s; *t; t++)
  15981. if (soap_coblank((soap_wchar) *t))
  15982. *t = L' ';
  15983. }
  15984. return s;
  15985. }
  15986. /* collapse white space */
  15987. for (t = s; *t && soap_coblank((soap_wchar) *t); t++)
  15988. continue;
  15989. n = 0;
  15990. while (t[n])
  15991. n++;
  15992. if (insitu && s < t)
  15993. (void) soap_memmove(s, n + 1, t, n + 1);
  15994. else
  15995. s = t;
  15996. if (n > 0) {
  15997. if (!soap_coblank((soap_wchar) s[n - 1])) {
  15998. for (t = s; (*t && !soap_coblank((soap_wchar) *t)) ||
  15999. (*t == 32 && (!t[1] || !soap_coblank((soap_wchar) t[1]))); t++)
  16000. continue;
  16001. if (!*t)
  16002. return s;
  16003. }
  16004. if (!insitu)
  16005. s = soap_wstrdup(soap, s);
  16006. if (s) {
  16007. for (t = s; *t; t++) {
  16008. if (soap_coblank((soap_wchar) *t)) {
  16009. wchar_t *r;
  16010. *t = L' ';
  16011. for (r = t + 1; *r && soap_coblank((soap_wchar) *r); r++)
  16012. continue;
  16013. if (r > t + 1)
  16014. (void) soap_memmove(t + 1, sizeof(wchar_t) * (n - (t - s)), r,
  16015. sizeof(wchar_t) * (n - (r - s) + 1));
  16016. }
  16017. }
  16018. t--;
  16019. if (t >= s && *t == 32)
  16020. *t = L'\0';
  16021. }
  16022. }
  16023. return s;
  16024. }
  16025. #endif
  16026. /******************************************************************************/
  16027. #ifndef WITH_LEAN
  16028. SOAP_FMAC1
  16029. const char *
  16030. SOAP_FMAC2
  16031. soap_wchar2s(struct soap *soap, const wchar_t *s) {
  16032. soap_wchar c;
  16033. char *r, *t;
  16034. const wchar_t *q = s;
  16035. size_t n = 0;
  16036. if (!s)
  16037. return NULL;
  16038. while ((c = *q++)) {
  16039. if (c > 0 && c < 0x80)
  16040. n++;
  16041. else
  16042. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  16043. n += 4;
  16044. #else
  16045. n += 6;
  16046. #endif
  16047. }
  16048. r = t = (char *) soap_malloc(soap, n + 1);
  16049. if (r) {
  16050. /* Convert wchar to UTF8 (chars above U+10FFFF are silently converted, but should not be used) */
  16051. while ((c = *s++)) {
  16052. if (c > 0 && c < 0x80) {
  16053. *t++ = (char) c;
  16054. } else {
  16055. /* check for UTF16 encoding when wchar_t is too small to hold UCS */
  16056. if (sizeof(wchar_t) < 4 && (c & 0xFC00) == 0xD800) {
  16057. soap_wchar d = *s;
  16058. if ((d & 0xFC00) == 0xDC00) {
  16059. c = ((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000;
  16060. s++;
  16061. }
  16062. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  16063. else
  16064. {
  16065. c = SOAP_UNKNOWN_UNICODE_CHAR; /* Malformed UTF-16 */
  16066. }
  16067. #endif
  16068. }
  16069. if (c < 0x0800) {
  16070. *t++ = (char) (0xC0 | ((c >> 6) & 0x1F));
  16071. } else {
  16072. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  16073. if (!((c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF)))
  16074. c = SOAP_UNKNOWN_UNICODE_CHAR;
  16075. #endif
  16076. if (c < 0x010000) {
  16077. *t++ = (char) (0xE0 | ((c >> 12) & 0x0F));
  16078. } else {
  16079. if (c < 0x200000) {
  16080. *t++ = (char) (0xF0 | ((c >> 18) & 0x07));
  16081. } else {
  16082. if (c < 0x04000000) {
  16083. *t++ = (char) (0xF8 | ((c >> 24) & 0x03));
  16084. } else {
  16085. *t++ = (char) (0xFC | ((c >> 30) & 0x01));
  16086. *t++ = (char) (0x80 | ((c >> 24) & 0x3F));
  16087. }
  16088. *t++ = (char) (0x80 | ((c >> 18) & 0x3F));
  16089. }
  16090. *t++ = (char) (0x80 | ((c >> 12) & 0x3F));
  16091. }
  16092. *t++ = (char) (0x80 | ((c >> 6) & 0x3F));
  16093. }
  16094. *t++ = (char) (0x80 | (c & 0x3F));
  16095. }
  16096. }
  16097. *t = '\0';
  16098. }
  16099. return r;
  16100. }
  16101. #endif
  16102. /******************************************************************************/
  16103. SOAP_FMAC1
  16104. int
  16105. SOAP_FMAC2
  16106. soap_outstring(struct soap *soap, const char *tag, int id, char *const *p, const char *type, int n) {
  16107. id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n, NULL);
  16108. if (id < 0)
  16109. return soap->error;
  16110. if (!**p && (soap->mode & SOAP_C_NILSTRING))
  16111. return soap_element_null(soap, tag, id, type);
  16112. if (soap_element_begin_out(soap, tag, id, type)
  16113. || soap_string_out(soap, *p, 0)
  16114. || soap_element_end_out(soap, tag))
  16115. return soap->error;
  16116. return SOAP_OK;
  16117. }
  16118. /******************************************************************************/
  16119. SOAP_FMAC1
  16120. char **
  16121. SOAP_FMAC2
  16122. soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen,
  16123. const char *pattern) {
  16124. (void) type;
  16125. if (soap_element_begin_in(soap, tag, 1, NULL)) {
  16126. if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
  16127. return NULL;
  16128. soap->error = SOAP_OK;
  16129. }
  16130. if (!p) {
  16131. p = (char **) soap_malloc(soap, sizeof(char *));
  16132. if (!p)
  16133. return NULL;
  16134. }
  16135. if (soap->null) {
  16136. *p = NULL;
  16137. } else if (soap->body) {
  16138. *p = soap_string_in(soap, flag, minlen, maxlen, pattern);
  16139. if (!*p || !(char *) soap_id_enter(soap, soap->id, *p, t, sizeof(char *), NULL, NULL, NULL, NULL))
  16140. return NULL;
  16141. if (!**p && tag && *tag == '-') {
  16142. soap->error = SOAP_NO_TAG;
  16143. return NULL;
  16144. }
  16145. } else if (tag && *tag == '-') {
  16146. soap->error = SOAP_NO_TAG;
  16147. return NULL;
  16148. } else if (*soap->href != '#') {
  16149. if (minlen > 0) {
  16150. soap->error = SOAP_LENGTH;
  16151. return NULL;
  16152. }
  16153. *p = soap_strdup(soap, SOAP_STR_EOS);
  16154. if (!*p)
  16155. return NULL;
  16156. }
  16157. if (*soap->href == '#')
  16158. p = (char **) soap_id_lookup(soap, soap->href, (void **) p, t, sizeof(char **), 0, NULL);
  16159. if (soap->body && soap_element_end_in(soap, tag))
  16160. return NULL;
  16161. return p;
  16162. }
  16163. /******************************************************************************/
  16164. #ifndef WITH_LEANER
  16165. SOAP_FMAC1
  16166. int
  16167. SOAP_FMAC2
  16168. soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const *p, const char *type, int n) {
  16169. id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n, NULL);
  16170. if (id < 0)
  16171. return soap->error;
  16172. if (!**p && (soap->mode & SOAP_C_NILSTRING))
  16173. return soap_element_null(soap, tag, id, type);
  16174. if (soap_element_begin_out(soap, tag, id, type)
  16175. || soap_wstring_out(soap, *p, 0)
  16176. || soap_element_end_out(soap, tag))
  16177. return soap->error;
  16178. return SOAP_OK;
  16179. }
  16180. #endif
  16181. /******************************************************************************/
  16182. #ifndef WITH_LEANER
  16183. SOAP_FMAC1
  16184. wchar_t **
  16185. SOAP_FMAC2
  16186. soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, int flag, long minlen,
  16187. long maxlen, const char *pattern) {
  16188. (void) type;
  16189. if (soap_element_begin_in(soap, tag, 1, NULL)) {
  16190. if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
  16191. return NULL;
  16192. soap->error = SOAP_OK;
  16193. }
  16194. if (!p) {
  16195. p = (wchar_t **) soap_malloc(soap, sizeof(wchar_t *));
  16196. if (!p)
  16197. return NULL;
  16198. }
  16199. if (soap->null) {
  16200. *p = NULL;
  16201. } else if (soap->body) {
  16202. *p = soap_wstring_in(soap, flag, minlen, maxlen, pattern);
  16203. if (!*p || !(wchar_t *) soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t *), NULL, NULL, NULL, NULL))
  16204. return NULL;
  16205. if (!**p && tag && *tag == '-') {
  16206. soap->error = SOAP_NO_TAG;
  16207. return NULL;
  16208. }
  16209. } else if (tag && *tag == '-') {
  16210. soap->error = SOAP_NO_TAG;
  16211. return NULL;
  16212. } else if (*soap->href != '#') {
  16213. if (minlen > 0) {
  16214. soap->error = SOAP_LENGTH;
  16215. return NULL;
  16216. }
  16217. *p = soap_wstrdup(soap, L"");
  16218. }
  16219. if (*soap->href == '#')
  16220. p = (wchar_t **) soap_id_lookup(soap, soap->href, (void **) p, t, sizeof(wchar_t **), 0, NULL);
  16221. if (soap->body && soap_element_end_in(soap, tag))
  16222. return NULL;
  16223. return p;
  16224. }
  16225. #endif
  16226. /******************************************************************************/
  16227. #ifndef WITH_LEAN
  16228. #ifdef UNDER_CE
  16229. /* WinCE mktime (based on the mingw-runtime, public domain) */
  16230. #define __FILETIME_to_ll(f) ((long long)(f).dwHighDateTime << 32 | (long long)(f).dwLowDateTime)
  16231. static time_t
  16232. mktime(struct tm *pt)
  16233. {
  16234. SYSTEMTIME s, s1, s2;
  16235. FILETIME f, f1, f2;
  16236. long long diff;
  16237. GetSystemTime(&s1);
  16238. GetLocalTime(&s2);
  16239. SystemTimeToFileTime(&s1, &f1);
  16240. SystemTimeToFileTime(&s2, &f2);
  16241. diff = (__FILETIME_to_ll(f2) - __FILETIME_to_ll(f1)) / 10000000LL;
  16242. s.wYear = pt->tm_year + 1900;
  16243. s.wMonth = pt->tm_mon + 1;
  16244. s.wDayOfWeek = pt->tm_wday;
  16245. s.wDay = pt->tm_mday;
  16246. s.wHour = pt->tm_hour;
  16247. s.wMinute = pt->tm_min;
  16248. s.wSecond = pt->tm_sec;
  16249. s.wMilliseconds = 0;
  16250. SystemTimeToFileTime(&s, &f);
  16251. return (time_t)((__FILETIME_to_ll(f) - 116444736000000000LL) / 10000000LL) - (time_t)diff;
  16252. }
  16253. #endif
  16254. #endif
  16255. /******************************************************************************/
  16256. #ifndef WITH_LEAN
  16257. #ifdef UNDER_CE
  16258. /* WinCE gmtime_r (based on the mingw-runtime, public domain) */
  16259. #define HAVE_GMTIME_R
  16260. static struct tm*
  16261. gmtime_r(const time_t *t, struct tm *pt)
  16262. {
  16263. FILETIME f, f1, f2;
  16264. SYSTEMTIME s, s1 = {0};
  16265. long long time = (long long)(*t) * 10000000LL + 116444736000000000LL;
  16266. f.dwHighDateTime = (DWORD)((time >> 32) & 0x00000000FFFFFFFF);
  16267. f.dwLowDateTime = (DWORD)(time & 0x00000000FFFFFFFF);
  16268. FileTimeToSystemTime(&f, &s);
  16269. pt->tm_year = s.wYear - 1900;
  16270. pt->tm_mon = s.wMonth - 1;
  16271. pt->tm_wday = s.wDayOfWeek;
  16272. pt->tm_mday = s.wDay;
  16273. s1.wYear = s.wYear;
  16274. s1.wMonth = 1;
  16275. s1.wDayOfWeek = 1;
  16276. s1.wDay = 1;
  16277. SystemTimeToFileTime(&s1, &f1);
  16278. SystemTimeToFileTime(&s, &f2);
  16279. pt->tm_yday = (((__FILETIME_to_ll(f2) - __FILETIME_to_ll(f1)) / 10000000LL) / (60 * 60 * 24));
  16280. pt->tm_hour = s.wHour;
  16281. pt->tm_min = s.wMinute;
  16282. pt->tm_sec = s.wSecond;
  16283. pt->tm_isdst = 0;
  16284. return pt;
  16285. }
  16286. #endif
  16287. #endif
  16288. /******************************************************************************/
  16289. #ifndef WITH_LEAN
  16290. #ifdef UNDER_CE
  16291. /* WinCE very simple strftime for format "%Y-%m-%dT%H:%M:%SZ", note: %F and %T not supported by MS */
  16292. static size_t
  16293. strftime(char *buf, size_t len, const char *format, const struct tm *pT)
  16294. {
  16295. (void)len; (void)format;
  16296. #ifndef WITH_NOZONE
  16297. (SOAP_SNPRINTF(buf, len, 20), "%04d-%02d-%02dT%02d:%02d:%02dZ", pT->tm_year + 1900, pT->tm_mon + 1, pT->tm_mday, pT->tm_hour, pT->tm_min, pT->tm_sec);
  16298. #else
  16299. (SOAP_SNPRINTF(buf, len, 20), "%04d-%02d-%02dT%02d:%02d:%02d", pT->tm_year + 1900, pT->tm_mon + 1, pT->tm_mday, pT->tm_hour, pT->tm_min, pT->tm_sec);
  16300. #endif
  16301. return len;
  16302. }
  16303. #endif
  16304. #endif
  16305. /******************************************************************************/
  16306. #if !defined(WITH_LEAN) || defined(WITH_COOKIES)
  16307. SOAP_FMAC1
  16308. time_t
  16309. SOAP_FMAC2
  16310. soap_timegm(struct tm *T) {
  16311. #if defined(HAVE_TIMEGM)
  16312. return timegm(T);
  16313. #else
  16314. time_t t, g, z;
  16315. struct tm tm;
  16316. #ifndef HAVE_GMTIME_R
  16317. struct tm *tp;
  16318. #endif
  16319. t = mktime(T);
  16320. if (t == (time_t)-1)
  16321. return (time_t)-1;
  16322. #ifdef HAVE_GMTIME_R
  16323. if (gmtime_r(&t, &tm) == SOAP_FUNC_R_ERR)
  16324. return (time_t)-1;
  16325. #else
  16326. tp = gmtime(&t);
  16327. if (!tp)
  16328. return (time_t)-1;
  16329. tm = *tp;
  16330. #endif
  16331. tm.tm_isdst = 0;
  16332. g = mktime(&tm);
  16333. if (g == (time_t)-1)
  16334. return (time_t)-1;
  16335. z = g - t;
  16336. return t - z;
  16337. #endif
  16338. }
  16339. #endif
  16340. /******************************************************************************/
  16341. #ifndef WITH_LEAN
  16342. SOAP_FMAC1
  16343. const char *
  16344. SOAP_FMAC2
  16345. soap_dateTime2s(struct soap *soap, time_t n) {
  16346. struct tm T, *pT = &T;
  16347. size_t l = 0;
  16348. #if defined(HAVE_GMTIME_R) && !defined(WITH_NOZONE)
  16349. if (gmtime_r(&n, pT) != SOAP_FUNC_R_ERR)
  16350. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
  16351. #elif defined(HAVE_GMTIME) && !defined(WITH_NOZONE)
  16352. pT = gmtime(&n);
  16353. if (pT)
  16354. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
  16355. #elif (defined(HAVE_TM_GMTOFF) || defined(HAVE_STRUCT_TM_TM_GMTOFF) || defined(HAVE_STRUCT_TM___TM_GMTOFF)) && !defined(WITH_NOZONE)
  16356. #if defined(HAVE_LOCALTIME_R)
  16357. if (localtime_r(&n, pT) != SOAP_FUNC_R_ERR)
  16358. {
  16359. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT);
  16360. if (l)
  16361. {
  16362. (void)soap_memmove(soap->tmpbuf + 23, sizeof(soap->tmpbuf) - 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */
  16363. soap->tmpbuf[22] = ':'; /* 2000-03-01T02:00:00+03:00 */
  16364. }
  16365. }
  16366. #else
  16367. pT = localtime(&n);
  16368. if (pT)
  16369. {
  16370. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT);
  16371. if (l)
  16372. {
  16373. (void)soap_memmove(soap->tmpbuf + 23, sizeof(soap->tmpbuf) - 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */
  16374. soap->tmpbuf[22] = ':'; /* 2000-03-01T02:00:00+03:00 */
  16375. }
  16376. }
  16377. #endif
  16378. #elif defined(HAVE_GETTIMEOFDAY) && !defined(WITH_NOZONE)
  16379. #if defined(HAVE_LOCALTIME_R)
  16380. if (localtime_r(&n, pT) != SOAP_FUNC_R_ERR)
  16381. {
  16382. struct timeval tv;
  16383. struct timezone tz;
  16384. memset((void*)&tz, 0, sizeof(tz));
  16385. gettimeofday(&tv, &tz);
  16386. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
  16387. if (l)
  16388. (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, 7), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
  16389. }
  16390. #else
  16391. pT = localtime(&n);
  16392. if (pT)
  16393. {
  16394. struct timeval tv;
  16395. struct timezone tz;
  16396. memset((void*)&tz, 0, sizeof(tz));
  16397. gettimeofday(&tv, &tz);
  16398. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
  16399. if (l)
  16400. (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, 7), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
  16401. }
  16402. #endif
  16403. #elif defined(HAVE_FTIME) && !defined(WITH_NOZONE)
  16404. #if defined(HAVE_LOCALTIME_R)
  16405. if (localtime_r(&n, pT) != SOAP_FUNC_R_ERR)
  16406. {
  16407. struct timeb t;
  16408. memset((void*)&t, 0, sizeof(t));
  16409. #ifdef __BORLANDC__
  16410. ::ftime(&t);
  16411. #else
  16412. ftime(&t);
  16413. #endif
  16414. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
  16415. if (l)
  16416. (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, 7), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
  16417. }
  16418. #else
  16419. pT = localtime(&n);
  16420. if (pT)
  16421. {
  16422. struct timeb t;
  16423. memset((void*)&t, 0, sizeof(t));
  16424. #ifdef __BORLANDC__
  16425. ::ftime(&t);
  16426. #else
  16427. ftime(&t);
  16428. #endif
  16429. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
  16430. if (l)
  16431. (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, 7), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
  16432. }
  16433. #endif
  16434. #elif defined(HAVE_LOCALTIME_R)
  16435. if (localtime_r(&n, pT) != SOAP_FUNC_R_ERR)
  16436. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
  16437. #else
  16438. pT = localtime(&n);
  16439. if (pT)
  16440. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
  16441. #endif
  16442. if (!l)
  16443. soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "1969-12-31T23:59:59Z");
  16444. return soap->tmpbuf;
  16445. }
  16446. #endif
  16447. /******************************************************************************/
  16448. #ifndef WITH_LEAN
  16449. SOAP_FMAC1
  16450. int
  16451. SOAP_FMAC2
  16452. soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n) {
  16453. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  16454. || soap_string_out(soap, soap_dateTime2s(soap, *p), 0))
  16455. return soap->error;
  16456. return soap_element_end_out(soap, tag);
  16457. }
  16458. #endif
  16459. /******************************************************************************/
  16460. #ifndef WITH_LEAN
  16461. SOAP_FMAC1
  16462. int
  16463. SOAP_FMAC2
  16464. soap_s2dateTime(struct soap *soap, const char *s, time_t *p) {
  16465. *p = 0;
  16466. if (s) {
  16467. char *t;
  16468. unsigned long d;
  16469. struct tm T;
  16470. if (!*s)
  16471. return soap->error = SOAP_EMPTY;
  16472. memset((void *) &T, 0, sizeof(T));
  16473. d = soap_strtoul(s, &t, 10);
  16474. if (*t == '-') {
  16475. /* YYYY-MM-DD */
  16476. T.tm_year = (int) d;
  16477. T.tm_mon = (int) soap_strtoul(t + 1, &t, 10);
  16478. T.tm_mday = (int) soap_strtoul(t + 1, &t, 10);
  16479. } else if (!(soap->mode & SOAP_XML_STRICT)) {
  16480. /* YYYYMMDD */
  16481. T.tm_year = (int) (d / 10000);
  16482. T.tm_mon = (int) (d / 100 % 100);
  16483. T.tm_mday = (int) (d % 100);
  16484. } else {
  16485. return soap->error = SOAP_TYPE;
  16486. }
  16487. if (*t == 'T' || ((*t == 't' || *t == ' ') && !(soap->mode & SOAP_XML_STRICT))) {
  16488. d = soap_strtoul(t + 1, &t, 10);
  16489. if (*t == ':') {
  16490. /* Thh:mm:ss */
  16491. T.tm_hour = (int) d;
  16492. T.tm_min = (int) soap_strtoul(t + 1, &t, 10);
  16493. T.tm_sec = (int) soap_strtoul(t + 1, &t, 10);
  16494. } else if (!(soap->mode & SOAP_XML_STRICT)) {
  16495. /* Thhmmss */
  16496. T.tm_hour = (int) (d / 10000);
  16497. T.tm_min = (int) (d / 100 % 100);
  16498. T.tm_sec = (int) (d % 100);
  16499. } else {
  16500. return soap->error = SOAP_TYPE;
  16501. }
  16502. }
  16503. if (T.tm_year == 1)
  16504. T.tm_year = 70;
  16505. else
  16506. T.tm_year -= 1900;
  16507. T.tm_mon--;
  16508. if (*t == '.') {
  16509. for (t++; *t; t++)
  16510. if (*t < '0' || *t > '9')
  16511. break;
  16512. }
  16513. if (*t == ' ' && !(soap->mode & SOAP_XML_STRICT))
  16514. t++;
  16515. if (*t) {
  16516. #ifndef WITH_NOZONE
  16517. if (*t == '+' || *t == '-') {
  16518. int h, m;
  16519. m = (int) soap_strtol(t, &t, 10);
  16520. if (*t == ':') {
  16521. /* +hh:mm */
  16522. h = m;
  16523. m = (int) soap_strtol(t + 1, &t, 10);
  16524. if (h < 0)
  16525. m = -m;
  16526. } else if (!(soap->mode & SOAP_XML_STRICT)) {
  16527. /* +hhmm */
  16528. h = m / 100;
  16529. m = m % 100;
  16530. } else {
  16531. /* +hh */
  16532. h = m;
  16533. m = 0;
  16534. }
  16535. if (*t)
  16536. return soap->error = SOAP_TYPE;
  16537. T.tm_min -= m;
  16538. T.tm_hour -= h;
  16539. /* put hour and min in range */
  16540. T.tm_hour += T.tm_min / 60;
  16541. T.tm_min %= 60;
  16542. if (T.tm_min < 0) {
  16543. T.tm_min += 60;
  16544. T.tm_hour--;
  16545. }
  16546. T.tm_mday += T.tm_hour / 24;
  16547. T.tm_hour %= 24;
  16548. if (T.tm_hour < 0) {
  16549. T.tm_hour += 24;
  16550. T.tm_mday--;
  16551. }
  16552. /* note: day of the month may be out of range, timegm() handles it */
  16553. } else if (*t != 'Z') {
  16554. return soap->error = SOAP_TYPE;
  16555. }
  16556. #endif
  16557. *p = soap_timegm(&T);
  16558. } else /* no UTC or timezone, so assume we got a localtime */
  16559. {
  16560. T.tm_isdst = -1;
  16561. *p = mktime(&T);
  16562. }
  16563. }
  16564. return soap->error;
  16565. }
  16566. #endif
  16567. /******************************************************************************/
  16568. #ifndef WITH_LEAN
  16569. SOAP_FMAC1
  16570. time_t *
  16571. SOAP_FMAC2
  16572. soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t) {
  16573. if (soap_element_begin_in(soap, tag, 0, NULL))
  16574. return NULL;
  16575. if (*soap->type
  16576. && soap_match_tag(soap, soap->type, type)
  16577. && soap_match_tag(soap, soap->type, ":dateTime")) {
  16578. soap->error = SOAP_TYPE;
  16579. soap_revert(soap);
  16580. return NULL;
  16581. }
  16582. p = (time_t *) soap_id_enter(soap, soap->id, p, t, sizeof(time_t), NULL, NULL, NULL, NULL);
  16583. if (!p)
  16584. return NULL;
  16585. if (*soap->href != '#') {
  16586. int err = soap_s2dateTime(soap, soap_value(soap), p);
  16587. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  16588. return NULL;
  16589. } else {
  16590. p = (time_t *) soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(time_t), 0, NULL, NULL);
  16591. if (soap->body && soap_element_end_in(soap, tag))
  16592. return NULL;
  16593. }
  16594. return p;
  16595. }
  16596. #endif
  16597. /******************************************************************************/
  16598. SOAP_FMAC1
  16599. int
  16600. SOAP_FMAC2
  16601. soap_outliteral(struct soap *soap, const char *tag, char *const *p, const char *type) {
  16602. if (tag && *tag != '-')
  16603. if (soap_element_begin_out(soap, tag, 0, type))
  16604. return soap->error;
  16605. if (p && *p)
  16606. if (soap_send(soap, *p)) /* send as-is */
  16607. return soap->error;
  16608. if (tag && *tag != '-')
  16609. return soap_element_end_out(soap, tag);
  16610. return SOAP_OK;
  16611. }
  16612. /******************************************************************************/
  16613. SOAP_FMAC1
  16614. char **
  16615. SOAP_FMAC2
  16616. soap_inliteral(struct soap *soap, const char *tag, char **p) {
  16617. if (soap_element_begin_in(soap, tag, 1, NULL)) {
  16618. if (soap->error != SOAP_NO_TAG || soap_peek(soap) == SOAP_TT)
  16619. return NULL;
  16620. soap->error = SOAP_OK;
  16621. }
  16622. if (!p) {
  16623. p = (char **) soap_malloc(soap, sizeof(char *));
  16624. if (!p)
  16625. return NULL;
  16626. }
  16627. if (soap->body || (tag && *tag == '-')) {
  16628. if (tag && *tag != '-')
  16629. *p = soap_string_in(soap, -1, -1, -1, NULL);
  16630. else
  16631. *p = soap_string_in(soap, 0, -1, -1, NULL);
  16632. if (!*p)
  16633. return NULL;
  16634. if (!**p && tag && *tag == '-') {
  16635. soap->error = SOAP_NO_TAG;
  16636. return NULL;
  16637. }
  16638. } else if (soap->null) {
  16639. *p = NULL;
  16640. } else {
  16641. *p = soap_strdup(soap, SOAP_STR_EOS);
  16642. }
  16643. if (soap->body && soap_element_end_in(soap, tag))
  16644. return NULL;
  16645. return p;
  16646. }
  16647. /******************************************************************************/
  16648. #ifndef WITH_LEANER
  16649. SOAP_FMAC1
  16650. int
  16651. SOAP_FMAC2
  16652. soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const *p, const char *type) {
  16653. if (tag && *tag != '-')
  16654. if (soap_element_begin_out(soap, tag, 0, type))
  16655. return soap->error;
  16656. if (p) {
  16657. wchar_t c;
  16658. const wchar_t *s = *p;
  16659. while ((c = *s++)) {
  16660. if (soap_pututf8(soap, (unsigned long) c)) /* send as-is in UTF8 */
  16661. return soap->error;
  16662. }
  16663. }
  16664. if (tag && *tag != '-')
  16665. return soap_element_end_out(soap, tag);
  16666. return SOAP_OK;
  16667. }
  16668. #endif
  16669. /******************************************************************************/
  16670. #ifndef WITH_LEANER
  16671. SOAP_FMAC1
  16672. wchar_t **
  16673. SOAP_FMAC2
  16674. soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p) {
  16675. if (soap_element_begin_in(soap, tag, 1, NULL)) {
  16676. if (soap->error != SOAP_NO_TAG || soap_peek(soap) == SOAP_TT)
  16677. return NULL;
  16678. soap->error = SOAP_OK;
  16679. }
  16680. if (!p) {
  16681. p = (wchar_t **) soap_malloc(soap, sizeof(wchar_t *));
  16682. if (!p)
  16683. return NULL;
  16684. }
  16685. if (soap->body) {
  16686. if (tag && *tag != '-')
  16687. *p = soap_wstring_in(soap, -1, -1, -1, NULL);
  16688. else
  16689. *p = soap_wstring_in(soap, 0, -1, -1, NULL);
  16690. if (!*p)
  16691. return NULL;
  16692. if (!**p && tag && *tag == '-') {
  16693. soap->error = SOAP_NO_TAG;
  16694. return NULL;
  16695. }
  16696. } else if (tag && *tag == '-') {
  16697. soap->error = SOAP_NO_TAG;
  16698. return NULL;
  16699. } else if (soap->null) {
  16700. *p = NULL;
  16701. } else {
  16702. *p = soap_wstrdup(soap, L"");
  16703. }
  16704. if (soap->body && soap_element_end_in(soap, tag))
  16705. return NULL;
  16706. return p;
  16707. }
  16708. #endif
  16709. /******************************************************************************/
  16710. SOAP_FMAC1
  16711. const char *
  16712. SOAP_FMAC2
  16713. soap_value(struct soap *soap) {
  16714. size_t i;
  16715. soap_wchar c = 0;
  16716. char *s = soap->tmpbuf;
  16717. if (!soap->body)
  16718. return SOAP_STR_EOS;
  16719. do {
  16720. c = soap_get(soap);
  16721. } while (soap_coblank(c));
  16722. for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++) {
  16723. if (c == SOAP_TT || c == SOAP_LT || (int) c == EOF)
  16724. break;
  16725. *s++ = (char) c;
  16726. c = soap_get(soap);
  16727. }
  16728. for (s--; i > 0; i--, s--) {
  16729. if (!soap_coblank((soap_wchar) *s))
  16730. break;
  16731. }
  16732. s[1] = '\0';
  16733. soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0'; /* appease */
  16734. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf));
  16735. if (c == SOAP_TT || c == SOAP_LT || (int) c == EOF) {
  16736. soap_unget(soap, c);
  16737. } else {
  16738. soap->error = SOAP_LENGTH;
  16739. return NULL;
  16740. }
  16741. #ifdef WITH_DOM
  16742. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  16743. {
  16744. soap->dom->text = soap_strdup(soap, soap->tmpbuf);
  16745. if (!soap->dom->text)
  16746. return NULL;
  16747. }
  16748. #endif
  16749. return soap->tmpbuf; /* return non-null pointer */
  16750. }
  16751. /******************************************************************************/
  16752. #if !defined(WITH_LEANER) || !defined(WITH_NOHTTP)
  16753. SOAP_FMAC1
  16754. int
  16755. SOAP_FMAC2
  16756. soap_getline(struct soap *soap, char *buf, int len) {
  16757. char *s = buf;
  16758. int i = len;
  16759. soap_wchar c = 0;
  16760. for (;;) {
  16761. while (i > 1) {
  16762. c = soap_getchar(soap);
  16763. if (c == '\r' || c == '\n')
  16764. break;
  16765. if ((int) c == EOF)
  16766. return soap->error = SOAP_CHK_EOF;
  16767. *s++ = (char) c;
  16768. i--;
  16769. }
  16770. *s = '\0';
  16771. if (c != '\n')
  16772. c = soap_getchar(soap); /* got \r or something else, now get \n */
  16773. if (c == '\n') {
  16774. if (i == len) /* empty line: end of HTTP/MIME header */
  16775. break;
  16776. c = soap_get0(soap);
  16777. if (c != ' ' && c != '\t') /* HTTP line continuation? */
  16778. break;
  16779. } else if ((int) c == EOF) {
  16780. return soap->error = SOAP_CHK_EOF;
  16781. } else if (i <= 1) {
  16782. return soap->error = SOAP_HDR;
  16783. }
  16784. }
  16785. return SOAP_OK;
  16786. }
  16787. #endif
  16788. /******************************************************************************/
  16789. static ULONG64
  16790. soap_count_attachments(struct soap *soap) {
  16791. #ifndef WITH_LEANER
  16792. struct soap_multipart *content;
  16793. ULONG64 count = soap->count;
  16794. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count="
  16795. SOAP_ULONG_FORMAT
  16796. "\n", count));
  16797. if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) {
  16798. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n"));
  16799. for (content = soap->dime.first; content; content = content->next) {
  16800. count += 12 + ((content->size + 3) & (~3));
  16801. if (content->id)
  16802. count += ((strlen(content->id) + 3) & (~3));
  16803. if (content->type)
  16804. count += ((strlen(content->type) + 3) & (~3));
  16805. if (content->options)
  16806. count += ((((unsigned char) content->options[2] << 8) | ((unsigned char) content->options[3])) + 7) &
  16807. (~3);
  16808. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n",
  16809. (unsigned long) content->size));
  16810. }
  16811. }
  16812. if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary) {
  16813. size_t n = strlen(soap->mime.boundary);
  16814. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n"));
  16815. for (content = soap->mime.first; content; content = content->next) {
  16816. const char *s;
  16817. /* count \r\n--boundary\r\n */
  16818. count += 6 + n;
  16819. /* count Content-Type: ...\r\n */
  16820. if (content->type)
  16821. count += 16 + strlen(content->type);
  16822. /* count Content-Transfer-Encoding: ...\r\n */
  16823. s = soap_code_str(mime_codes, content->encoding);
  16824. if (s)
  16825. count += 29 + strlen(s);
  16826. /* count Content-ID: ...\r\n */
  16827. if (content->id)
  16828. count += 14 + strlen(content->id);
  16829. /* count Content-Location: ...\r\n */
  16830. if (content->location)
  16831. count += 20 + strlen(content->location);
  16832. /* count Content-Description: ...\r\n */
  16833. if (content->description)
  16834. count += 23 + strlen(content->description);
  16835. /* count \r\n...content */
  16836. count += 2 + content->size;
  16837. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n",
  16838. (unsigned long) content->size));
  16839. }
  16840. /* count \r\n--boundary-- */
  16841. count += 6 + n;
  16842. }
  16843. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count="
  16844. SOAP_ULONG_FORMAT
  16845. "\n", count));
  16846. return count;
  16847. #else
  16848. return soap->count;
  16849. #endif
  16850. }
  16851. /******************************************************************************/
  16852. #ifndef WITH_LEANER
  16853. static int
  16854. soap_putdimefield(struct soap *soap, const char *s, size_t n) {
  16855. if (soap_send_raw(soap, s, n))
  16856. return soap->error;
  16857. return soap_send_raw(soap, SOAP_STR_PADDING, -(long) n & 3);
  16858. }
  16859. #endif
  16860. /******************************************************************************/
  16861. #ifndef WITH_LEANER
  16862. SOAP_FMAC1
  16863. char *
  16864. SOAP_FMAC2
  16865. soap_dime_option(struct soap *soap, unsigned short optype, const char *option) {
  16866. size_t n;
  16867. char *s = NULL;
  16868. if (option) {
  16869. n = strlen(option);
  16870. s = (char *) soap_malloc(soap, n + 5);
  16871. if (s) {
  16872. s[0] = (char) (optype >> 8);
  16873. s[1] = (char) (optype & 0xFF);
  16874. s[2] = (char) (n >> 8);
  16875. s[3] = (char) (n & 0xFF);
  16876. soap_strcpy(s + 4, n + 1, option);
  16877. }
  16878. }
  16879. return s;
  16880. }
  16881. #endif
  16882. /******************************************************************************/
  16883. #ifndef WITH_LEANER
  16884. SOAP_FMAC1
  16885. int
  16886. SOAP_FMAC2
  16887. soap_putdimehdr(struct soap *soap) {
  16888. unsigned char tmp[12];
  16889. size_t optlen = 0, idlen = 0, typelen = 0;
  16890. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id ? soap->dime.id : SOAP_STR_EOS));
  16891. if (soap->dime.options)
  16892. optlen = (((unsigned char) soap->dime.options[2] << 8) | ((unsigned char) soap->dime.options[3])) + 4;
  16893. if (soap->dime.id) {
  16894. idlen = strlen(soap->dime.id);
  16895. if (idlen > 0x0000FFFF)
  16896. idlen = 0x0000FFFF;
  16897. }
  16898. if (soap->dime.type) {
  16899. typelen = strlen(soap->dime.type);
  16900. if (typelen > 0x0000FFFF)
  16901. typelen = 0x0000FFFF;
  16902. }
  16903. tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7);
  16904. tmp[1] = soap->dime.flags & 0xF0;
  16905. tmp[2] = (char) (optlen >> 8);
  16906. tmp[3] = (char) (optlen & 0xFF);
  16907. tmp[4] = (char) (idlen >> 8);
  16908. tmp[5] = (char) (idlen & 0xFF);
  16909. tmp[6] = (char) (typelen >> 8);
  16910. tmp[7] = (char) (typelen & 0xFF);
  16911. tmp[8] = (char) (soap->dime.size >> 24);
  16912. tmp[9] = (char) ((soap->dime.size >> 16) & 0xFF);
  16913. tmp[10] = (char) ((soap->dime.size >> 8) & 0xFF);
  16914. tmp[11] = (char) (soap->dime.size & 0xFF);
  16915. if (soap_send_raw(soap, (char *) tmp, 12)
  16916. || soap_putdimefield(soap, soap->dime.options, optlen)
  16917. || soap_putdimefield(soap, soap->dime.id, idlen)
  16918. || soap_putdimefield(soap, soap->dime.type, typelen))
  16919. return soap->error;
  16920. return SOAP_OK;
  16921. }
  16922. #endif
  16923. /******************************************************************************/
  16924. #ifndef WITH_LEANER
  16925. SOAP_FMAC1
  16926. int
  16927. SOAP_FMAC2
  16928. soap_putdime(struct soap *soap) {
  16929. struct soap_multipart *content;
  16930. if (!(soap->mode & SOAP_ENC_DIME))
  16931. return SOAP_OK;
  16932. for (content = soap->dime.first; content; content = content->next) {
  16933. void *handle;
  16934. soap->dime.size = content->size;
  16935. soap->dime.id = content->id;
  16936. soap->dime.type = content->type;
  16937. soap->dime.options = content->options;
  16938. soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA;
  16939. if (soap->fdimereadopen &&
  16940. ((handle = soap->fdimereadopen(soap, (void *) content->ptr, content->id, content->type,
  16941. content->options)) != NULL || soap->error)) {
  16942. size_t size = content->size;
  16943. if (!handle) {
  16944. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n"));
  16945. return soap->error;
  16946. }
  16947. if (!size && ((soap->mode & SOAP_ENC_PLAIN) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK ||
  16948. (soap->mode & SOAP_IO) == SOAP_IO_STORE)) {
  16949. size_t chunksize = sizeof(soap->tmpbuf);
  16950. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n"));
  16951. do {
  16952. size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize);
  16953. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long) size));
  16954. if (size < chunksize) {
  16955. soap->dime.flags &= ~SOAP_DIME_CF;
  16956. if (!content->next)
  16957. soap->dime.flags |= SOAP_DIME_ME;
  16958. } else {
  16959. soap->dime.flags |= SOAP_DIME_CF;
  16960. }
  16961. soap->dime.size = size;
  16962. if (soap_putdimehdr(soap)
  16963. || soap_putdimefield(soap, soap->tmpbuf, size))
  16964. break;
  16965. if (soap->dime.id) {
  16966. soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA);
  16967. soap->dime.id = NULL;
  16968. soap->dime.type = NULL;
  16969. soap->dime.options = NULL;
  16970. }
  16971. } while (size >= chunksize);
  16972. } else {
  16973. if (!content->next)
  16974. soap->dime.flags |= SOAP_DIME_ME;
  16975. if (soap_putdimehdr(soap))
  16976. return soap->error;
  16977. do {
  16978. size_t bufsize;
  16979. if (size < sizeof(soap->tmpbuf))
  16980. bufsize = size;
  16981. else
  16982. bufsize = sizeof(soap->tmpbuf);
  16983. bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize);
  16984. if (!bufsize) {
  16985. DBGLOG(TEST, SOAP_MESSAGE(fdebug,
  16986. "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n",
  16987. (unsigned long) size, (unsigned long) content->size));
  16988. soap->error = SOAP_CHK_EOF;
  16989. break;
  16990. }
  16991. if (soap_send_raw(soap, soap->tmpbuf, bufsize))
  16992. break;
  16993. size -= bufsize;
  16994. } while (size);
  16995. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
  16996. if (soap_send_raw(soap, SOAP_STR_PADDING, -(long) soap->dime.size & 3))
  16997. return soap->error;
  16998. }
  16999. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
  17000. if (soap->fdimereadclose)
  17001. soap->fdimereadclose(soap, handle);
  17002. } else {
  17003. if (!content->next)
  17004. soap->dime.flags |= SOAP_DIME_ME;
  17005. if (soap_putdimehdr(soap)
  17006. || soap_putdimefield(soap, (char *) content->ptr, content->size))
  17007. return soap->error;
  17008. }
  17009. }
  17010. return SOAP_OK;
  17011. }
  17012. #endif
  17013. /******************************************************************************/
  17014. #ifndef WITH_LEANER
  17015. static char *
  17016. soap_getdimefield(struct soap *soap, size_t n) {
  17017. char *p = NULL;
  17018. if (n > 0) {
  17019. p = (char *) soap_malloc(soap, n + 1 > n ? n + 1 : n);
  17020. if (p) {
  17021. char *s = p;
  17022. size_t i;
  17023. for (i = n; i > 0; i--) {
  17024. soap_wchar c = soap_get1(soap);
  17025. if ((int) c == EOF) {
  17026. soap->error = SOAP_CHK_EOF;
  17027. return NULL;
  17028. }
  17029. *s++ = (char) c;
  17030. }
  17031. if (n + 1 > n)
  17032. *s = '\0'; /* force NUL terminated */
  17033. soap->error = soap_move(soap, (size_t) (-(long) n & 3));
  17034. if (soap->error)
  17035. return NULL;
  17036. } else {
  17037. soap->error = SOAP_EOM;
  17038. }
  17039. }
  17040. return p;
  17041. }
  17042. #endif
  17043. /******************************************************************************/
  17044. #ifndef WITH_LEANER
  17045. SOAP_FMAC1
  17046. int
  17047. SOAP_FMAC2
  17048. soap_getdimehdr(struct soap *soap) {
  17049. soap_wchar c;
  17050. char *s;
  17051. int i;
  17052. unsigned char tmp[12];
  17053. size_t optlen, idlen, typelen;
  17054. if (!(soap->mode & SOAP_ENC_DIME))
  17055. return soap->error = SOAP_DIME_END;
  17056. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n"));
  17057. s = (char *) tmp;
  17058. for (i = 12; i > 0; i--) {
  17059. c = soap_getchar(soap);
  17060. if ((int) c == EOF)
  17061. return soap->error = SOAP_CHK_EOF;
  17062. *s++ = (char) c;
  17063. }
  17064. if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION)
  17065. return soap->error = SOAP_DIME_MISMATCH;
  17066. soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0);
  17067. optlen = (tmp[2] << 8) | tmp[3];
  17068. idlen = (tmp[4] << 8) | tmp[5];
  17069. typelen = (tmp[6] << 8) | tmp[7];
  17070. soap->dime.size = ((size_t) tmp[8] << 24) | ((size_t) tmp[9] << 16) | ((size_t) tmp[10] << 8) | ((size_t) tmp[11]);
  17071. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long) soap->dime.size, soap->dime.flags));
  17072. soap->dime.options = soap_getdimefield(soap, optlen);
  17073. if (!soap->dime.options && soap->error)
  17074. return soap->error;
  17075. soap->dime.id = soap_getdimefield(soap, idlen);
  17076. if (!soap->dime.id && soap->error)
  17077. return soap->error;
  17078. soap->dime.type = soap_getdimefield(soap, typelen);
  17079. if (!soap->dime.type && soap->error)
  17080. return soap->error;
  17081. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME flags=%x id='%s', type='%s', options='%s'\n", soap->dime.flags,
  17082. soap->dime.id ? soap->dime.id : SOAP_STR_EOS, soap->dime.type ? soap->dime.type : "",
  17083. soap->dime.options ? soap->dime.options + 4 : SOAP_STR_EOS));
  17084. if ((soap->dime.flags & SOAP_DIME_ME))
  17085. soap->mode &= ~SOAP_ENC_DIME;
  17086. return SOAP_OK;
  17087. }
  17088. #endif
  17089. /******************************************************************************/
  17090. #ifndef WITH_LEANER
  17091. SOAP_FMAC1
  17092. int
  17093. SOAP_FMAC2
  17094. soap_getdime(struct soap *soap) {
  17095. if (soap->dime.buflen || soap->dime.chunksize) {
  17096. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip remainder of SOAP in DIME (%u bytes or %u bytes in chunk left)\n",
  17097. (unsigned int) soap->dime.buflen, (unsigned int) soap->dime.chunksize));
  17098. do
  17099. if (soap_get1(soap) == (int) EOF)
  17100. return soap->error = SOAP_CHK_EOF;
  17101. while (soap->dime.buflen || soap->dime.chunksize);
  17102. if (soap_move(soap, (size_t) (-(long) soap->dime.size & 3)))
  17103. return soap->error = SOAP_CHK_EOF;
  17104. if (!(soap->mode & SOAP_ENC_DIME))
  17105. return SOAP_OK;
  17106. } else {
  17107. if (soap_move(soap, (size_t) (((soap->dime.size + 3) & (~3)) - soap_tell(soap))))
  17108. return soap->error = SOAP_CHK_EOF;
  17109. }
  17110. for (;;) {
  17111. struct soap_multipart *content;
  17112. if (soap_getdimehdr(soap))
  17113. break;
  17114. if (soap->fdimewriteopen &&
  17115. ((soap->dime.ptr = (char *) soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type,
  17116. soap->dime.options)) != NULL || soap->error)) {
  17117. const char *id, *type, *options;
  17118. size_t size, n;
  17119. if (!soap->dime.ptr)
  17120. return soap->error;
  17121. id = soap->dime.id;
  17122. type = soap->dime.type;
  17123. options = soap->dime.options;
  17124. for (;;) {
  17125. size = soap->dime.size;
  17126. for (;;) {
  17127. n = soap->buflen - soap->bufidx;
  17128. if (size < n)
  17129. n = size;
  17130. soap->error = soap->fdimewrite(soap, (void *) soap->dime.ptr, soap->buf + soap->bufidx, n);
  17131. if (soap->error)
  17132. break;
  17133. size -= n;
  17134. if (!size) {
  17135. soap->bufidx += n;
  17136. break;
  17137. }
  17138. if (soap_recv(soap)) {
  17139. soap->error = SOAP_EOF;
  17140. goto end;
  17141. }
  17142. }
  17143. if (soap_move(soap, (size_t) (-(long) soap->dime.size & 3))) {
  17144. soap->error = SOAP_EOF;
  17145. break;
  17146. }
  17147. if (!(soap->dime.flags & SOAP_DIME_CF))
  17148. break;
  17149. if (soap_getdimehdr(soap))
  17150. break;
  17151. }
  17152. end:
  17153. if (soap->fdimewriteclose)
  17154. soap->fdimewriteclose(soap, (void *) soap->dime.ptr);
  17155. soap->dime.size = 0;
  17156. soap->dime.id = id;
  17157. soap->dime.type = type;
  17158. soap->dime.options = options;
  17159. } else if ((soap->dime.flags & SOAP_DIME_CF)) {
  17160. const char *id, *type, *options;
  17161. id = soap->dime.id;
  17162. type = soap->dime.type;
  17163. options = soap->dime.options;
  17164. if (soap_alloc_block(soap) == NULL)
  17165. return soap->error = SOAP_EOM;
  17166. for (;;) {
  17167. soap_wchar c;
  17168. size_t i;
  17169. char *s;
  17170. if (soap->dime.size > SOAP_MAXDIMESIZE) {
  17171. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu exceeds SOAP_MAXDIMESIZE=%lu\n",
  17172. (unsigned long) soap->dime.size, (unsigned long) SOAP_MAXDIMESIZE));
  17173. return soap->error = SOAP_DIME_ERROR;
  17174. }
  17175. s = (char *) soap_push_block(soap, NULL, soap->dime.size);
  17176. if (!s)
  17177. return soap->error = SOAP_EOM;
  17178. for (i = soap->dime.size; i > 0; i--) {
  17179. c = soap_get1(soap);
  17180. if ((int) c == EOF)
  17181. return soap->error = SOAP_EOF;
  17182. *s++ = (char) c;
  17183. }
  17184. if (soap_move(soap, (size_t) (-(long) soap->dime.size & 3)))
  17185. return soap->error = SOAP_EOF;
  17186. if (!(soap->dime.flags & SOAP_DIME_CF))
  17187. break;
  17188. if (soap_getdimehdr(soap))
  17189. return soap->error;
  17190. }
  17191. soap->dime.size = soap->blist->size;
  17192. if (soap->dime.size + 1 > soap->dime.size)
  17193. soap->blist->size++; /* allocate one more byte in blist for the terminating '\0' */
  17194. soap->dime.ptr = soap_save_block(soap, NULL, NULL, 0);
  17195. if (!soap->dime.ptr)
  17196. return soap->error;
  17197. if (soap->dime.size + 1 > soap->dime.size)
  17198. soap->dime.ptr[soap->dime.size] = '\0'; /* make 0-terminated, just in case even though this is binary data */
  17199. soap->dime.id = id;
  17200. soap->dime.type = type;
  17201. soap->dime.options = options;
  17202. } else {
  17203. soap->dime.ptr = soap_getdimefield(soap, soap->dime.size);
  17204. }
  17205. content = soap_alloc_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size);
  17206. if (!content)
  17207. return soap->error = SOAP_EOM;
  17208. content->id = soap->dime.id;
  17209. content->type = soap->dime.type;
  17210. content->options = soap->dime.options;
  17211. if (soap->error)
  17212. return soap->error;
  17213. soap_resolve_attachment(soap, content);
  17214. }
  17215. if (soap->error != SOAP_DIME_END)
  17216. return soap->error;
  17217. return soap->error = SOAP_OK;
  17218. }
  17219. #endif
  17220. /******************************************************************************/
  17221. #ifndef WITH_LEANER
  17222. SOAP_FMAC1
  17223. int
  17224. SOAP_FMAC2
  17225. soap_getmimehdr(struct soap *soap) {
  17226. struct soap_multipart *content;
  17227. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get MIME header\n"));
  17228. do {
  17229. if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
  17230. return soap->error;
  17231. } while (!*soap->msgbuf);
  17232. if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-') {
  17233. char *s = soap->msgbuf + strlen(soap->msgbuf) - 1;
  17234. /* remove white space */
  17235. while (soap_coblank((soap_wchar) *s))
  17236. s--;
  17237. s[1] = '\0';
  17238. if (soap->mime.boundary) {
  17239. if (strcmp(soap->msgbuf + 2, soap->mime.boundary))
  17240. return soap->error = SOAP_MIME_ERROR;
  17241. } else {
  17242. soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2);
  17243. if (!soap->mime.boundary)
  17244. return soap->error = SOAP_EOM;
  17245. }
  17246. if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
  17247. return soap->error;
  17248. }
  17249. if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL))
  17250. return soap->error = SOAP_EOM;
  17251. content = soap->mime.last;
  17252. for (;;) {
  17253. char *key = soap->msgbuf;
  17254. char *val;
  17255. if (!*key)
  17256. break;
  17257. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME header: %s\n", key));
  17258. val = strchr(soap->msgbuf, ':');
  17259. if (val) {
  17260. *val = '\0';
  17261. do {
  17262. val++;
  17263. } while (*val && *val <= 32);
  17264. if (!soap_tag_cmp(key, "Content-ID"))
  17265. content->id = soap_strdup(soap, val);
  17266. else if (!soap_tag_cmp(key, "Content-Location"))
  17267. content->location = soap_strdup(soap, val);
  17268. else if (!content->id && !soap_tag_cmp(key, "Content-Disposition"))
  17269. content->id = soap_strdup(soap, soap_http_header_attribute(soap, val, "name"));
  17270. else if (!soap_tag_cmp(key, "Content-Type"))
  17271. content->type = soap_strdup(soap, val);
  17272. else if (!soap_tag_cmp(key, "Content-Description"))
  17273. content->description = soap_strdup(soap, val);
  17274. else if (!soap_tag_cmp(key, "Content-Transfer-Encoding"))
  17275. content->encoding = (enum soap_mime_encoding) soap_code_int(mime_codes, val, (LONG64) SOAP_MIME_NONE);
  17276. }
  17277. if (soap_getline(soap, key, sizeof(soap->msgbuf)))
  17278. return soap->error;
  17279. }
  17280. return SOAP_OK;
  17281. }
  17282. #endif
  17283. /******************************************************************************/
  17284. #ifndef WITH_LEANER
  17285. SOAP_FMAC1
  17286. int
  17287. SOAP_FMAC2
  17288. soap_getmime(struct soap *soap) {
  17289. while (soap_recv_mime_attachment(soap, NULL))
  17290. continue;
  17291. return soap->error;
  17292. }
  17293. #endif
  17294. /******************************************************************************/
  17295. #ifndef WITH_LEANER
  17296. SOAP_FMAC1
  17297. void
  17298. SOAP_FMAC2
  17299. soap_post_check_mime_attachments(struct soap *soap) {
  17300. soap->imode |= SOAP_MIME_POSTCHECK;
  17301. }
  17302. #endif
  17303. /******************************************************************************/
  17304. #ifndef WITH_LEANER
  17305. SOAP_FMAC1
  17306. int
  17307. SOAP_FMAC2
  17308. soap_check_mime_attachments(struct soap *soap) {
  17309. if ((soap->mode & SOAP_MIME_POSTCHECK))
  17310. return soap_recv_mime_attachment(soap, NULL) != NULL;
  17311. return SOAP_OK;
  17312. }
  17313. #endif
  17314. /******************************************************************************/
  17315. #ifndef WITH_LEANER
  17316. SOAP_FMAC1
  17317. struct soap_multipart *
  17318. SOAP_FMAC2
  17319. soap_recv_mime_attachment(struct soap *soap, void *handle) {
  17320. soap_wchar c = 0;
  17321. size_t i, m = 0;
  17322. char *s, *t = NULL;
  17323. struct soap_multipart *content;
  17324. short flag = 0;
  17325. if (!(soap->mode & SOAP_ENC_MIME))
  17326. return NULL;
  17327. content = soap->mime.last;
  17328. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get MIME (%p)\n", (void *) content));
  17329. if (!content) {
  17330. if (soap_getmimehdr(soap))
  17331. return NULL;
  17332. content = soap->mime.last;
  17333. } else if (content != soap->mime.first) {
  17334. if (soap->fmimewriteopen &&
  17335. ((content->ptr = (char *) soap->fmimewriteopen(soap, (void *) handle, content->id, content->type,
  17336. content->description, content->encoding)) != NULL ||
  17337. soap->error)) {
  17338. if (!content->ptr)
  17339. return NULL;
  17340. }
  17341. }
  17342. DBGLOG(TEST,
  17343. SOAP_MESSAGE(fdebug, "Parsing MIME content id='%s' type='%s'\n", content->id ? content->id : SOAP_STR_EOS,
  17344. content->type ? content->type : SOAP_STR_EOS));
  17345. if (!content->ptr && soap_alloc_block(soap) == NULL) {
  17346. soap->error = SOAP_EOM;
  17347. return NULL;
  17348. }
  17349. for (;;) {
  17350. if (content->ptr) {
  17351. s = soap->tmpbuf;
  17352. } else {
  17353. s = (char *) soap_push_block(soap, NULL, sizeof(soap->tmpbuf));
  17354. if (!s) {
  17355. soap->error = SOAP_EOM;
  17356. return NULL;
  17357. }
  17358. }
  17359. for (i = 0; i < sizeof(soap->tmpbuf); i++) {
  17360. if (m > 0) {
  17361. *s++ = *t++;
  17362. m--;
  17363. } else {
  17364. if (!flag) {
  17365. c = soap_getchar(soap);
  17366. if ((int) c == EOF) {
  17367. if (content->ptr && soap->fmimewriteclose)
  17368. soap->fmimewriteclose(soap, (void *) content->ptr);
  17369. soap->error = SOAP_CHK_EOF;
  17370. return NULL;
  17371. }
  17372. }
  17373. if (flag || c == '\r') {
  17374. memset((void *) soap->msgbuf, 0, sizeof(soap->msgbuf));
  17375. soap_strcpy(soap->msgbuf, sizeof(soap->msgbuf), "\n--");
  17376. if (soap->mime.boundary) {
  17377. if (soap_strncat(soap->msgbuf, sizeof(soap->msgbuf), soap->mime.boundary,
  17378. sizeof(soap->msgbuf) - 4)) {
  17379. soap->error = SOAP_MIME_ERROR;
  17380. return NULL;
  17381. }
  17382. }
  17383. t = soap->msgbuf;
  17384. do {
  17385. c = soap_getchar(soap);
  17386. } while (c == *t++);
  17387. if ((int) c == EOF) {
  17388. if (content->ptr && soap->fmimewriteclose)
  17389. soap->fmimewriteclose(soap, (void *) content->ptr);
  17390. soap->error = SOAP_CHK_EOF;
  17391. return NULL;
  17392. }
  17393. if (!*--t)
  17394. goto end;
  17395. *t = (char) c;
  17396. flag = (c == '\r');
  17397. m = t - soap->msgbuf + 1 - flag;
  17398. t = soap->msgbuf;
  17399. c = '\r';
  17400. }
  17401. *s++ = (char) c;
  17402. }
  17403. }
  17404. if (content->ptr && soap->fmimewrite) {
  17405. soap->error = soap->fmimewrite(soap, (void *) content->ptr, soap->tmpbuf, i);
  17406. if (soap->error)
  17407. break;
  17408. }
  17409. }
  17410. end:
  17411. if (content->ptr) {
  17412. if (!soap->error && soap->fmimewrite)
  17413. soap->error = soap->fmimewrite(soap, (void *) content->ptr, soap->tmpbuf, i);
  17414. if (soap->fmimewriteclose)
  17415. soap->fmimewriteclose(soap, (void *) content->ptr);
  17416. if (soap->error)
  17417. return NULL;
  17418. } else {
  17419. *s = '\0'; /* make 0-terminated, just in case even though this is binary data */
  17420. content->size = soap_size_block(soap, NULL, i + 1) - 1; /* last block with '\0' */
  17421. content->ptr = soap_save_block(soap, NULL, NULL, 0);
  17422. }
  17423. soap_resolve_attachment(soap, content);
  17424. if (c == '-' && soap_getchar(soap) == '-') {
  17425. soap->mode &= ~SOAP_ENC_MIME;
  17426. if ((soap->mode & SOAP_MIME_POSTCHECK) && soap_end_recv(soap)) {
  17427. if (soap->keep_alive == -2) /* special case to keep alive */
  17428. soap->keep_alive = 0;
  17429. soap_closesock(soap);
  17430. return NULL;
  17431. }
  17432. } else {
  17433. while (c != '\r' && (int) c != EOF && soap_coblank(c))
  17434. c = soap_getchar(soap);
  17435. if (c != '\r' || soap_getchar(soap) != '\n') {
  17436. soap->error = SOAP_MIME_ERROR;
  17437. return NULL;
  17438. }
  17439. if (soap_getmimehdr(soap))
  17440. return NULL;
  17441. }
  17442. return content;
  17443. }
  17444. #endif
  17445. /******************************************************************************/
  17446. #ifndef WITH_LEANER
  17447. SOAP_FMAC1
  17448. int
  17449. SOAP_FMAC2
  17450. soap_match_cid(struct soap *soap, const char *s, const char *t) {
  17451. size_t n;
  17452. if (!s)
  17453. return 1;
  17454. if (!strcmp(s, t))
  17455. return 0;
  17456. if (!strncmp(s, "cid:", 4))
  17457. s += 4;
  17458. n = strlen(t);
  17459. if (*t == '<') {
  17460. t++;
  17461. n -= 2;
  17462. }
  17463. if (!strncmp(s, t, n) && !s[n])
  17464. return 0;
  17465. (void) soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS);
  17466. if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n])
  17467. return 0;
  17468. return 1;
  17469. }
  17470. #endif
  17471. /******************************************************************************/
  17472. /* return UUID "<prefix>xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx" in a temporary buffer */
  17473. SOAP_FMAC1
  17474. const char *
  17475. SOAP_FMAC2
  17476. soap_rand_uuid(struct soap *soap, const char *prefix) {
  17477. int r1, r2, r3, r4;
  17478. #ifdef WITH_OPENSSL
  17479. r1 = soap_random;
  17480. r2 = soap_random;
  17481. #else
  17482. size_t i;
  17483. static int k = 0xFACEB00C;
  17484. int lo = k % 127773;
  17485. int hi = k / 127773;
  17486. # if defined(HAVE_GETTIMEOFDAY)
  17487. struct timeval tv;
  17488. gettimeofday(&tv, NULL);
  17489. r1 = 10000000 * tv.tv_sec + tv.tv_usec;
  17490. # elif defined(UNDER_CE)
  17491. r1 = (int)Random();
  17492. # elif !defined(WITH_LEAN)
  17493. r1 = (int)time(NULL);
  17494. # else
  17495. r1 = k;
  17496. # endif
  17497. k = 16807 * lo - 2836 * hi;
  17498. if (k <= 0)
  17499. k += 0x7FFFFFFF;
  17500. r2 = k;
  17501. /* k &= 0x8FFFFFFF; */
  17502. for (i = 0; i < (sizeof(soap->buf) < 16UL ? sizeof(soap->buf) : 16UL); i++)
  17503. r2 += soap->buf[i];
  17504. #endif
  17505. r3 = soap_random;
  17506. r4 = soap_random;
  17507. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), prefix ? strlen(prefix) + 37 : 37),
  17508. "%s%8.8x-%4.4hx-4%3.3hx-%4.4hx-%4.4hx%8.8x", prefix ? prefix : SOAP_STR_EOS, r1, (short) (r2 >> 16),
  17509. (short) (((short) r2 >> 4) & 0x0FFF), (short) (((short) (r3 >> 16) & 0x3FFF) | 0x8000), (short) r3, r4);
  17510. return soap->tmpbuf;
  17511. }
  17512. /******************************************************************************/
  17513. #ifndef WITH_LEANER
  17514. static void
  17515. soap_resolve_attachment(struct soap *soap, struct soap_multipart *content) {
  17516. if (content->id) {
  17517. struct soap_xlist **xp = &soap->xlist;
  17518. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id='%s'\n", content->id));
  17519. while (*xp) {
  17520. struct soap_xlist *xq = *xp;
  17521. if (!soap_match_cid(soap, xq->id, content->id)) {
  17522. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment id='%s' for content id='%s'\n", xq->id,
  17523. content->id));
  17524. *xp = xq->next;
  17525. *xq->ptr = (unsigned char *) content->ptr;
  17526. *xq->size = (int) content->size;
  17527. *xq->type = (char *) content->type;
  17528. if (content->options)
  17529. *xq->options = (char *) content->options;
  17530. else
  17531. *xq->options = (char *) content->description;
  17532. SOAP_FREE(soap, xq);
  17533. } else {
  17534. xp = &(*xp)->next;
  17535. }
  17536. }
  17537. }
  17538. }
  17539. #endif
  17540. /******************************************************************************/
  17541. #ifndef WITH_LEANER
  17542. SOAP_FMAC1
  17543. int
  17544. SOAP_FMAC2
  17545. soap_putmimehdr(struct soap *soap, struct soap_multipart *content) {
  17546. const char *s;
  17547. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type='%s'\n", content->type ? content->type : SOAP_STR_EOS));
  17548. if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n"))
  17549. return soap->error;
  17550. if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n"))
  17551. return soap->error;
  17552. s = soap_code_str(mime_codes, content->encoding);
  17553. if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n"))
  17554. return soap->error;
  17555. if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n"))
  17556. return soap->error;
  17557. if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n"))
  17558. return soap->error;
  17559. if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n"))
  17560. return soap->error;
  17561. return soap_send_raw(soap, "\r\n", 2);
  17562. }
  17563. #endif
  17564. /******************************************************************************/
  17565. #ifndef WITH_LEANER
  17566. SOAP_FMAC1
  17567. int
  17568. SOAP_FMAC2
  17569. soap_putmime(struct soap *soap) {
  17570. struct soap_multipart *content;
  17571. if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary)
  17572. return SOAP_OK;
  17573. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n"));
  17574. for (content = soap->mime.first; content; content = content->next) {
  17575. void *handle;
  17576. if (soap->fmimereadopen &&
  17577. ((handle = soap->fmimereadopen(soap, (void *) content->ptr, content->id, content->type,
  17578. content->description)) != NULL || soap->error)) {
  17579. size_t size = content->size;
  17580. if (!handle) {
  17581. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n"));
  17582. return soap->error;
  17583. }
  17584. if (soap_putmimehdr(soap, content))
  17585. return soap->error;
  17586. if (!size) {
  17587. if ((soap->mode & SOAP_ENC_PLAIN) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK ||
  17588. (soap->mode & SOAP_IO) == SOAP_IO_STORE) {
  17589. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n"));
  17590. do {
  17591. size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf));
  17592. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long) size));
  17593. if (soap_send_raw(soap, soap->tmpbuf, size))
  17594. break;
  17595. } while (size);
  17596. } else {
  17597. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n"));
  17598. }
  17599. } else {
  17600. do {
  17601. size_t bufsize;
  17602. if (size < sizeof(soap->tmpbuf))
  17603. bufsize = size;
  17604. else
  17605. bufsize = sizeof(soap->tmpbuf);
  17606. bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize);
  17607. if (!bufsize) {
  17608. DBGLOG(TEST, SOAP_MESSAGE(fdebug,
  17609. "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n",
  17610. (unsigned long) size, (unsigned long) content->size));
  17611. soap->error = SOAP_EOF;
  17612. break;
  17613. }
  17614. if (soap_send_raw(soap, soap->tmpbuf, bufsize))
  17615. break;
  17616. size -= bufsize;
  17617. } while (size);
  17618. }
  17619. if (soap->fmimereadclose)
  17620. soap->fmimereadclose(soap, handle);
  17621. } else {
  17622. if (soap_putmimehdr(soap, content)
  17623. || soap_send_raw(soap, content->ptr, content->size))
  17624. return soap->error;
  17625. }
  17626. }
  17627. return soap_send3(soap, "\r\n--", soap->mime.boundary, "--");
  17628. }
  17629. #endif
  17630. /******************************************************************************/
  17631. #ifndef WITH_LEANER
  17632. SOAP_FMAC1
  17633. void
  17634. SOAP_FMAC2
  17635. soap_set_dime(struct soap *soap) {
  17636. soap->omode |= SOAP_ENC_DIME;
  17637. soap->dime.first = NULL;
  17638. soap->dime.last = NULL;
  17639. }
  17640. #endif
  17641. /******************************************************************************/
  17642. #ifndef WITH_LEANER
  17643. SOAP_FMAC1
  17644. void
  17645. SOAP_FMAC2
  17646. soap_set_mime(struct soap *soap, const char *boundary, const char *start) {
  17647. soap->omode |= SOAP_ENC_MIME;
  17648. soap->mime.first = NULL;
  17649. soap->mime.last = NULL;
  17650. soap->mime.boundary = soap_strdup(soap, boundary);
  17651. soap->mime.start = soap_strdup(soap, start);
  17652. }
  17653. #endif
  17654. /******************************************************************************/
  17655. #ifndef WITH_LEANER
  17656. SOAP_FMAC1
  17657. void
  17658. SOAP_FMAC2
  17659. soap_clr_dime(struct soap *soap) {
  17660. soap->omode &= ~SOAP_ENC_DIME;
  17661. soap->dime.first = NULL;
  17662. soap->dime.last = NULL;
  17663. }
  17664. #endif
  17665. /******************************************************************************/
  17666. #ifndef WITH_LEANER
  17667. SOAP_FMAC1
  17668. void
  17669. SOAP_FMAC2
  17670. soap_clr_mime(struct soap *soap) {
  17671. soap->omode &= ~SOAP_ENC_MIME;
  17672. soap->mime.first = NULL;
  17673. soap->mime.last = NULL;
  17674. soap->mime.boundary = NULL;
  17675. soap->mime.start = NULL;
  17676. }
  17677. #endif
  17678. /******************************************************************************/
  17679. #ifndef WITH_LEANER
  17680. static int
  17681. soap_begin_attachments(struct soap *soap) {
  17682. if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start) {
  17683. const char *s;
  17684. if (strlen(soap->mime.boundary) + strlen(soap->mime.start) + 140 > sizeof(soap->tmpbuf))
  17685. return soap->error = SOAP_EOM;
  17686. if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) {
  17687. s = "application/dime";
  17688. } else if (soap->version == 2) {
  17689. if ((soap->mode & SOAP_ENC_MTOM))
  17690. s = "application/xop+xml; charset=utf-8; type=\"application/soap+xml\"";
  17691. else
  17692. s = "application/soap+xml; charset=utf-8";
  17693. } else if ((soap->mode & SOAP_ENC_MTOM)) {
  17694. s = "application/xop+xml; charset=utf-8; type=\"text/xml\"";
  17695. } else {
  17696. s = "text/xml; charset=utf-8";
  17697. }
  17698. (SOAP_SNPRINTF_SAFE(soap->tmpbuf, sizeof(soap->tmpbuf)),
  17699. "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n",
  17700. soap->mime.boundary, s, soap->mime.start);
  17701. if (soap_send(soap, soap->tmpbuf))
  17702. return soap->error;
  17703. }
  17704. if ((soap->mode & SOAP_IO_LENGTH))
  17705. soap->dime.size = (size_t) soap->count; /* DIME in MIME correction, soap->count is small */
  17706. if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME)) {
  17707. if (soap_putdimehdr(soap))
  17708. return soap->error;
  17709. }
  17710. return SOAP_OK;
  17711. }
  17712. #endif
  17713. /******************************************************************************/
  17714. #ifndef WITH_LEANER
  17715. static int
  17716. soap_end_attachments(struct soap *soap) {
  17717. if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) {
  17718. if (soap->count > 0xFFFFFFFF)
  17719. return soap->error = SOAP_DIME_ERROR;
  17720. soap->dime.size = (size_t) soap->count - soap->dime.size; /* DIME in MIME correction */
  17721. (SOAP_SNPRINTF(soap->id, sizeof(soap->id), strlen(soap->dime_id_format) + 20), soap->dime_id_format, 0);
  17722. soap->dime.id = soap->id;
  17723. if (soap->local_namespaces && soap->local_namespaces[0].id) {
  17724. if (soap->local_namespaces[0].out)
  17725. soap->dime.type = (char *) soap->local_namespaces[0].out;
  17726. else
  17727. soap->dime.type = (char *) soap->local_namespaces[0].ns;
  17728. }
  17729. soap->dime.options = NULL;
  17730. soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI;
  17731. if (!soap->dime.first)
  17732. soap->dime.flags |= SOAP_DIME_ME;
  17733. soap->count += 12 + ((strlen(soap->dime.id) + 3) & (~3)) +
  17734. (soap->dime.type ? ((strlen(soap->dime.type) + 3) & (~3)) : 0);
  17735. }
  17736. if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
  17737. return soap_send_raw(soap, SOAP_STR_PADDING, -(long) soap->dime.size & 3);
  17738. return SOAP_OK;
  17739. }
  17740. #endif
  17741. /******************************************************************************/
  17742. #ifndef WITH_LEANER
  17743. static struct soap_multipart *
  17744. soap_alloc_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, const char *ptr,
  17745. size_t size) {
  17746. struct soap_multipart *content;
  17747. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New DIME/MIME attachment %p (%lu)\n", (void *) ptr, (unsigned long) size));
  17748. content = (struct soap_multipart *) soap_malloc(soap, sizeof(struct soap_multipart));
  17749. if (content) {
  17750. content->next = NULL;
  17751. content->ptr = ptr;
  17752. content->size = size;
  17753. content->id = NULL;
  17754. content->type = NULL;
  17755. content->options = NULL;
  17756. content->encoding = SOAP_MIME_NONE;
  17757. content->location = NULL;
  17758. content->description = NULL;
  17759. if (!*first)
  17760. *first = content;
  17761. if (*last)
  17762. (*last)->next = content;
  17763. *last = content;
  17764. }
  17765. return content;
  17766. }
  17767. #endif
  17768. /******************************************************************************/
  17769. #ifndef WITH_LEANER
  17770. SOAP_FMAC1
  17771. int
  17772. SOAP_FMAC2
  17773. soap_set_dime_attachment(struct soap *soap, const char *ptr, size_t size, const char *type, const char *id,
  17774. unsigned short optype, const char *option) {
  17775. struct soap_multipart *content = soap_alloc_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size);
  17776. if (!content)
  17777. return SOAP_EOM;
  17778. content->id = soap_strdup(soap, id);
  17779. content->type = soap_strdup(soap, type);
  17780. content->options = soap_dime_option(soap, optype, option);
  17781. return SOAP_OK;
  17782. }
  17783. #endif
  17784. /******************************************************************************/
  17785. #ifndef WITH_LEANER
  17786. SOAP_FMAC1
  17787. int
  17788. SOAP_FMAC2
  17789. soap_set_mime_attachment(struct soap *soap, const char *ptr, size_t size, enum soap_mime_encoding encoding,
  17790. const char *type, const char *id, const char *location, const char *description) {
  17791. struct soap_multipart *content = soap_alloc_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size);
  17792. if (!content)
  17793. return SOAP_EOM;
  17794. content->id = soap_strdup(soap, id);
  17795. content->type = soap_strdup(soap, type);
  17796. content->encoding = encoding;
  17797. content->location = soap_strdup(soap, location);
  17798. content->description = soap_strdup(soap, description);
  17799. return SOAP_OK;
  17800. }
  17801. #endif
  17802. /******************************************************************************/
  17803. #ifndef WITH_LEANER
  17804. SOAP_FMAC1
  17805. struct soap_multipart *
  17806. SOAP_FMAC2
  17807. soap_next_multipart(struct soap_multipart *content) {
  17808. if (content)
  17809. return content->next;
  17810. return NULL;
  17811. }
  17812. #endif
  17813. /******************************************************************************/
  17814. #ifndef WITH_LEANER
  17815. static void
  17816. soap_select_mime_boundary(struct soap *soap) {
  17817. while (!soap->mime.boundary || soap_valid_mime_boundary(soap)) {
  17818. char *s = soap->mime.boundary;
  17819. size_t n = 0;
  17820. if (s)
  17821. n = strlen(s);
  17822. if (n < 16) {
  17823. n = 64;
  17824. s = soap->mime.boundary = (char *) soap_malloc(soap, n + 1);
  17825. if (!s)
  17826. return;
  17827. }
  17828. *s++ = '=';
  17829. *s++ = '=';
  17830. n -= 4;
  17831. while (n) {
  17832. *s++ = soap_base64o[soap_random & 0x3F];
  17833. n--;
  17834. }
  17835. *s++ = '=';
  17836. *s++ = '=';
  17837. *s = '\0';
  17838. }
  17839. if (!soap->mime.start)
  17840. soap->mime.start = "<SOAP-ENV:Envelope>";
  17841. }
  17842. #endif
  17843. /******************************************************************************/
  17844. #ifndef WITH_LEANER
  17845. static int
  17846. soap_valid_mime_boundary(struct soap *soap) {
  17847. struct soap_multipart *content;
  17848. size_t k;
  17849. if (soap->fmimeread)
  17850. return SOAP_OK;
  17851. k = strlen(soap->mime.boundary);
  17852. for (content = soap->mime.first; content; content = content->next) {
  17853. if (content->ptr && content->size >= k) {
  17854. const char *p = (const char *) content->ptr;
  17855. size_t i;
  17856. for (i = 0; i < content->size - k; i++, p++) {
  17857. if (!strncmp(p, soap->mime.boundary, k))
  17858. return SOAP_ERR;
  17859. }
  17860. }
  17861. }
  17862. return SOAP_OK;
  17863. }
  17864. #endif
  17865. /******************************************************************************/
  17866. #ifdef WITH_GZIP
  17867. static int
  17868. soap_getgziphdr(struct soap *soap)
  17869. {
  17870. int i;
  17871. soap_wchar c = 0, f = 0;
  17872. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n"));
  17873. for (i = 0; i < 9; i++)
  17874. {
  17875. c = soap_get1(soap);
  17876. if (i == 1 && c == 8)
  17877. soap->z_dict = 0;
  17878. if (i == 2)
  17879. f = c;
  17880. }
  17881. if (f & 0x04) /* FEXTRA */
  17882. {
  17883. i = soap_get1(soap);
  17884. i |= soap_get1(soap) << 8;
  17885. while (i-- > 0)
  17886. {
  17887. if ((int)soap_get1(soap) == EOF)
  17888. return soap->error = SOAP_ZLIB_ERROR;
  17889. }
  17890. }
  17891. if (f & 0x08) /* skip FNAME */
  17892. {
  17893. do
  17894. {
  17895. c = soap_get1(soap);
  17896. } while (c && (int)c != EOF);
  17897. }
  17898. if ((int)c != EOF && (f & 0x10)) /* skip FCOMMENT */
  17899. {
  17900. do
  17901. {
  17902. c = soap_get1(soap);
  17903. } while (c && (int)c != EOF);
  17904. }
  17905. if ((int)c != EOF && (f & 0x02)) /* skip FHCRC (CRC32 is used) */
  17906. {
  17907. c = soap_get1(soap);
  17908. if ((int)c != EOF)
  17909. c = soap_get1(soap);
  17910. }
  17911. if ((int)c == EOF)
  17912. return soap->error = SOAP_ZLIB_ERROR;
  17913. return SOAP_OK;
  17914. }
  17915. #endif
  17916. /******************************************************************************/
  17917. SOAP_FMAC1
  17918. int
  17919. SOAP_FMAC2
  17920. soap_begin_serve(struct soap *soap) {
  17921. #ifdef WITH_FASTCGI
  17922. if (FCGI_Accept() < 0)
  17923. {
  17924. soap->error = SOAP_EOF;
  17925. return soap_send_fault(soap);
  17926. }
  17927. #endif
  17928. soap_begin(soap);
  17929. if (soap_begin_recv(soap)
  17930. || soap_envelope_begin_in(soap)
  17931. || soap_recv_header(soap)
  17932. || soap_body_begin_in(soap)) {
  17933. if (soap->error < SOAP_STOP) {
  17934. #ifdef WITH_FASTCGI
  17935. (void)soap_send_fault(soap);
  17936. #else
  17937. return soap_send_fault(soap);
  17938. #endif
  17939. }
  17940. return soap_closesock(soap);
  17941. }
  17942. return SOAP_OK;
  17943. }
  17944. /******************************************************************************/
  17945. SOAP_FMAC1
  17946. int
  17947. SOAP_FMAC2
  17948. soap_begin_recv(struct soap *soap) {
  17949. // std::cerr<<"Recieved data Sassan2: "<<soap_getchar(soap)<<std::endl;
  17950. soap_wchar c;
  17951. DBGLOG(TEST,
  17952. SOAP_MESSAGE(fdebug, "Initializing for input from socket=%d/fd=%d\n", (int) soap->socket, soap->recvfd));
  17953. soap->error = SOAP_OK;
  17954. #ifndef WITH_LEANER
  17955. soap->recverror = SOAP_OK;
  17956. #endif
  17957. soap_free_temp(soap);
  17958. soap_set_local_namespaces(soap);
  17959. soap->version = 0; /* don't assume we're parsing SOAP content by default */
  17960. #ifndef WITH_NOIDREF
  17961. soap_free_iht(soap);
  17962. #endif
  17963. if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK) {
  17964. soap->imode &= ~SOAP_IO;
  17965. soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_CHUNK;
  17966. }
  17967. soap->imode &= ~(SOAP_ENC_DIME | SOAP_ENC_MIME | SOAP_ENC_MTOM | SOAP_ENC_ZLIB);
  17968. soap->mode = soap->imode;
  17969. if (!(soap->mode & SOAP_IO_KEEPALIVE))
  17970. soap->keep_alive = 0;
  17971. if (!soap->keep_alive)
  17972. soap->buflen = soap->bufidx = 0;
  17973. soap->null = 0;
  17974. soap->position = 0;
  17975. soap->mustUnderstand = 0;
  17976. soap->shaky = 0;
  17977. soap->ahead = 0;
  17978. soap->peeked = 0;
  17979. soap->level = 0;
  17980. soap->part = SOAP_BEGIN_RECV;
  17981. soap->count = 0;
  17982. soap->length = 0;
  17983. soap->cdata = 0;
  17984. *soap->endpoint = '\0';
  17985. soap->action = NULL;
  17986. soap->header = NULL;
  17987. soap->fault = NULL;
  17988. soap->status = 0;
  17989. soap->fform = NULL;
  17990. soap->body = 1;
  17991. #ifndef WITH_LEANER
  17992. soap->dom = NULL;
  17993. soap->dime.count = 0;
  17994. soap->dime.chunksize = 0;
  17995. soap->dime.buflen = 0;
  17996. soap->dime.list = NULL;
  17997. soap->dime.first = NULL;
  17998. soap->dime.last = NULL;
  17999. soap->mime.list = NULL;
  18000. soap->mime.first = NULL;
  18001. soap->mime.last = NULL;
  18002. soap->mime.boundary = NULL;
  18003. soap->mime.start = NULL;
  18004. #endif
  18005. #ifdef WIN32
  18006. #ifndef UNDER_CE
  18007. #ifndef WITH_FASTCGI
  18008. if (!soap_valid_socket(soap->socket) && !soap->is && soap->recvfd >= 0) /* Set win32 stdin or soap->recvfd to BINARY, e.g. to support DIME */
  18009. #ifdef __BORLANDC__
  18010. setmode(soap->recvfd, _O_BINARY);
  18011. #else
  18012. _setmode(soap->recvfd, _O_BINARY);
  18013. #endif
  18014. #endif
  18015. #endif
  18016. #endif
  18017. #ifdef WITH_ZLIB
  18018. soap->zlib_in = SOAP_ZLIB_NONE;
  18019. soap->zlib_out = SOAP_ZLIB_NONE;
  18020. if (!soap->d_stream)
  18021. {
  18022. soap->d_stream = (z_stream*)SOAP_MALLOC(soap, sizeof(z_stream));
  18023. if (!soap->d_stream)
  18024. return soap->error = SOAP_EOM;
  18025. soap->d_stream->zalloc = Z_NULL;
  18026. soap->d_stream->zfree = Z_NULL;
  18027. soap->d_stream->opaque = Z_NULL;
  18028. soap->d_stream->next_in = Z_NULL;
  18029. soap->d_stream->msg = Z_NULL;
  18030. }
  18031. soap->d_stream->avail_in = 0;
  18032. soap->d_stream->next_out = (Byte*)soap->buf;
  18033. soap->d_stream->avail_out = sizeof(soap->buf);
  18034. soap->z_ratio_in = 1.0;
  18035. #endif
  18036. #ifdef WITH_OPENSSL
  18037. if (soap->ssl)
  18038. ERR_clear_error();
  18039. #endif
  18040. #ifndef WITH_LEAN
  18041. soap->start = (ULONG64) time(NULL);
  18042. #endif
  18043. #ifndef WITH_LEANER
  18044. if (soap->fprepareinitrecv && (soap->error = soap->fprepareinitrecv(soap)) != SOAP_OK)
  18045. return soap->error;
  18046. #endif
  18047. c = soap_getchar(soap);
  18048. #ifdef WITH_GZIP
  18049. if (c == 0x1F)
  18050. {
  18051. if (soap_getgziphdr(soap))
  18052. return soap->error;
  18053. if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK)
  18054. return soap->error = SOAP_ZLIB_ERROR;
  18055. if (soap->z_dict)
  18056. {
  18057. if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
  18058. return soap->error = SOAP_ZLIB_ERROR;
  18059. }
  18060. soap->zlib_state = SOAP_ZLIB_INFLATE;
  18061. soap->mode |= SOAP_ENC_ZLIB;
  18062. soap->zlib_in = SOAP_ZLIB_GZIP;
  18063. soap->z_crc = crc32(0L, NULL, 0);
  18064. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
  18065. if (!soap->z_buf)
  18066. soap->z_buf = (char*)SOAP_MALLOC(soap, sizeof(soap->buf));
  18067. (void)soap_memcpy((void*)soap->z_buf, sizeof(soap->buf), (const void*)soap->buf, sizeof(soap->buf));
  18068. /* should not chunk over plain transport, so why bother to check? */
  18069. /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */
  18070. /* soap->z_buflen = soap->bufidx; */
  18071. /* else */
  18072. soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
  18073. soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx);
  18074. soap->z_buflen = soap->buflen;
  18075. soap->buflen = soap->bufidx;
  18076. c = ' ';
  18077. }
  18078. #endif
  18079. while (soap_coblank(c))
  18080. c = soap_getchar(soap);
  18081. #ifndef WITH_LEANER
  18082. if (c == '-' && soap_get0(soap) == '-') {
  18083. soap->mode |= SOAP_ENC_MIME;
  18084. } else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20) {
  18085. soap->mode |= SOAP_ENC_DIME;
  18086. } else
  18087. #endif
  18088. {
  18089. /* skip BOM */
  18090. if (c == 0xEF && soap_get0(soap) == 0xBB) {
  18091. soap_get1(soap);
  18092. c = soap_get1(soap);
  18093. if (c == 0xBF) {
  18094. soap->mode &= ~SOAP_ENC_LATIN;
  18095. c = soap_getchar(soap);
  18096. } else {
  18097. c = (0x0F << 12) | (0xBB << 6) | (c & 0x3F); /* UTF-8 */
  18098. }
  18099. } else if ((c == 0xFE && soap_get0(soap) == 0xFF) /* UTF-16 BE */
  18100. || (c == 0xFF && soap_get0(soap) == 0xFE)) /* UTF-16 LE */
  18101. {
  18102. return soap->error = SOAP_UTF_ERROR;
  18103. }
  18104. /* skip space */
  18105. while (soap_coblank(c))
  18106. c = soap_getchar(soap);
  18107. }
  18108. if ((int) c == EOF)
  18109. return soap->error = SOAP_CHK_EOF;
  18110. soap_unget(soap, c);
  18111. #ifndef WITH_NOHTTP
  18112. /* if not XML/MIME/DIME/ZLIB, assume HTTP method or status line */
  18113. if (((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) &&
  18114. !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB | SOAP_ENC_PLAIN))) {
  18115. soap_mode m = soap->imode;
  18116. soap->error = soap->fparse(soap);
  18117. soap->mode = soap->imode; /* if imode is changed, effectuate */
  18118. soap->imode = m; /* restore imode */
  18119. if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) {
  18120. soap->chunkbuflen = soap->buflen;
  18121. soap->buflen = soap->bufidx;
  18122. soap->chunksize = 0;
  18123. }
  18124. #ifdef WITH_ZLIB
  18125. soap->mode &= ~SOAP_ENC_ZLIB;
  18126. if (soap->zlib_in != SOAP_ZLIB_NONE)
  18127. {
  18128. #ifdef WITH_GZIP
  18129. if (soap->zlib_in != SOAP_ZLIB_DEFLATE)
  18130. {
  18131. c = soap_get1(soap);
  18132. if (c == (int)EOF)
  18133. return soap->error = SOAP_EOF;
  18134. if (c == 0x1F)
  18135. {
  18136. if (soap_getgziphdr(soap))
  18137. return soap->error;
  18138. if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK)
  18139. return soap->error = SOAP_ZLIB_ERROR;
  18140. soap->z_crc = crc32(0L, NULL, 0);
  18141. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
  18142. }
  18143. else
  18144. {
  18145. soap_revget1(soap);
  18146. if (inflateInit(soap->d_stream) != Z_OK)
  18147. return soap->error = SOAP_ZLIB_ERROR;
  18148. soap->zlib_in = SOAP_ZLIB_DEFLATE;
  18149. }
  18150. }
  18151. else
  18152. #endif
  18153. if (inflateInit(soap->d_stream) != Z_OK)
  18154. return soap->error = SOAP_ZLIB_ERROR;
  18155. if (soap->z_dict)
  18156. {
  18157. if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
  18158. return soap->error = SOAP_ZLIB_ERROR;
  18159. }
  18160. soap->zlib_state = SOAP_ZLIB_INFLATE;
  18161. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n"));
  18162. soap->mode |= SOAP_ENC_ZLIB;
  18163. if (!soap->z_buf)
  18164. soap->z_buf = (char*)SOAP_MALLOC(soap, sizeof(soap->buf));
  18165. (void)soap_memcpy((void*)soap->z_buf, sizeof(soap->buf), (const void*)soap->buf, sizeof(soap->buf));
  18166. soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
  18167. soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx);
  18168. soap->z_buflen = soap->buflen;
  18169. soap->buflen = soap->bufidx;
  18170. }
  18171. #endif
  18172. #ifndef WITH_LEANER
  18173. if (soap->fpreparerecv && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK && soap->buflen > soap->bufidx) {
  18174. int r;
  18175. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Invoking fpreparerecv\n"));
  18176. r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx);
  18177. if (r)
  18178. return soap->error = r;
  18179. }
  18180. #endif
  18181. if (soap->error && soap->error < SOAP_STOP) {
  18182. if (soap->status >= 200 && soap->status < 600) {
  18183. const char *s = soap_http_get_body(soap, NULL);
  18184. (void) soap_end_recv(soap);
  18185. if (soap->status >= 300)
  18186. soap->keep_alive = 0; /* to force close */
  18187. return soap_set_receiver_error(soap, "HTTP Error", s, soap->status);
  18188. }
  18189. return soap->error;
  18190. }
  18191. if (!soap->body && soap->status >= 200 && soap->status < 600)
  18192. return soap->error = soap->status; /* client side received HTTP status code */
  18193. if (soap->status > SOAP_POST) {
  18194. soap->fform = NULL;
  18195. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Invoking http method handler\n"));
  18196. switch (soap->status) {
  18197. case SOAP_GET:
  18198. if (soap_http_skip_body(soap) || soap_end_recv(soap))
  18199. return soap->error;
  18200. soap->error = soap->fget(soap);
  18201. break;
  18202. case SOAP_PUT:
  18203. soap->error = soap->fput(soap);
  18204. break;
  18205. case SOAP_PATCH:
  18206. soap->error = soap->fpatch(soap);
  18207. break;
  18208. case SOAP_DEL:
  18209. if (soap_http_skip_body(soap) || soap_end_recv(soap))
  18210. return soap->error;
  18211. soap->error = soap->fdel(soap);
  18212. break;
  18213. case SOAP_HEAD:
  18214. if (soap_http_skip_body(soap) || soap_end_recv(soap))
  18215. return soap->error;
  18216. soap->error = soap->fhead(soap);
  18217. break;
  18218. case SOAP_OPTIONS:
  18219. if (soap_http_skip_body(soap) || soap_end_recv(soap))
  18220. return soap->error;
  18221. soap->error = soap->fopt(soap);
  18222. break;
  18223. default:
  18224. if (soap_http_skip_body(soap) || soap_end_recv(soap))
  18225. return soap->error;
  18226. return 405;
  18227. }
  18228. if (soap->error == SOAP_OK)
  18229. return soap->error = SOAP_STOP; /* prevents further processing */
  18230. if (soap->error != SOAP_FORM || !soap->fform) /* continue if handler returned SOAP_FORM */
  18231. return soap->error;
  18232. soap->error = SOAP_OK;
  18233. }
  18234. if (soap->fform) {
  18235. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Invoking http form handler\n"));
  18236. soap->error = soap->fform(soap);
  18237. if (soap->error == SOAP_OK)
  18238. return soap->error = SOAP_STOP; /* prevents further processing */
  18239. if (soap->status != SOAP_POST ||
  18240. soap->error != 404) /* continue with POST if handler returned HTTP not found */
  18241. return soap->error;
  18242. soap->error = SOAP_OK;
  18243. }
  18244. if (!soap->body)//Sassan No_Data
  18245. {
  18246. std::cout << "No Content Recieved at " << time(NULL) << " for " << soap->host <<" Calling CheckQueue..."<< std::endl;
  18247. return soap->error =20400 ;
  18248. }
  18249. }
  18250. #endif
  18251. #ifndef WITH_LEANER
  18252. if ((soap->mode & SOAP_ENC_MIME)) {
  18253. do /* skip preamble */
  18254. {
  18255. c = soap_getchar(soap);
  18256. if ((int) c == EOF)
  18257. return soap->error = SOAP_CHK_EOF;
  18258. } while (c != '-' || soap_get0(soap) != '-');
  18259. soap_unget(soap, c);
  18260. if (soap_getmimehdr(soap))
  18261. return soap->error;
  18262. if (soap->mime.start) {
  18263. do {
  18264. if (!soap->mime.last->id)
  18265. break;
  18266. if (!soap_match_cid(soap, soap->mime.start, soap->mime.last->id))
  18267. break;
  18268. } while (soap_recv_mime_attachment(soap, NULL));
  18269. }
  18270. if (soap_http_header_attribute(soap, soap->mime.first->type, "application/dime"))
  18271. soap->mode |= SOAP_ENC_DIME;
  18272. }
  18273. if ((soap->mode & SOAP_ENC_DIME)) {
  18274. if (soap_getdimehdr(soap))
  18275. return soap->error;
  18276. if ((soap->dime.flags & SOAP_DIME_CF)) {
  18277. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME message\n"));
  18278. soap->dime.chunksize = soap->dime.size;
  18279. if (soap->buflen - soap->bufidx >= soap->dime.chunksize) {
  18280. soap->dime.buflen = soap->buflen;
  18281. soap->buflen = soap->bufidx + soap->dime.chunksize;
  18282. } else {
  18283. soap->dime.chunksize -= soap->buflen - soap->bufidx;
  18284. }
  18285. }
  18286. soap->count = soap->buflen - soap->bufidx;
  18287. if (soap->recv_maxlength && soap->count > soap->recv_maxlength)
  18288. return soap->error = SOAP_EOF;
  18289. }
  18290. #endif
  18291. return SOAP_OK;
  18292. }
  18293. /******************************************************************************/
  18294. SOAP_FMAC1
  18295. int
  18296. SOAP_FMAC2
  18297. soap_envelope_begin_out(struct soap *soap) {
  18298. if (soap->version == 0)
  18299. return SOAP_OK;
  18300. soap->part = SOAP_IN_ENVELOPE;
  18301. return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL);
  18302. }
  18303. /******************************************************************************/
  18304. SOAP_FMAC1
  18305. int
  18306. SOAP_FMAC2
  18307. soap_envelope_end_out(struct soap *soap) {
  18308. if (soap->version == 0)
  18309. return SOAP_OK;
  18310. if (soap_element_end_out(soap, "SOAP-ENV:Envelope")
  18311. || soap_send_raw(soap, "\r\n", 2)) /* 2.8: always emit \r\n */
  18312. return soap->error;
  18313. soap->part = SOAP_END_ENVELOPE;
  18314. return SOAP_OK;
  18315. }
  18316. /******************************************************************************/
  18317. SOAP_FMAC1
  18318. int
  18319. SOAP_FMAC2
  18320. soap_http_has_body(struct soap *soap) {
  18321. return soap->length || (soap->mode & SOAP_ENC_ZLIB) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK;
  18322. }
  18323. /******************************************************************************/
  18324. SOAP_FMAC1
  18325. int
  18326. SOAP_FMAC2
  18327. soap_http_skip_body(struct soap *soap) {
  18328. ULONG64 k = soap->length;
  18329. /* check HTTP body, return "" if none */
  18330. if (!k && !(soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK)
  18331. return SOAP_OK;
  18332. /* do not consume DIME or MIME attachments, leave this to soap_end_recv */
  18333. if ((soap->mode & SOAP_ENC_DIME) || (soap->mode & SOAP_ENC_MIME))
  18334. return SOAP_OK;
  18335. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skipping HTTP body (mode=0x%x)\n", soap->mode));
  18336. if (k && !(soap->mode & SOAP_ENC_ZLIB)) {
  18337. size_t i;
  18338. soap->length = 0;
  18339. for (i = 0; i < k; i++) {
  18340. soap_wchar c = soap_get1(soap);
  18341. if ((int) c == EOF)
  18342. break;
  18343. }
  18344. } else {
  18345. for (;;) {
  18346. soap_wchar c = soap_get1(soap);
  18347. if ((int) c == EOF)
  18348. break;
  18349. }
  18350. }
  18351. return SOAP_OK;
  18352. }
  18353. /******************************************************************************/
  18354. SOAP_FMAC1
  18355. char *
  18356. SOAP_FMAC2
  18357. soap_http_get_body(struct soap *soap, size_t *len) {
  18358. return soap_http_get_body_prefix(soap, len, NULL);
  18359. }
  18360. /******************************************************************************/
  18361. SOAP_FMAC1
  18362. char *
  18363. SOAP_FMAC2
  18364. soap_http_get_form(struct soap *soap) {
  18365. return soap_http_get_body_prefix(soap, NULL, "?");
  18366. }
  18367. /******************************************************************************/
  18368. SOAP_FMAC1
  18369. char *
  18370. SOAP_FMAC2
  18371. soap_http_get_body_prefix(struct soap *soap, size_t *len, const char *prefix) {
  18372. char *s;
  18373. ULONG64 k = soap->length;
  18374. size_t n = 0;
  18375. if (!prefix)
  18376. prefix = SOAP_STR_EOS;
  18377. else
  18378. n = strlen(prefix);
  18379. if (len)
  18380. *len = 0;
  18381. /* check HTTP body, return "" if none */
  18382. if (!k && !(soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK)
  18383. return soap_strdup(soap, prefix);
  18384. /* do not consume DIME or MIME attachments, leave this to soap_end_recv */
  18385. if ((soap->mode & SOAP_ENC_DIME) || (soap->mode & SOAP_ENC_MIME))
  18386. return soap_strdup(soap, prefix);
  18387. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing HTTP body, prefixed with '%s' (mode=0x%x)\n", prefix, soap->mode));
  18388. if (k && !(soap->mode & SOAP_ENC_ZLIB)) {
  18389. char *t;
  18390. soap->length = 0;
  18391. /* http content length != 0 and uncompressed body */
  18392. if ((SOAP_MAXALLOCSIZE != 0 && n + k > SOAP_MAXALLOCSIZE) || n + k > (ULONG64) ((size_t) -2)) {
  18393. soap->error = SOAP_EOM;
  18394. return NULL;
  18395. }
  18396. s = t = (char *) soap_malloc(soap, (size_t) k + n + 1);
  18397. if (s) {
  18398. size_t i;
  18399. soap_strcpy(t, n + 1, prefix);
  18400. t += n;
  18401. for (i = 0; i < k; i++) {
  18402. soap_wchar c = soap_get1(soap);
  18403. if ((int) c == EOF)
  18404. break;
  18405. *t++ = (char) (c & 0xFF);
  18406. }
  18407. *t = '\0';
  18408. if (len)
  18409. *len = n + i;
  18410. } else {
  18411. soap->error = SOAP_EOM;
  18412. return NULL;
  18413. }
  18414. } else {
  18415. size_t i, l = 0;
  18416. if (soap_alloc_block(soap) == NULL)
  18417. return NULL;
  18418. if (n) {
  18419. s = (char *) soap_push_block(soap, NULL, n);
  18420. if (!s)
  18421. return NULL;
  18422. soap_strcpy(s, n + 1, prefix);
  18423. l += n;
  18424. }
  18425. for (;;) {
  18426. size_t k = SOAP_BLKLEN;
  18427. s = (char *) soap_push_block(soap, NULL, k);
  18428. if (!s)
  18429. return NULL;
  18430. for (i = 0; i < k; i++) {
  18431. soap_wchar c;
  18432. l++;
  18433. if (l == 0) {
  18434. soap->error = SOAP_EOM;
  18435. return NULL;
  18436. }
  18437. c = soap_get1(soap);
  18438. if ((int) c == EOF)
  18439. goto end;
  18440. *s++ = (char) (c & 0xFF);
  18441. }
  18442. }
  18443. end:
  18444. *s = '\0';
  18445. if (len)
  18446. *len = l - 1;
  18447. soap_size_block(soap, NULL, i + 1);
  18448. s = soap_save_block(soap, NULL, NULL, 0);
  18449. }
  18450. return s;
  18451. }
  18452. /******************************************************************************/
  18453. SOAP_FMAC1
  18454. int
  18455. SOAP_FMAC2
  18456. soap_envelope_begin_in(struct soap *soap) {
  18457. soap->part = SOAP_IN_ENVELOPE;
  18458. if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL)) {
  18459. if (soap->error == SOAP_TAG_MISMATCH) {
  18460. if (!soap_element_begin_in(soap, "Envelope", 0, NULL))
  18461. soap->error = SOAP_VERSIONMISMATCH;
  18462. else if (soap->status == 0
  18463. || (soap->status >= 200 && soap->status <= 299)
  18464. || soap->status == 400
  18465. || soap->status == 500)
  18466. return SOAP_OK; /* allow non-SOAP (REST) XML content to be captured */
  18467. soap->error = soap->status;
  18468. } else if (soap->status) {
  18469. soap->error = soap->status;
  18470. }
  18471. return soap->error;
  18472. }
  18473. soap_version(soap);
  18474. return SOAP_OK;
  18475. }
  18476. /******************************************************************************/
  18477. SOAP_FMAC1
  18478. int
  18479. SOAP_FMAC2
  18480. soap_envelope_end_in(struct soap *soap) {
  18481. if (soap->version == 0)
  18482. return SOAP_OK;
  18483. soap->part = SOAP_END_ENVELOPE;
  18484. return soap_element_end_in(soap, "SOAP-ENV:Envelope");
  18485. }
  18486. /******************************************************************************/
  18487. SOAP_FMAC1
  18488. int
  18489. SOAP_FMAC2
  18490. soap_body_begin_out(struct soap *soap) {
  18491. if (soap->version == 1)
  18492. soap->encoding = 1;
  18493. #ifndef WITH_LEAN
  18494. if ((soap->mode & SOAP_SEC_WSUID) && soap_set_attr(soap, "wsu:Id", "Body", 1))
  18495. return soap->error;
  18496. #endif
  18497. if (soap->version == 0)
  18498. return SOAP_OK;
  18499. soap->part = SOAP_IN_BODY;
  18500. return soap_element_begin_out(soap, "SOAP-ENV:Body", 0, NULL);
  18501. }
  18502. /******************************************************************************/
  18503. SOAP_FMAC1
  18504. int
  18505. SOAP_FMAC2
  18506. soap_body_end_out(struct soap *soap) {
  18507. if (soap->version == 0)
  18508. return SOAP_OK;
  18509. if (soap_element_end_out(soap, "SOAP-ENV:Body"))
  18510. return soap->error;
  18511. soap->part = SOAP_END_BODY;
  18512. return SOAP_OK;
  18513. }
  18514. /******************************************************************************/
  18515. SOAP_FMAC1
  18516. int
  18517. SOAP_FMAC2
  18518. soap_body_begin_in(struct soap *soap) {
  18519. if (soap->version == 0)
  18520. return SOAP_OK;
  18521. soap->part = SOAP_IN_BODY;
  18522. if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0, NULL))
  18523. return soap->error;
  18524. if (!soap->body) {
  18525. return SOAP_NO_DATA;
  18526. }
  18527. return SOAP_OK;
  18528. }
  18529. /******************************************************************************/
  18530. SOAP_FMAC1
  18531. int
  18532. SOAP_FMAC2
  18533. soap_body_end_in(struct soap *soap) {
  18534. if (soap->version == 0)
  18535. return SOAP_OK;
  18536. if (soap->part == SOAP_NO_BODY)
  18537. return soap->error = SOAP_OK;
  18538. soap->part = SOAP_END_BODY;
  18539. return soap_element_end_in(soap, "SOAP-ENV:Body");
  18540. }
  18541. /******************************************************************************/
  18542. SOAP_FMAC1
  18543. int
  18544. SOAP_FMAC2
  18545. soap_recv_header(struct soap *soap) {
  18546. if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH)
  18547. soap->error = SOAP_OK;
  18548. if (soap->error == SOAP_OK && soap->fheader)
  18549. soap->error = soap->fheader(soap);
  18550. return soap->error;
  18551. }
  18552. /******************************************************************************/
  18553. SOAP_FMAC1
  18554. void
  18555. SOAP_FMAC2
  18556. soap_set_endpoint(struct soap *soap, const char *endpoint) {
  18557. const char *s, *t;
  18558. size_t i, n;
  18559. soap->endpoint[0] = '\0';
  18560. soap->host[0] = '\0';
  18561. soap->path[0] = '/';
  18562. soap->path[1] = '\0';
  18563. soap->port = 80;
  18564. if (!endpoint || !*endpoint)
  18565. return;
  18566. #ifdef WITH_OPENSSL
  18567. if (!soap_tag_cmp(endpoint, "https:*"))
  18568. soap->port = 443;
  18569. #endif
  18570. soap_strcpy(soap->endpoint, sizeof(soap->endpoint), endpoint);
  18571. s = strchr(endpoint, ':');
  18572. if (s && s[1] == '/' && s[2] == '/')
  18573. s += 3;
  18574. else
  18575. s = endpoint;
  18576. #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
  18577. t = strchr(s, '@');
  18578. if (t && *s != ':' && *s != '@') {
  18579. size_t l = t - s + 1;
  18580. char *r = (char *) soap_malloc(soap, l);
  18581. n = s - endpoint;
  18582. if (r) {
  18583. s = soap_decode(r, l, s, ":@");
  18584. soap->userid = r;
  18585. soap->passwd = SOAP_STR_EOS;
  18586. if (*s == ':') {
  18587. s++;
  18588. if (*s != '@') {
  18589. l = t - s + 1;
  18590. r = r + strlen(r) + 1;
  18591. s = soap_decode(r, l, s, "@");
  18592. soap->passwd = r;
  18593. }
  18594. }
  18595. }
  18596. s++;
  18597. soap_strcpy(soap->endpoint + n, sizeof(soap->endpoint) - n, s);
  18598. }
  18599. #endif
  18600. n = strlen(s);
  18601. if (n >= sizeof(soap->host))
  18602. n = sizeof(soap->host) - 1;
  18603. #ifdef WITH_IPV6
  18604. if (s[0] == '[')
  18605. {
  18606. s++;
  18607. for (i = 0; i < n; i++)
  18608. {
  18609. if (s[i] == ']')
  18610. {
  18611. s++;
  18612. --n;
  18613. break;
  18614. }
  18615. soap->host[i] = s[i];
  18616. }
  18617. }
  18618. else
  18619. {
  18620. for (i = 0; i < n; i++)
  18621. {
  18622. soap->host[i] = s[i];
  18623. if (s[i] == '/' || s[i] == ':' || s[i] == '?')
  18624. break;
  18625. }
  18626. }
  18627. #else
  18628. for (i = 0; i < n; i++) {
  18629. soap->host[i] = s[i];
  18630. if (s[i] == '/' || s[i] == ':' || s[i] == '?')
  18631. break;
  18632. }
  18633. #endif
  18634. soap->host[i] = '\0';
  18635. if (s[i] == ':') {
  18636. soap->port = (int) soap_strtol(s + i + 1, NULL, 10);
  18637. for (i++; i < n; i++)
  18638. if (s[i] == '/')
  18639. break;
  18640. }
  18641. if (i < n && s[i])
  18642. soap_strcpy(soap->path, sizeof(soap->path), s + i);
  18643. if (soap->override_host && *soap->override_host) {
  18644. soap_strcpy(soap->host, sizeof(soap->host), soap->override_host);
  18645. if (soap->override_port)
  18646. soap->port = soap->override_port;
  18647. }
  18648. if (soap->userid && !soap->authrealm)
  18649. soap->authrealm = soap->host;
  18650. }
  18651. /******************************************************************************/
  18652. #ifndef WITH_NOHTTP
  18653. SOAP_FMAC1
  18654. int
  18655. SOAP_FMAC2
  18656. soap_GET(struct soap *soap, const char *endpoint, const char *action) {
  18657. return soap_connect_command(soap, SOAP_GET, endpoint, action);
  18658. }
  18659. #endif
  18660. /******************************************************************************/
  18661. #ifndef WITH_NOHTTP
  18662. SOAP_FMAC1
  18663. int
  18664. SOAP_FMAC2
  18665. soap_PUT(struct soap *soap, const char *endpoint, const char *action, const char *type) {
  18666. soap->http_content = type;
  18667. if ((soap->omode & SOAP_IO) != SOAP_IO_CHUNK) {
  18668. soap->omode &= ~SOAP_IO;
  18669. soap->omode |= SOAP_IO_STORE;
  18670. }
  18671. return soap_connect_command(soap, SOAP_PUT, endpoint, action);
  18672. }
  18673. #endif
  18674. /******************************************************************************/
  18675. #ifndef WITH_NOHTTP
  18676. SOAP_FMAC1
  18677. int
  18678. SOAP_FMAC2
  18679. soap_POST(struct soap *soap, const char *endpoint, const char *action, const char *type) {
  18680. soap->http_content = type;
  18681. if ((soap->omode & SOAP_IO) != SOAP_IO_CHUNK) {
  18682. soap->omode &= ~SOAP_IO;
  18683. soap->omode |= SOAP_IO_STORE;
  18684. }
  18685. return soap_connect_command(soap, SOAP_POST_FILE, endpoint, action);
  18686. }
  18687. #endif
  18688. /******************************************************************************/
  18689. #ifndef WITH_NOHTTP
  18690. SOAP_FMAC1
  18691. int
  18692. SOAP_FMAC2
  18693. soap_PATCH(struct soap *soap, const char *endpoint, const char *action, const char *type) {
  18694. soap->http_content = type;
  18695. if ((soap->omode & SOAP_IO) != SOAP_IO_CHUNK) {
  18696. soap->omode &= ~SOAP_IO;
  18697. soap->omode |= SOAP_IO_STORE;
  18698. }
  18699. return soap_connect_command(soap, SOAP_PATCH, endpoint, action);
  18700. }
  18701. #endif
  18702. /******************************************************************************/
  18703. #ifndef WITH_NOHTTP
  18704. SOAP_FMAC1
  18705. int
  18706. SOAP_FMAC2
  18707. soap_DELETE(struct soap *soap, const char *endpoint) {
  18708. if (soap_connect_command(soap, SOAP_DEL, endpoint, NULL)
  18709. || soap_recv_empty_response(soap))
  18710. return soap_closesock(soap);
  18711. return SOAP_OK;
  18712. }
  18713. #endif
  18714. /******************************************************************************/
  18715. SOAP_FMAC1
  18716. int
  18717. SOAP_FMAC2
  18718. soap_connect(struct soap *soap, const char *endpoint, const char *action) {
  18719. return soap_connect_command(soap, SOAP_POST, endpoint, action);
  18720. }
  18721. /******************************************************************************/
  18722. SOAP_FMAC1
  18723. int
  18724. SOAP_FMAC2
  18725. soap_connect_command(struct soap *soap, int http_command, const char *endpoints, const char *action) {
  18726. if (endpoints) {
  18727. const char *s;
  18728. s = strchr(endpoints, ' ');
  18729. if (s) {
  18730. size_t l = strlen(endpoints);
  18731. char *endpoint = NULL;
  18732. if (SOAP_MAXALLOCSIZE == 0 || l <= SOAP_MAXALLOCSIZE)
  18733. endpoint = (char *) SOAP_MALLOC(soap, l + 1);
  18734. if (!endpoint)
  18735. return soap->error = SOAP_EOM;
  18736. for (;;) {
  18737. (void) soap_strncpy(endpoint, l + 1, endpoints, s - endpoints);
  18738. endpoint[s - endpoints] = '\0';
  18739. if (soap_try_connect_command(soap, http_command, endpoint, action) != SOAP_TCP_ERROR)
  18740. break;
  18741. if (!*s)
  18742. break;
  18743. soap->error = SOAP_OK;
  18744. while (*s == ' ')
  18745. s++;
  18746. endpoints = s;
  18747. s = strchr(endpoints, ' ');
  18748. if (!s)
  18749. s = endpoints + strlen(endpoints);
  18750. }
  18751. SOAP_FREE(soap, endpoint);
  18752. } else {
  18753. soap_try_connect_command(soap, http_command, endpoints, action);
  18754. }
  18755. }
  18756. return soap->error;
  18757. }
  18758. /******************************************************************************/
  18759. static int
  18760. soap_try_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action) {
  18761. char host[sizeof(soap->host)];
  18762. int port;
  18763. ULONG64 count;
  18764. soap->error = SOAP_OK;
  18765. soap_memcpy(host, sizeof(host), soap->host, sizeof(soap->host)); /* save previous host name: if != then reconnect */
  18766. port = soap->port; /* save previous port to compare */
  18767. soap->status = http_command;
  18768. soap_set_endpoint(soap, endpoint);
  18769. soap->action = soap_strdup(soap, action);
  18770. #ifndef WITH_LEANER
  18771. if (soap->fconnect) {
  18772. soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port);
  18773. if (soap->error)
  18774. return soap->error;
  18775. } else
  18776. #endif
  18777. if (soap->fopen && *soap->host) {
  18778. if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port ||
  18779. !soap->fpoll || soap->fpoll(soap)) {
  18780. soap->error = SOAP_OK;
  18781. #ifndef WITH_LEAN
  18782. if (!strncmp(endpoint, "soap.udp:", 9) || !strncmp(endpoint, "udp:", 4)) {
  18783. soap->omode |= SOAP_IO_UDP;
  18784. } else
  18785. #endif
  18786. {
  18787. soap->keep_alive = 0; /* to force close */
  18788. soap->omode &= ~SOAP_IO_UDP; /* to force close */
  18789. }
  18790. soap_closesock(soap);
  18791. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect/reconnect to '%s' host='%s' path='%s' port=%d\n",
  18792. endpoint ? endpoint : "(null)", soap->host, soap->path, soap->port));
  18793. if (!soap->keep_alive || !soap_valid_socket(soap->socket)) {
  18794. soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port);
  18795. if (!soap_valid_socket(soap->socket) || soap->error) {
  18796. if (soap->error)
  18797. return soap->error;
  18798. return soap->error = SOAP_TCP_ERROR;
  18799. }
  18800. soap->keep_alive = -((soap->omode & SOAP_IO_KEEPALIVE) != 0);
  18801. }
  18802. }
  18803. }
  18804. #ifdef WITH_NTLM
  18805. if (soap_ntlm_handshake(soap, SOAP_GET, endpoint, soap->host, soap->port))
  18806. return soap->error;
  18807. #endif
  18808. count = soap_count_attachments(soap);
  18809. if (soap_init_send(soap))
  18810. return soap->error;
  18811. #ifndef WITH_NOHTTP
  18812. if (http_command == SOAP_GET || http_command == SOAP_DEL || http_command == SOAP_HEAD ||
  18813. http_command == SOAP_OPTIONS) {
  18814. soap->mode &= ~SOAP_IO;
  18815. soap->mode |= SOAP_IO_BUFFER;
  18816. }
  18817. if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_PLAIN) && endpoint) {
  18818. soap_mode k = soap->mode;
  18819. soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
  18820. if ((k & SOAP_IO) != SOAP_IO_FLUSH)
  18821. soap->mode |= SOAP_IO_BUFFER;
  18822. soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count);
  18823. if (soap->error)
  18824. return soap->error;
  18825. if ((k & SOAP_IO) == SOAP_IO_CHUNK) {
  18826. if (soap_flush(soap))
  18827. return soap->error;
  18828. }
  18829. soap->mode = k;
  18830. }
  18831. if (http_command == SOAP_GET || http_command == SOAP_DEL || http_command == SOAP_HEAD ||
  18832. http_command == SOAP_OPTIONS)
  18833. return soap_end_send_flush(soap);
  18834. #endif
  18835. #ifndef WITH_LEANER
  18836. if (soap_begin_attachments(soap))
  18837. return soap->error;
  18838. #endif
  18839. return SOAP_OK;
  18840. }
  18841. /******************************************************************************/
  18842. #ifdef WITH_NTLM
  18843. static int
  18844. soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const char *host, int port)
  18845. {
  18846. /* requires libntlm from http://www.nongnu.org/libntlm/ */
  18847. const char *userid = (soap->proxy_userid ? soap->proxy_userid : soap->userid);
  18848. const char *passwd = (soap->proxy_passwd ? soap->proxy_passwd : soap->passwd);
  18849. struct SOAP_ENV__Header *oldheader;
  18850. if (soap->ntlm_challenge && userid && passwd && soap->authrealm)
  18851. {
  18852. tSmbNtlmAuthRequest req;
  18853. tSmbNtlmAuthResponse res;
  18854. tSmbNtlmAuthChallenge ch;
  18855. int k = soap->keep_alive;
  18856. ULONG64 l = soap->length;
  18857. ULONG64 c = soap->count;
  18858. soap_mode m = soap->mode, o = soap->omode;
  18859. int s = soap->status;
  18860. char *a = soap->action;
  18861. short v = soap->version;
  18862. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "NTLM '%s'\n", soap->ntlm_challenge));
  18863. if (!*soap->ntlm_challenge)
  18864. {
  18865. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "NTLM S->C Type 1: received NTLM authentication challenge from server\n"));
  18866. /* S -> C 401 Unauthorized
  18867. WWW-Authenticate: NTLM
  18868. */
  18869. buildSmbNtlmAuthRequest(&req, userid, soap->authrealm);
  18870. soap->ntlm_challenge = soap_s2base64(soap, (unsigned char*)(void*)&req, NULL, SmbLength(&req));
  18871. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "NTLM C->S Type 2: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap->ntlm_challenge));
  18872. /* C -> S GET ...
  18873. Authorization: NTLM TlRMTVNTUAABAAAAA7IAAAoACgApAAAACQAJACAAAABMSUdIVENJVFlVUlNBLU1JTk9S
  18874. */
  18875. soap->omode = SOAP_IO_BUFFER;
  18876. if (soap_init_send(soap))
  18877. return soap->error;
  18878. if (!soap->keep_alive)
  18879. soap->keep_alive = -1; /* client keep alive */
  18880. soap->status = command;
  18881. if (soap->fpost(soap, endpoint, host, port, soap->path, soap->action, 0)
  18882. || soap_end_send_flush(soap))
  18883. return soap->error;
  18884. soap->mode = m;
  18885. soap->keep_alive = k;
  18886. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "NTLM S->C Type 2: waiting on server NTLM response\n"));
  18887. oldheader = soap->header;
  18888. if (soap_begin_recv(soap))
  18889. if (soap->error == SOAP_EOF)
  18890. return soap->error;
  18891. (void)soap_end_recv(soap);
  18892. soap->header = oldheader;
  18893. soap->length = l;
  18894. if (soap->status != 401 && soap->status != 407)
  18895. return soap->error = SOAP_NTLM_ERROR;
  18896. soap->error = SOAP_OK;
  18897. }
  18898. /* S -> C 401 Unauthorized
  18899. WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAU3J2Tm9uY2UAAAAAAAAAAA==
  18900. */
  18901. soap_base642s(soap, soap->ntlm_challenge, (char*)&ch, sizeof(tSmbNtlmAuthChallenge), NULL);
  18902. buildSmbNtlmAuthResponse(&ch, &res, userid, passwd);
  18903. soap->ntlm_challenge = soap_s2base64(soap, (unsigned char*)(void*)&res, NULL, SmbLength(&res));
  18904. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "NTLM C->S Type 3: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap->ntlm_challenge));
  18905. /* C -> S GET ...
  18906. Authorization: NTLM TlRMTVNTUAADAAAAGAAYAHIAAAAYABgAigAAABQAFABAAAAADAAMAFQAAAASABIAYAAAAAAAAACiAAAAAYIAAFUAUgBTAEEALQBNAEkATgBPAFIAWgBhAHAAaABvAGQATABJAEcASABUAEMASQBUAFkArYfKbe/jRoW5xDxHeoxC1gBmfWiS5+iX4OAN4xBKG/IFPwfH3agtPEia6YnhsADT
  18907. */
  18908. soap->userid = NULL;
  18909. soap->passwd = NULL;
  18910. soap->proxy_userid = NULL;
  18911. soap->proxy_passwd = NULL;
  18912. soap->keep_alive = k;
  18913. soap->length = l;
  18914. soap->count = c;
  18915. soap->mode = m;
  18916. soap->omode = o;
  18917. soap->status = s;
  18918. soap->action = a;
  18919. soap->version = v;
  18920. }
  18921. return SOAP_OK;
  18922. }
  18923. #endif
  18924. /******************************************************************************/
  18925. SOAP_FMAC1
  18926. char *
  18927. SOAP_FMAC2
  18928. soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n) {
  18929. int i;
  18930. unsigned long m;
  18931. char *p;
  18932. if (!t)
  18933. t = (char *) soap_malloc(soap, (n + 2) / 3 * 4 + 1);
  18934. if (!t)
  18935. return NULL;
  18936. p = t;
  18937. t[0] = '\0';
  18938. if (!s)
  18939. return p;
  18940. for (; n > 2; n -= 3, s += 3) {
  18941. m = s[0];
  18942. m = (m << 8) | s[1];
  18943. m = (m << 8) | s[2];
  18944. for (i = 4; i > 0; m >>= 6)
  18945. t[--i] = soap_base64o[m & 0x3F];
  18946. t += 4;
  18947. }
  18948. t[0] = '\0';
  18949. if (n > 0) /* 0 < n <= 2 implies that t[0..4] is allocated (base64 scaling formula) */
  18950. {
  18951. m = 0;
  18952. for (i = 0; i < n; i++)
  18953. m = (m << 8) | *s++;
  18954. for (; i < 3; i++)
  18955. m <<= 8;
  18956. for (i = 4; i > 0; m >>= 6)
  18957. t[--i] = soap_base64o[m & 0x3F];
  18958. for (i = 3; i > n; i--)
  18959. t[i] = '=';
  18960. t[4] = '\0';
  18961. }
  18962. return p;
  18963. }
  18964. /******************************************************************************/
  18965. SOAP_FMAC1
  18966. const char *
  18967. SOAP_FMAC2
  18968. soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n) {
  18969. size_t i, j;
  18970. soap_wchar c;
  18971. unsigned long m;
  18972. const char *p;
  18973. if (!s || !*s) {
  18974. if (n)
  18975. *n = 0;
  18976. if (soap->error)
  18977. return NULL;
  18978. return SOAP_NON_NULL;
  18979. }
  18980. if (!t) {
  18981. l = (strlen(s) + 3) / 4 * 3 + 1; /* space for raw binary and \0 */
  18982. t = (char *) soap_malloc(soap, l);
  18983. }
  18984. if (!t)
  18985. return NULL;
  18986. p = t;
  18987. if (n)
  18988. *n = 0;
  18989. for (i = 0;; i += 3, l -= 3) {
  18990. m = 0;
  18991. j = 0;
  18992. while (j < 4) {
  18993. c = *s++;
  18994. if (c == '=' || !c) {
  18995. if (l >= j - 1) {
  18996. switch (j) {
  18997. case 2:
  18998. *t++ = (char) ((m >> 4) & 0xFF);
  18999. i++;
  19000. l--;
  19001. break;
  19002. case 3:
  19003. *t++ = (char) ((m >> 10) & 0xFF);
  19004. *t++ = (char) ((m >> 2) & 0xFF);
  19005. i += 2;
  19006. l -= 2;
  19007. }
  19008. }
  19009. if (n)
  19010. *n = (int) i;
  19011. if (l)
  19012. *t = '\0';
  19013. return p;
  19014. }
  19015. c -= '+';
  19016. if (c >= 0 && c <= 79) {
  19017. int b = soap_base64i[c];
  19018. if (b >= 64) {
  19019. soap->error = SOAP_TYPE;
  19020. return NULL;
  19021. }
  19022. m = (m << 6) + b;
  19023. j++;
  19024. } else if (!soap_coblank(c + '+')) {
  19025. soap->error = SOAP_TYPE;
  19026. return NULL;
  19027. }
  19028. }
  19029. if (l < 3) {
  19030. if (n)
  19031. *n = (int) i;
  19032. if (l)
  19033. *t = '\0';
  19034. return p;
  19035. }
  19036. *t++ = (char) ((m >> 16) & 0xFF);
  19037. *t++ = (char) ((m >> 8) & 0xFF);
  19038. *t++ = (char) (m & 0xFF);
  19039. }
  19040. }
  19041. /******************************************************************************/
  19042. SOAP_FMAC1
  19043. char *
  19044. SOAP_FMAC2
  19045. soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n) {
  19046. char *p;
  19047. if (!t)
  19048. t = (char *) soap_malloc(soap, 2 * n + 1);
  19049. if (!t)
  19050. return NULL;
  19051. p = t;
  19052. t[0] = '\0';
  19053. if (s) {
  19054. for (; n > 0; n--) {
  19055. int m = *s++;
  19056. *t++ = (char) ((m >> 4) + (m > 159 ? 'a' - 10 : '0'));
  19057. m &= 0x0F;
  19058. *t++ = (char) (m + (m > 9 ? 'a' - 10 : '0'));
  19059. }
  19060. }
  19061. *t++ = '\0';
  19062. return p;
  19063. }
  19064. /******************************************************************************/
  19065. SOAP_FMAC1
  19066. const char *
  19067. SOAP_FMAC2
  19068. soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n) {
  19069. const char *p;
  19070. if (!s || !*s) {
  19071. if (n)
  19072. *n = 0;
  19073. if (soap->error)
  19074. return NULL;
  19075. return SOAP_NON_NULL;
  19076. }
  19077. if (!t) {
  19078. l = strlen(s) / 2 + 1; /* make sure enough space for \0 */
  19079. t = (char *) soap_malloc(soap, l);
  19080. }
  19081. if (!t)
  19082. return NULL;
  19083. p = t;
  19084. while (l) {
  19085. int d1, d2;
  19086. d1 = *s++;
  19087. if (!d1)
  19088. break;
  19089. d2 = *s++;
  19090. if (!d2)
  19091. break;
  19092. *t++ = (char) (((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'));
  19093. l--;
  19094. }
  19095. if (n)
  19096. *n = (int) (t - p);
  19097. if (l)
  19098. *t = '\0';
  19099. return p;
  19100. }
  19101. /******************************************************************************/
  19102. #ifndef WITH_NOHTTP
  19103. SOAP_FMAC1
  19104. const char *
  19105. SOAP_FMAC2
  19106. soap_http_content_type(struct soap *soap, int status) {
  19107. if (soap->status != SOAP_GET && soap->status != SOAP_DEL && soap->status != SOAP_CONNECT) {
  19108. const char *s = "text/xml; charset=utf-8";
  19109. #ifndef WITH_LEANER
  19110. const char *r = NULL;
  19111. size_t n;
  19112. #endif
  19113. if (((status >= SOAP_FILE && status < SOAP_FILE + 600) || soap->status == SOAP_PUT ||
  19114. soap->status == SOAP_POST_FILE || soap->status == SOAP_PATCH) && soap->http_content &&
  19115. *soap->http_content && !strchr(soap->http_content, 10) && !strchr(soap->http_content, 13))
  19116. s = soap->http_content;
  19117. else if (status == SOAP_HTML)
  19118. s = "text/html; charset=utf-8";
  19119. else if (soap->version == 2)
  19120. s = "application/soap+xml; charset=utf-8";
  19121. soap->http_content = NULL; /* use http_content once (assign new value before each call) */
  19122. #ifndef WITH_LEANER
  19123. if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM)) {
  19124. if ((soap->mode & SOAP_ENC_MTOM)) {
  19125. if (soap->version == 2)
  19126. r = "application/soap+xml";
  19127. else
  19128. r = "text/xml";
  19129. s = "application/xop+xml";
  19130. } else {
  19131. s = "application/dime";
  19132. }
  19133. }
  19134. if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary) {
  19135. const char *t;
  19136. size_t l;
  19137. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(soap->mime.boundary) + 53),
  19138. "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary);
  19139. t = strchr(s, ';');
  19140. if (t)
  19141. n = t - s;
  19142. else
  19143. n = strlen(s);
  19144. l = strlen(soap->tmpbuf);
  19145. if (sizeof(soap->tmpbuf) > l + n)
  19146. (void) soap_strncpy(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, s, n);
  19147. if (soap->mime.start) {
  19148. l = strlen(soap->tmpbuf);
  19149. (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, strlen(soap->mime.start) + 10),
  19150. "\"; start=\"%s", soap->mime.start);
  19151. }
  19152. if (r) {
  19153. l = strlen(soap->tmpbuf);
  19154. (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, strlen(r) + 15), "\"; start-info=\"%s", r);
  19155. }
  19156. l = strlen(soap->tmpbuf);
  19157. if (sizeof(soap->tmpbuf) > l)
  19158. soap_strcpy(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, "\"");
  19159. } else {
  19160. soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), s);
  19161. }
  19162. if (status == SOAP_OK && soap->version == 2 && soap->action) {
  19163. size_t l = strlen(soap->tmpbuf);
  19164. n = strlen(soap->action);
  19165. (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, n + 11), "; action=\"%s\"", soap->action);
  19166. }
  19167. #else
  19168. soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), s);
  19169. #endif
  19170. return soap->tmpbuf;
  19171. }
  19172. return NULL;
  19173. }
  19174. #endif
  19175. /******************************************************************************/
  19176. #ifndef WITH_NOHTTP
  19177. SOAP_FMAC1
  19178. int
  19179. SOAP_FMAC2
  19180. soap_puthttphdr(struct soap *soap, int status, ULONG64 count) {
  19181. int err = SOAP_OK;
  19182. if (soap_http_content_type(soap, status)) {
  19183. err = soap->fposthdr(soap, "Content-Type", soap->tmpbuf);
  19184. if (err)
  19185. return err;
  19186. #ifdef WITH_ZLIB
  19187. if ((soap->omode & SOAP_ENC_ZLIB))
  19188. {
  19189. #ifdef WITH_GZIP
  19190. err = soap->fposthdr(soap, "Content-Encoding", soap->zlib_out == SOAP_ZLIB_DEFLATE ? "deflate" : "gzip");
  19191. #else
  19192. err = soap->fposthdr(soap, "Content-Encoding", "deflate");
  19193. #endif
  19194. if (err)
  19195. return err;
  19196. }
  19197. #endif
  19198. #ifndef WITH_LEANER
  19199. if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK) {
  19200. err = soap->fposthdr(soap, "Transfer-Encoding", "chunked");
  19201. } else
  19202. #endif
  19203. {
  19204. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), SOAP_ULONG_FORMAT, count);
  19205. err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf);
  19206. }
  19207. if (err)
  19208. return err;
  19209. }
  19210. if (soap->http_extra_header) {
  19211. err = soap_send(soap, soap->http_extra_header);
  19212. soap->http_extra_header = NULL; /* use http_extra_header once (assign new value before each call) */
  19213. if (err)
  19214. return err;
  19215. err = soap_send_raw(soap, "\r\n", 2);
  19216. if (err)
  19217. return err;
  19218. }
  19219. if (soap->keep_alive) {
  19220. if (soap->keep_alive > 0 && soap->recv_timeout) {
  19221. int t = soap->recv_timeout;
  19222. if (t < 0)
  19223. t = 1;
  19224. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), "timeout=%d, max=%d", soap->recv_timeout,
  19225. soap->keep_alive);
  19226. err = soap->fposthdr(soap, "Keep-Alive", soap->tmpbuf);
  19227. if (err)
  19228. return err;
  19229. }
  19230. return soap->fposthdr(soap, "Connection", "keep-alive");
  19231. }
  19232. return soap->fposthdr(soap, "Connection", "close");
  19233. }
  19234. #endif
  19235. /******************************************************************************/
  19236. #ifndef WITH_LEAN
  19237. static const char *
  19238. soap_set_validation_fault(struct soap *soap, const char *s, const char *t) {
  19239. if (!t)
  19240. t = SOAP_STR_EOS;
  19241. if (*soap->tag)
  19242. (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(s) + strlen(t) + strlen(soap->tag) + 47),
  19243. "Validation constraint violation: %s%s in element '%s'", s, t, soap->tag);
  19244. else
  19245. (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(s) + strlen(t) + 33),
  19246. "Validation constraint violation: %s%s", s, t);
  19247. return soap->msgbuf;
  19248. }
  19249. #endif
  19250. /******************************************************************************/
  19251. SOAP_FMAC1
  19252. void
  19253. SOAP_FMAC2
  19254. soap_set_fault(struct soap *soap) {
  19255. const char **c;
  19256. const char **s;
  19257. if (soap->version == 0)
  19258. soap_version(soap);
  19259. c = soap_faultcode(soap);
  19260. s = soap_faultstring(soap);
  19261. if (soap->fseterror)
  19262. soap->fseterror(soap, c, s);
  19263. if (!*c) {
  19264. if (soap->version == 2)
  19265. *c = "SOAP-ENV:Sender";
  19266. else if (soap->version == 1)
  19267. *c = "SOAP-ENV:Client";
  19268. else
  19269. *c = "";
  19270. }
  19271. if (*s)
  19272. return;
  19273. if (soap->error >= SOAP_POST)
  19274. soap->error = SOAP_HTTP_METHOD;
  19275. switch (soap->error) {
  19276. #ifndef WITH_LEAN
  19277. case SOAP_CLI_FAULT:
  19278. *s = "Client fault";
  19279. break;
  19280. case SOAP_SVR_FAULT:
  19281. *s = "Server fault";
  19282. break;
  19283. case SOAP_TAG_MISMATCH:
  19284. *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL);
  19285. break;
  19286. case SOAP_TYPE:
  19287. if (*soap->type)
  19288. *s = soap_set_validation_fault(soap, "type mismatch ", soap->type);
  19289. else if (*soap->arrayType)
  19290. *s = soap_set_validation_fault(soap, "array type mismatch", NULL);
  19291. else
  19292. *s = soap_set_validation_fault(soap, "invalid value", NULL);
  19293. break;
  19294. case SOAP_SYNTAX_ERROR:
  19295. *s = soap_set_validation_fault(soap, "syntax error", NULL);
  19296. break;
  19297. case SOAP_NO_TAG:
  19298. if (soap->version == 0 && soap->level == 0)
  19299. *s = soap_set_validation_fault(soap, "root element expected", NULL);
  19300. else if (soap->level == 0)
  19301. *s = soap_set_validation_fault(soap, "SOAP message expected", NULL);
  19302. else
  19303. *s = soap_set_validation_fault(soap, "element tag expected", NULL);
  19304. break;
  19305. case SOAP_END_TAG:
  19306. *s = soap_set_validation_fault(soap, "closing tag expected", NULL);
  19307. break;
  19308. case SOAP_MUSTUNDERSTAND:
  19309. *c = "SOAP-ENV:MustUnderstand";
  19310. (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(soap->tag) + 65),
  19311. "The data in element '%s' must be understood but cannot be processed, Sassan %s", soap->tag, debug);
  19312. *s = soap->msgbuf;
  19313. break;
  19314. case SOAP_VERSIONMISMATCH:
  19315. *c = "SOAP-ENV:VersionMismatch";
  19316. *s = "Invalid SOAP message or SOAP version mismatch";
  19317. break;
  19318. case SOAP_DATAENCODINGUNKNOWN:
  19319. *c = "SOAP-ENV:DataEncodingUnknown";
  19320. *s = "Unsupported SOAP data encoding";
  19321. break;
  19322. case SOAP_NAMESPACE:
  19323. *s = soap_set_validation_fault(soap, "namespace error", NULL);
  19324. break;
  19325. case SOAP_USER_ERROR:
  19326. *s = "User data access error";
  19327. break;
  19328. case SOAP_NO_METHOD:
  19329. (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(soap->tag) + 66),
  19330. "Method '%s' not implemented: method name or namespace not recognized", soap->tag);
  19331. *s = soap->msgbuf;
  19332. break;
  19333. case SOAP_NO_DATA:
  19334. *s = "Data required for operation";
  19335. break;
  19336. case SOAP_GET_METHOD:
  19337. *s = "HTTP GET method not implemented";
  19338. break;
  19339. case SOAP_PUT_METHOD:
  19340. *s = "HTTP PUT method not implemented";
  19341. break;
  19342. case SOAP_PATCH_METHOD:
  19343. *s = "HTTP PATCH method not implemented";
  19344. break;
  19345. case SOAP_DEL_METHOD:
  19346. *s = "HTTP DELETE method not implemented";
  19347. break;
  19348. case SOAP_HTTP_METHOD:
  19349. *s = "HTTP method error";
  19350. break;
  19351. case SOAP_EOM:
  19352. *s = "Out of memory";
  19353. break;
  19354. case SOAP_MOE:
  19355. *s = "Memory overflow or memory corruption error";
  19356. break;
  19357. case SOAP_HDR:
  19358. *s = "Header line too long";
  19359. break;
  19360. case SOAP_IOB:
  19361. *s = "Array index out of bounds";
  19362. break;
  19363. case SOAP_NULL:
  19364. *s = soap_set_validation_fault(soap, "nil not allowed", NULL);
  19365. break;
  19366. case SOAP_DUPLICATE_ID:
  19367. *s = soap_set_validation_fault(soap, "multiple elements (use the SOAP_XML_TREE flag) with duplicate id ",
  19368. soap->id);
  19369. if (soap->version == 2)
  19370. *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID";
  19371. break;
  19372. case SOAP_MISSING_ID:
  19373. *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id);
  19374. if (soap->version == 2)
  19375. *soap_faultsubcode(soap) = "SOAP-ENC:MissingID";
  19376. break;
  19377. case SOAP_HREF:
  19378. *s = soap_set_validation_fault(soap, "incompatible object type id-ref ", soap->id);
  19379. break;
  19380. case SOAP_FAULT:
  19381. break;
  19382. #ifndef WITH_NOIO
  19383. case SOAP_UDP_ERROR:
  19384. *s = "Message too large for UDP packet";
  19385. break;
  19386. case SOAP_TCP_ERROR:
  19387. *s = tcp_error(soap);
  19388. break;
  19389. #endif
  19390. case SOAP_HTTP_ERROR:
  19391. *s = "An HTTP processing error occurred";
  19392. break;
  19393. case SOAP_NTLM_ERROR:
  19394. *s = "An HTTP NTLM authentication error occurred";
  19395. break;
  19396. case SOAP_SSL_ERROR:
  19397. #ifdef WITH_OPENSSL
  19398. *s = "SSL/TLS error";
  19399. #else
  19400. *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL";
  19401. #endif
  19402. break;
  19403. case SOAP_PLUGIN_ERROR:
  19404. *s = "Plugin registry error";
  19405. break;
  19406. case SOAP_DIME_ERROR:
  19407. *s = "DIME format error or max DIME size exceeds SOAP_MAXDIMESIZE currently set to " SOAP_XSTRINGIFY(
  19408. SOAP_MAXDIMESIZE);
  19409. break;
  19410. case SOAP_DIME_HREF:
  19411. *s = "DIME href to missing attachment";
  19412. break;
  19413. case SOAP_DIME_MISMATCH:
  19414. *s = "DIME version/transmission error";
  19415. break;
  19416. case SOAP_DIME_END:
  19417. *s = "End of DIME error";
  19418. break;
  19419. case SOAP_MIME_ERROR:
  19420. *s = "MIME format error";
  19421. break;
  19422. case SOAP_MIME_HREF:
  19423. *s = "MIME href to missing attachment";
  19424. break;
  19425. case SOAP_MIME_END:
  19426. *s = "End of MIME error";
  19427. break;
  19428. case SOAP_ZLIB_ERROR:
  19429. #ifdef WITH_ZLIB
  19430. (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), (soap->d_stream && soap->d_stream->msg ? strlen(soap->d_stream->msg) : 0) + 19), "Zlib/gzip error: '%s'", soap->d_stream && soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS);
  19431. *s = soap->msgbuf;
  19432. #else
  19433. *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP";
  19434. #endif
  19435. break;
  19436. case SOAP_REQUIRED:
  19437. *s = soap_set_validation_fault(soap, "missing required attribute", NULL);
  19438. break;
  19439. case SOAP_PROHIBITED:
  19440. *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL);
  19441. break;
  19442. case SOAP_LEVEL:
  19443. *s = "Maximum XML nesting depth level exceeded: increase maxlevel";
  19444. break;
  19445. case SOAP_LENGTH:
  19446. *s = soap_set_validation_fault(soap, "value range or content length violation", NULL);
  19447. break;
  19448. case SOAP_OCCURS:
  19449. *s = soap_set_validation_fault(soap, "occurrence constraint violation", NULL);
  19450. break;
  19451. case SOAP_FIXED:
  19452. *s = soap_set_validation_fault(soap, "value does not match the fixed value required", NULL);
  19453. break;
  19454. case SOAP_EMPTY:
  19455. *s = soap_set_validation_fault(soap, "empty value provided where a value is required", NULL);
  19456. break;
  19457. case SOAP_FD_EXCEEDED:
  19458. *s = "Maximum number of open connections was reached: increase FD_SETSIZE or define HAVE_POLL";
  19459. break;
  19460. case SOAP_UTF_ERROR:
  19461. *s = "UTF content encoding error";
  19462. break;
  19463. case SOAP_STOP:
  19464. *s = "Stopped: service request already handled by plugin (informative)";
  19465. break;
  19466. #endif
  19467. case SOAP_EOF:
  19468. #ifndef WITH_NOIO
  19469. *s = soap_strerror(soap); /* *s = soap->msgbuf */
  19470. #ifndef WITH_LEAN
  19471. if (strlen(soap->msgbuf) + 25 < sizeof(soap->msgbuf)) {
  19472. (void) soap_memmove((void *) (soap->msgbuf + 25), sizeof(soap->tmpbuf) - 25,
  19473. (const void *) soap->msgbuf, strlen(soap->msgbuf) + 1);
  19474. if (soap->is)
  19475. #if defined(__cplusplus) && !defined(WITH_COMPAT)
  19476. (void) soap_memcpy((void *) soap->msgbuf, sizeof(soap->msgbuf),
  19477. (const void *) "End or bad std::istream: ", 25);
  19478. #else
  19479. (void)soap_memcpy((void*)soap->msgbuf, sizeof(soap->msgbuf), (const void*)"End at NUL buffer input: ", 25);
  19480. #endif
  19481. else
  19482. (void) soap_memcpy((void *) soap->msgbuf, sizeof(soap->msgbuf),
  19483. (const void *) "End of file or no input: ", 25);
  19484. }
  19485. #endif
  19486. break;
  19487. #else
  19488. *s = "End of file or no input";
  19489. break;
  19490. #endif
  19491. case SOAP_ERR:
  19492. *s = "An unspecified error occurred";
  19493. break;
  19494. default:
  19495. #ifndef WITH_NOHTTP
  19496. #ifndef WITH_LEAN
  19497. if (soap->error >= 200 && soap->error < 600) {
  19498. const char *t = http_error(soap, soap->error);
  19499. (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(t) + 54), "Error %d: HTTP %d %s", soap->error,
  19500. soap->error, t);
  19501. *s = soap->msgbuf;
  19502. } else
  19503. #endif
  19504. #endif
  19505. {
  19506. (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), 26), "Error %d", soap->error);
  19507. *s = soap->msgbuf;
  19508. }
  19509. }
  19510. }
  19511. /******************************************************************************/
  19512. SOAP_FMAC1
  19513. int
  19514. SOAP_FMAC2
  19515. soap_send_fault(struct soap *soap) {
  19516. int status = soap->error;
  19517. if (status == SOAP_OK || status == SOAP_STOP)
  19518. return soap_closesock(soap);
  19519. #ifndef WITH_NOHTTP
  19520. if (status >= 200 && status <= 299)
  19521. return soap_send_empty_response(soap, status);
  19522. #endif
  19523. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error));
  19524. soap->keep_alive = 0; /* error: close connection later by disabling keep-alive here */
  19525. soap_set_fault(soap);
  19526. if (soap->error < 200 && soap->error != SOAP_FAULT)
  19527. soap->header = NULL;
  19528. if (status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout)) {
  19529. int r = 1;
  19530. #ifndef WITH_NOIO
  19531. if (soap->fpoll && soap->fpoll(soap)) {
  19532. r = 0;
  19533. }
  19534. #ifndef WITH_LEAN
  19535. else if (soap_valid_socket(soap->socket)) {
  19536. r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_SND, 0);
  19537. if (r > 0) {
  19538. int t;
  19539. if (!(r & SOAP_TCP_SELECT_SND)
  19540. || ((r & SOAP_TCP_SELECT_RCV)
  19541. && recv(soap->socket, (char *) &t, 1, MSG_PEEK) < 0))
  19542. r = 0;
  19543. }
  19544. }
  19545. #endif
  19546. #endif
  19547. if (r > 0) {
  19548. soap->error = SOAP_OK;
  19549. if (soap->version > 0) {
  19550. soap->encodingStyle = NULL; /* no encodingStyle in Faults */
  19551. soap_serializeheader(soap);
  19552. soap_serializefault(soap);
  19553. (void) soap_begin_count(soap);
  19554. if ((soap->mode & SOAP_IO_LENGTH)) {
  19555. if (soap_envelope_begin_out(soap)
  19556. || soap_putheader(soap)
  19557. || soap_body_begin_out(soap)
  19558. || soap_putfault(soap)
  19559. || soap_body_end_out(soap)
  19560. || soap_envelope_end_out(soap))
  19561. return soap_closesock(soap);
  19562. }
  19563. (void) soap_end_count(soap);
  19564. if (soap_response(soap, status)
  19565. || soap_envelope_begin_out(soap)
  19566. || soap_putheader(soap)
  19567. || soap_body_begin_out(soap)
  19568. || soap_putfault(soap)
  19569. || soap_body_end_out(soap)
  19570. || soap_envelope_end_out(soap)
  19571. || soap_end_send(soap))
  19572. return soap_closesock(soap);
  19573. } else {
  19574. const char *s = *soap_faultstring(soap);
  19575. const char **d = soap_faultdetail(soap);
  19576. (void) soap_begin_count(soap);
  19577. if ((soap->mode & SOAP_IO_LENGTH))
  19578. if (soap_element_begin_out(soap, "fault", 0, NULL)
  19579. || soap_outstring(soap, "reason", 0, (char *const *) &s, NULL, 0)
  19580. || soap_outliteral(soap, "detail", (char *const *) d, NULL)
  19581. || soap_element_end_out(soap, "fault"))
  19582. return soap_closesock(soap);
  19583. (void) soap_end_count(soap);
  19584. if (soap_response(soap, status)
  19585. || soap_element_begin_out(soap, "fault", 0, NULL)
  19586. || soap_outstring(soap, "reason", 0, (char *const *) &s, NULL, 0)
  19587. || soap_outliteral(soap, "detail", (char *const *) d, NULL)
  19588. || soap_element_end_out(soap, "fault")
  19589. || soap_end_send(soap))
  19590. return soap_closesock(soap);
  19591. }
  19592. }
  19593. }
  19594. soap->error = status;
  19595. return soap_closesock(soap);
  19596. }
  19597. /******************************************************************************/
  19598. SOAP_FMAC1
  19599. int
  19600. SOAP_FMAC2
  19601. soap_recv_fault(struct soap *soap, int check) {
  19602. int status = soap->status;
  19603. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Check (%d) if receiving SOAP Fault (status = %d)\n", check, status));
  19604. if (!check) {
  19605. /* try getfault when no tag or tag mismatched at level 2, otherwise close and return SOAP_TAG_MISMATCH or HTTP error code */
  19606. if (soap->error != SOAP_NO_TAG && (soap->error != SOAP_TAG_MISMATCH || soap->level != 2)) {
  19607. if (soap->error == SOAP_TAG_MISMATCH && soap->level == 0) {
  19608. soap->error = SOAP_OK;
  19609. if (!soap_element_begin_in(soap, "fault", 0, NULL)) {
  19610. char *s = NULL, *d = NULL;
  19611. (void) soap_instring(soap, "reason", &s, NULL, 0, 1, 0, -1, NULL);
  19612. (void) soap_inliteral(soap, "detail", &d);
  19613. if (!soap_element_end_in(soap, "fault") && !soap_end_recv(soap)) {
  19614. *soap_faultstring(soap) = s;
  19615. *soap_faultdetail(soap) = d;
  19616. if (status)
  19617. soap->error = status;
  19618. else
  19619. soap->error = SOAP_FAULT;
  19620. soap_set_fault(soap);
  19621. return soap_closesock(soap);
  19622. }
  19623. }
  19624. soap->error = SOAP_TAG_MISMATCH;
  19625. }
  19626. if (status && (status < 200 || status > 299))
  19627. soap->error = status;
  19628. return soap_closesock(soap);
  19629. }
  19630. }
  19631. soap->error = SOAP_OK;
  19632. if (soap_getfault(soap)) {
  19633. /* if check>0 and no SOAP Fault is present and no HTTP error then just return to parse request */
  19634. if (check
  19635. && (status == 0 || (status >= 200 && status <= 299))
  19636. && ((soap->error == SOAP_TAG_MISMATCH && soap->level == 2) || soap->error == SOAP_NO_TAG))
  19637. return soap->error = SOAP_OK;
  19638. /* if check=0 and empty SOAP Body and encodingStyle is NULL and no HTTP error then just return */
  19639. if (!check
  19640. && (status == 0 || (status >= 200 && status <= 299))
  19641. && !soap->encodingStyle
  19642. && (soap->error == SOAP_NO_TAG && soap->level <= 2))
  19643. return soap->error = SOAP_OK;
  19644. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed with error %d at level %u tag '%s'\n",
  19645. soap->error, soap->level, soap->tag));
  19646. *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client");
  19647. if (status)
  19648. soap->error = status;
  19649. else
  19650. soap->error = status = SOAP_NO_DATA;
  19651. soap_set_fault(soap);
  19652. } else {
  19653. const char *s = *soap_faultcode(soap);
  19654. if (!soap_match_tag(soap, s, "SOAP-ENV:Server")
  19655. || !soap_match_tag(soap, s, "SOAP-ENV:Receiver")) {
  19656. status = SOAP_SVR_FAULT;
  19657. } else if (!soap_match_tag(soap, s, "SOAP-ENV:Client")
  19658. || !soap_match_tag(soap, s, "SOAP-ENV:Sender")) {
  19659. status = SOAP_CLI_FAULT;
  19660. } else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand")) {
  19661. status = SOAP_MUSTUNDERSTAND;
  19662. } else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch")) {
  19663. status = SOAP_VERSIONMISMATCH;
  19664. } else {
  19665. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Received SOAP Fault code %s\n", s));
  19666. status = SOAP_FAULT;
  19667. }
  19668. if (!soap_body_end_in(soap))
  19669. soap_envelope_end_in(soap);
  19670. }
  19671. (void) soap_end_recv(soap);
  19672. soap->error = status;
  19673. return soap_closesock(soap);
  19674. }
  19675. /******************************************************************************/
  19676. #ifndef WITH_NOHTTP
  19677. SOAP_FMAC1
  19678. int
  19679. SOAP_FMAC2
  19680. soap_send_empty_response(struct soap *soap, int httpstatuscode) {
  19681. soap_mode m = soap->omode;
  19682. if (!(m & SOAP_IO_UDP)) {
  19683. soap->count = 0;
  19684. if ((m & SOAP_IO) == SOAP_IO_CHUNK)
  19685. soap->omode = (m & ~SOAP_IO) | SOAP_IO_BUFFER;
  19686. (void) soap_response(soap, httpstatuscode);
  19687. (void) soap_end_send(soap); /* force end of sends */
  19688. soap->error = SOAP_STOP; /* stops the server from returning another response */
  19689. soap->omode = m;
  19690. }
  19691. return soap_closesock(soap);
  19692. }
  19693. #endif
  19694. /******************************************************************************/
  19695. #ifndef WITH_NOHTTP
  19696. SOAP_FMAC1
  19697. int
  19698. SOAP_FMAC2
  19699. soap_recv_empty_response(struct soap *soap) {
  19700. soap->error = SOAP_OK;
  19701. if (!(soap->omode & SOAP_IO_UDP) && !(soap->omode & SOAP_ENC_PLAIN)) {
  19702. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Receiving empty response\n"));
  19703. if (soap_begin_recv(soap) == SOAP_OK) {
  19704. if (soap_http_skip_body(soap) || soap_end_recv(soap))
  19705. return soap_closesock(soap);
  19706. } else if (soap->error == 200 || soap->error == 201 || soap->error == 202) {
  19707. soap->error = SOAP_OK;
  19708. }
  19709. }
  19710. #ifndef WITH_LEANER
  19711. else if ((soap->fprepareinitrecv && (soap->error = soap->fprepareinitrecv(soap)))
  19712. || (soap->fpreparefinalrecv && (soap->error = soap->fpreparefinalrecv(soap)))) {
  19713. return soap->error;
  19714. }
  19715. #endif
  19716. return soap_closesock(soap);
  19717. }
  19718. #endif
  19719. /******************************************************************************/
  19720. #ifndef WITH_NOIO
  19721. static const char *
  19722. soap_strerror(struct soap *soap) {
  19723. int err = soap->errnum;
  19724. *soap->msgbuf = '\0';
  19725. if (err) {
  19726. #ifndef WIN32
  19727. # ifdef HAVE_STRERROR_R
  19728. # if (!_GNU_SOURCE && !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__ANDROID__) || !defined(__GLIBC__)
  19729. strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* XSI-compliant */
  19730. # else
  19731. return strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* GNU-specific */
  19732. # endif
  19733. # else
  19734. return strerror(err);
  19735. # endif
  19736. #else
  19737. #ifndef UNDER_CE
  19738. DWORD len;
  19739. *soap->msgbuf = '\0';
  19740. len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)soap->msgbuf, (DWORD)sizeof(soap->msgbuf), NULL);
  19741. #else
  19742. DWORD i, len;
  19743. *soap->msgbuf = '\0';
  19744. len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)soap->msgbuf, (DWORD)(sizeof(soap->msgbuf)/sizeof(TCHAR)), NULL);
  19745. for (i = 0; i <= len; i++)
  19746. {
  19747. if (((TCHAR*)soap->msgbuf)[i] < 0x80)
  19748. soap->msgbuf[i] = (char)((TCHAR*)soap->msgbuf)[i];
  19749. else
  19750. soap->msgbuf[i] = '?';
  19751. }
  19752. #endif
  19753. #endif
  19754. } else {
  19755. if (soap->recv_maxlength && soap->count > soap->recv_maxlength) {
  19756. soap_strcpy(soap->msgbuf, sizeof(soap->msgbuf), "max message length exceeded");
  19757. } else {
  19758. int tt = soap->transfer_timeout, rt = soap->recv_timeout, st = soap->send_timeout;
  19759. #ifndef WITH_LEAN
  19760. int tu = ' ', ru = ' ', su = ' ';
  19761. #endif
  19762. soap_strcpy(soap->msgbuf, sizeof(soap->msgbuf), "message transfer interrupted");
  19763. if (tt | rt || st)
  19764. soap_strcpy(soap->msgbuf + 28, sizeof(soap->msgbuf) - 28, " or timed out");
  19765. #ifndef WITH_LEAN
  19766. if (tt < 0) {
  19767. tt = -tt;
  19768. tu = 'u';
  19769. }
  19770. if (rt < 0) {
  19771. rt = -rt;
  19772. ru = 'u';
  19773. }
  19774. if (st < 0) {
  19775. st = -st;
  19776. su = 'u';
  19777. }
  19778. if (tt) {
  19779. size_t l = strlen(soap->msgbuf);
  19780. (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, 43), " (%d%csec max transfer time)", tt, tu);
  19781. }
  19782. if (rt) {
  19783. size_t l = strlen(soap->msgbuf);
  19784. (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, 40), " (%d%csec max recv delay)", rt, ru);
  19785. }
  19786. if (st) {
  19787. size_t l = strlen(soap->msgbuf);
  19788. (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, 40), " (%d%csec max send delay)", st, su);
  19789. }
  19790. #endif
  19791. }
  19792. }
  19793. return soap->msgbuf;
  19794. }
  19795. #endif
  19796. /******************************************************************************/
  19797. static int
  19798. soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring,
  19799. const char *faultdetailXML, int soaperror) {
  19800. *soap_faultcode(soap) = faultcode;
  19801. if (faultsubcodeQName)
  19802. *soap_faultsubcode(soap) = faultsubcodeQName;
  19803. *soap_faultstring(soap) = faultstring;
  19804. if (faultdetailXML && *faultdetailXML) {
  19805. const char **s = soap_faultdetail(soap);
  19806. if (s)
  19807. *s = faultdetailXML;
  19808. }
  19809. return soap->error = soaperror;
  19810. }
  19811. /******************************************************************************/
  19812. SOAP_FMAC1
  19813. int
  19814. SOAP_FMAC2
  19815. soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror) {
  19816. return soap_set_error(soap,
  19817. soap->version == 2 ? "SOAP-ENV:Sender" : soap->version == 1 ? "SOAP-ENV:Client" : "at sender",
  19818. NULL, faultstring, faultdetailXML, soaperror);
  19819. }
  19820. /******************************************************************************/
  19821. SOAP_FMAC1
  19822. int
  19823. SOAP_FMAC2
  19824. soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror) {
  19825. return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : soap->version == 1 ? "SOAP-ENV:Server"
  19826. : "detected", NULL,
  19827. faultstring, faultdetailXML, soaperror);
  19828. }
  19829. /******************************************************************************/
  19830. static int
  19831. soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring,
  19832. const char *faultdetailXML) {
  19833. char *r = NULL, *s = NULL, *t = NULL;
  19834. DBGFUN2("soap_copy_fault", "code=%s", faultcode ? faultcode : "(null)", "string=%s",
  19835. faultstring ? faultstring : "(null)")
  19836. if (faultsubcodeQName)
  19837. r = soap_strdup(soap, faultsubcodeQName);
  19838. if (faultstring)
  19839. s = soap_strdup(soap, faultstring);
  19840. if (faultdetailXML)
  19841. t = soap_strdup(soap, faultdetailXML);
  19842. return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT);
  19843. }
  19844. /******************************************************************************/
  19845. SOAP_FMAC1
  19846. int
  19847. SOAP_FMAC2
  19848. soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML) {
  19849. return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetailXML);
  19850. }
  19851. /******************************************************************************/
  19852. SOAP_FMAC1
  19853. int
  19854. SOAP_FMAC2
  19855. soap_sender_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring,
  19856. const char *faultdetailXML) {
  19857. return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : soap->version == 1 ? "SOAP-ENV:Client"
  19858. : "at source",
  19859. faultsubcodeQName, faultstring, faultdetailXML);
  19860. }
  19861. /******************************************************************************/
  19862. SOAP_FMAC1
  19863. int
  19864. SOAP_FMAC2
  19865. soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML) {
  19866. return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetailXML);
  19867. }
  19868. /******************************************************************************/
  19869. SOAP_FMAC1
  19870. int
  19871. SOAP_FMAC2
  19872. soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring,
  19873. const char *faultdetailXML) {
  19874. return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : soap->version == 1 ? "SOAP-ENV:Server"
  19875. : "is internal",
  19876. faultsubcodeQName, faultstring, faultdetailXML);
  19877. }
  19878. /******************************************************************************/
  19879. #ifndef WITH_NOSTDLIB
  19880. SOAP_FMAC1
  19881. void
  19882. SOAP_FMAC2
  19883. soap_print_fault(struct soap *soap, FILE *fd) {
  19884. if (soap_check_state(soap)) {
  19885. fprintf(fd, "Error: soap struct state not initialized\n");
  19886. } else if (soap->error) {
  19887. const char **c, *v = NULL, *s, *d;
  19888. c = soap_faultcode(soap);
  19889. if (!*c) {
  19890. soap_set_fault(soap);
  19891. c = soap_faultcode(soap);
  19892. }
  19893. if (soap->version == 2)
  19894. v = soap_fault_subcode(soap);
  19895. s = soap_fault_string(soap);
  19896. d = soap_fault_detail(soap);
  19897. fprintf(fd, "%s%d fault %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ",
  19898. soap->version ? (int) soap->version : soap->error, *c, v ? v : "no subcode", s ? s : "[no reason]",
  19899. d ? d : "[no detail]");
  19900. }
  19901. }
  19902. #endif
  19903. /******************************************************************************/
  19904. #ifdef __cplusplus
  19905. #ifndef WITH_LEAN
  19906. #ifndef WITH_NOSTDLIB
  19907. #ifndef WITH_COMPAT
  19908. SOAP_FMAC1
  19909. void
  19910. SOAP_FMAC2
  19911. soap_stream_fault(struct soap *soap, std::ostream &os) {
  19912. if (soap_check_state(soap)) {
  19913. os << "Error: soap struct state not initialized\n";
  19914. } else if (soap->error) {
  19915. const char **c, *v = NULL, *s, *d;
  19916. c = soap_faultcode(soap);
  19917. if (!*c) {
  19918. soap_set_fault(soap);
  19919. c = soap_faultcode(soap);
  19920. }
  19921. if (soap->version == 2)
  19922. v = soap_fault_subcode(soap);
  19923. s = soap_fault_string(soap);
  19924. d = soap_fault_detail(soap);
  19925. os << (soap->version ? "SOAP 1." : "Error ")
  19926. << (soap->version ? (int) soap->version : soap->error)
  19927. << " fault " << *c
  19928. << "[" << (v ? v : "no subcode") << "]"
  19929. << std::endl
  19930. << "\"" << (s ? s : "[no reason]") << "\""
  19931. << std::endl
  19932. << "Detail: " << (d ? d : "[no detail]")
  19933. << std::endl;
  19934. }
  19935. }
  19936. #endif
  19937. #endif
  19938. #endif
  19939. #endif
  19940. /******************************************************************************/
  19941. #ifndef WITH_LEAN
  19942. #ifndef WITH_NOSTDLIB
  19943. SOAP_FMAC1
  19944. char *
  19945. SOAP_FMAC2
  19946. soap_sprint_fault(struct soap *soap, char *buf, size_t len) {
  19947. if (soap_check_state(soap)) {
  19948. soap_strcpy(buf, len, "Error: soap struct not initialized");
  19949. } else if (soap->error) {
  19950. const char **c, *v = NULL, *s, *d;
  19951. c = soap_faultcode(soap);
  19952. if (!*c) {
  19953. soap_set_fault(soap);
  19954. c = soap_faultcode(soap);
  19955. }
  19956. if (soap->version == 2)
  19957. v = soap_fault_subcode(soap);
  19958. if (!v)
  19959. v = "no subcode";
  19960. s = soap_fault_string(soap);
  19961. if (!s)
  19962. s = "[no reason]";
  19963. d = soap_fault_detail(soap);
  19964. if (!d)
  19965. d = "[no detail]";
  19966. (SOAP_SNPRINTF(buf, len, strlen(*c) + strlen(v) + strlen(s) + strlen(d) + 72),
  19967. "%s%d fault %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ",
  19968. soap->version ? (int) soap->version : soap->error, *c, v, s, d);
  19969. } else if (len > 0) {
  19970. *buf = '\0';
  19971. }
  19972. return buf;
  19973. }
  19974. #endif
  19975. #endif
  19976. /******************************************************************************/
  19977. #ifndef WITH_NOSTDLIB
  19978. SOAP_FMAC1
  19979. void
  19980. SOAP_FMAC2
  19981. soap_print_fault_location(struct soap *soap, FILE *fd) {
  19982. #ifndef WITH_LEAN
  19983. int i, j, c1, c2;
  19984. if (soap_check_state(soap) == SOAP_OK && soap->error && soap->error != SOAP_STOP && soap->bufidx <= soap->buflen &&
  19985. soap->buflen > 0 && soap->buflen <= sizeof(soap->buf)) {
  19986. i = (int) soap->bufidx - 1;
  19987. if (i <= 0)
  19988. i = 0;
  19989. c1 = soap->buf[i];
  19990. soap->buf[i] = '\0';
  19991. if ((int) soap->buflen >= i + 1024)
  19992. j = i + 1023;
  19993. else
  19994. j = (int) soap->buflen - 1;
  19995. c2 = soap->buf[j];
  19996. soap->buf[j] = '\0';
  19997. fprintf(fd, "%s%c\n<!-- ** HERE ** -->\n", soap->buf, c1);
  19998. if (soap->bufidx < soap->buflen)
  19999. fprintf(fd, "%s\n", soap->buf + soap->bufidx);
  20000. soap->buf[i] = (char) c1;
  20001. soap->buf[j] = (char) c2;
  20002. }
  20003. #else
  20004. (void)soap;
  20005. (void)fd;
  20006. #endif
  20007. }
  20008. #endif
  20009. /******************************************************************************/
  20010. #ifdef __cplusplus
  20011. #ifndef WITH_LEAN
  20012. #ifndef WITH_NOSTDLIB
  20013. #ifndef WITH_COMPAT
  20014. SOAP_FMAC1
  20015. void
  20016. SOAP_FMAC2
  20017. soap_stream_fault_location(struct soap *soap, std::ostream &os) {
  20018. int i, j, c1, c2;
  20019. if (soap_check_state(soap) == SOAP_OK && soap->error && soap->error != SOAP_STOP && soap->bufidx <= soap->buflen &&
  20020. soap->buflen > 0 && soap->buflen <= sizeof(soap->buf)) {
  20021. i = (int) soap->bufidx - 1;
  20022. if (i <= 0)
  20023. i = 0;
  20024. c1 = soap->buf[i];
  20025. soap->buf[i] = '\0';
  20026. if ((int) soap->buflen >= i + 1024)
  20027. j = i + 1023;
  20028. else
  20029. j = (int) soap->buflen - 1;
  20030. c2 = soap->buf[j];
  20031. soap->buf[j] = '\0';
  20032. os << soap->buf << (char) c1 << std::endl << "<!-- ** HERE ** -->" << std::endl;
  20033. if (soap->bufidx < soap->buflen)
  20034. os << soap->buf + soap->bufidx << std::endl;
  20035. soap->buf[i] = (char) c1;
  20036. soap->buf[j] = (char) c2;
  20037. }
  20038. }
  20039. #endif
  20040. #endif
  20041. #endif
  20042. #endif
  20043. /******************************************************************************/
  20044. SOAP_FMAC1
  20045. int
  20046. SOAP_FMAC2
  20047. soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap *, struct soap_plugin *, void *), void *arg) {
  20048. struct soap_plugin *p;
  20049. int err;
  20050. p = (struct soap_plugin *) SOAP_MALLOC(soap, sizeof(struct soap_plugin));
  20051. if (!p)
  20052. return soap->error = SOAP_EOM;
  20053. p->id = NULL;
  20054. p->data = NULL;
  20055. p->fcopy = NULL;
  20056. p->fdelete = NULL;
  20057. err = fcreate(soap, p, arg);
  20058. if (!err && p->fdelete && p->id) {
  20059. if (!soap_lookup_plugin(soap, p->id)) {
  20060. p->next = soap->plugins;
  20061. soap->plugins = p;
  20062. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id));
  20063. return SOAP_OK;
  20064. }
  20065. DBGLOG(TEST,
  20066. SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin with the same ID already registered\n",
  20067. p->id));
  20068. SOAP_FREE(soap, p);
  20069. return SOAP_OK;
  20070. }
  20071. DBGLOG(TEST, SOAP_MESSAGE(fdebug,
  20072. "Could not register plugin '%s': plugin returned error %d or plugin ID not set or fdelete callback not set\n",
  20073. p->id ? p->id : "plugin ID not set", err));
  20074. SOAP_FREE(soap, p);
  20075. soap->error = err ? err : SOAP_PLUGIN_ERROR;
  20076. return soap->error;
  20077. }
  20078. /******************************************************************************/
  20079. static void *
  20080. fplugin(struct soap *soap, const char *id) {
  20081. struct soap_plugin *p;
  20082. for (p = soap->plugins; p; p = p->next)
  20083. if (p->id == id || !strcmp(p->id, id))
  20084. return p->data;
  20085. return NULL;
  20086. }
  20087. /******************************************************************************/
  20088. SOAP_FMAC1
  20089. void *
  20090. SOAP_FMAC2
  20091. soap_lookup_plugin(struct soap *soap, const char *id) {
  20092. return soap->fplugin(soap, id);
  20093. }
  20094. /******************************************************************************/
  20095. #ifdef __cplusplus
  20096. }
  20097. #endif
  20098. /******************************************************************************\
  20099. *
  20100. * C++ soap struct methods
  20101. *
  20102. \******************************************************************************/
  20103. #ifdef __cplusplus
  20104. soap::soap() {
  20105. soap_init(this);
  20106. /* no logs to prevent DEBUG mode leaks when the user calls a soap_init() on this context */
  20107. soap_set_test_logfile(this, NULL);
  20108. soap_set_sent_logfile(this, NULL);
  20109. soap_set_recv_logfile(this, NULL);
  20110. }
  20111. #endif
  20112. /******************************************************************************/
  20113. #ifdef __cplusplus
  20114. soap::soap(soap_mode m) {
  20115. soap_init1(this, m);
  20116. }
  20117. #endif
  20118. /******************************************************************************/
  20119. #ifdef __cplusplus
  20120. soap::soap(soap_mode im, soap_mode om) {
  20121. soap_init2(this, im, om);
  20122. }
  20123. #endif
  20124. /******************************************************************************/
  20125. #ifdef __cplusplus
  20126. soap::soap(const struct soap &soap) {
  20127. soap_copy_context(this, &soap);
  20128. }
  20129. #endif
  20130. /******************************************************************************/
  20131. #ifdef __cplusplus
  20132. struct soap &soap::operator=(const struct soap &soap) {
  20133. soap_done(this);
  20134. soap_copy_context(this, &soap);
  20135. return *this;
  20136. }
  20137. #endif
  20138. /******************************************************************************/
  20139. #ifdef __cplusplus
  20140. void soap::destroy() {
  20141. soap_destroy(this);
  20142. soap_end(this);
  20143. }
  20144. #endif
  20145. /******************************************************************************/
  20146. #ifdef __cplusplus
  20147. soap::~soap() {
  20148. soap_done(this);
  20149. }
  20150. #endif
  20151. /******************************************************************************/