stdsoap2.cpp 617 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860
  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 *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized, short isearly);
  138. static void soap_utilize_ns(struct soap *soap, const char *tag, short isearly);
  139. static const wchar_t* soap_wstring(struct soap *soap, const char *s, int flag, long minlen, long maxlen, const char *pattern);
  140. static wchar_t* soap_wcollapse(struct soap *soap, wchar_t *s, int flag, int insitu);
  141. #endif
  142. static const char* soap_string(struct soap *soap, const char *s, int flag, long minlen, long maxlen, const char *pattern);
  143. static char* soap_collapse(struct soap *soap, char *s, int flag, int insitu);
  144. static const char* soap_QName(struct soap *soap, const char *s, long minlen, long maxlen, const char *pattern);
  145. #ifndef WITH_LEANER
  146. static int soap_begin_attachments(struct soap*);
  147. static int soap_end_attachments(struct soap *soap);
  148. static struct soap_multipart *soap_alloc_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, const char*, size_t);
  149. static int soap_putdimefield(struct soap*, const char*, size_t);
  150. static char *soap_getdimefield(struct soap*, size_t);
  151. static void soap_select_mime_boundary(struct soap*);
  152. static int soap_valid_mime_boundary(struct soap*);
  153. static void soap_resolve_attachment(struct soap*, struct soap_multipart*);
  154. #endif
  155. #ifdef WITH_GZIP
  156. static int soap_getgziphdr(struct soap*);
  157. #endif
  158. #ifdef WITH_OPENSSL
  159. # ifndef SOAP_SSL_RSA_BITS
  160. # define SOAP_SSL_RSA_BITS 2048
  161. # endif
  162. static int soap_ssl_init_done = 0;
  163. static int ssl_auth_init(struct soap*);
  164. static int ssl_verify_callback(int, X509_STORE_CTX*);
  165. static int ssl_verify_callback_allow_expired_certificate(int, X509_STORE_CTX*);
  166. static int ssl_password(char*, int, int, void *);
  167. #endif
  168. #ifdef WITH_GNUTLS
  169. # ifndef SOAP_SSL_RSA_BITS
  170. # define SOAP_SSL_RSA_BITS 2048
  171. # endif
  172. static int soap_ssl_init_done = 0;
  173. static int ssl_auth_init(struct soap*);
  174. static const char *ssl_verify(struct soap *soap, const char *host);
  175. # if GNUTLS_VERSION_NUMBER < 0x020b00
  176. # if defined(HAVE_PTHREAD_H)
  177. # include <pthread.h>
  178. /* make GNUTLS thread safe with pthreads */
  179. GCRY_THREAD_OPTION_PTHREAD_IMPL;
  180. # elif defined(HAVE_PTH_H)
  181. #include <pth.h>
  182. /* make GNUTLS thread safe with PTH */
  183. GCRY_THREAD_OPTION_PTH_IMPL;
  184. # endif
  185. # endif
  186. #endif
  187. #ifdef WITH_SYSTEMSSL
  188. static int ssl_auth_init(struct soap*);
  189. static int ssl_recv(int sk, void *s, int n, char *user);
  190. static int ssl_send(int sk, void *s, int n, char *user);
  191. #endif
  192. #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
  193. static const char * soap_decode(char*, size_t, const char*, const char*);
  194. #endif
  195. #ifndef WITH_NOHTTP
  196. static soap_wchar soap_getchunkchar(struct soap*);
  197. static const char *http_error(struct soap*, int);
  198. static int http_get(struct soap*);
  199. static int http_put(struct soap*);
  200. static int http_patch(struct soap*);
  201. static int http_del(struct soap*);
  202. static int http_200(struct soap*);
  203. static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, ULONG64);
  204. static int http_send_header(struct soap*, const char*);
  205. static int http_post_header(struct soap*, const char*, const char*);
  206. static int http_response(struct soap*, int, ULONG64);
  207. static int http_parse(struct soap*);
  208. static int http_parse_header(struct soap*, const char*, const char*);
  209. #endif
  210. #ifndef WITH_NOIO
  211. static int fsend(struct soap*, const char*, size_t);
  212. static size_t frecv(struct soap*, char*, size_t);
  213. static int tcp_init(struct soap*);
  214. static const char *tcp_error(struct soap*);
  215. #if !defined(WITH_IPV6)
  216. static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr);
  217. #endif
  218. #if !defined(WITH_IPV6) || defined(WITH_COOKIES)
  219. static int tcp_gethostbyname(struct soap*, const char *addr, struct hostent *hostent, struct in_addr *inaddr);
  220. #endif
  221. static SOAP_SOCKET tcp_connect(struct soap*, const char *endpoint, const char *host, int port);
  222. static SOAP_SOCKET tcp_accept(struct soap*, SOAP_SOCKET, struct sockaddr*, int*);
  223. static int tcp_select(struct soap*, SOAP_SOCKET, int, int);
  224. static int tcp_disconnect(struct soap*);
  225. static int tcp_closesocket(struct soap*, SOAP_SOCKET);
  226. static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int);
  227. static const char *soap_strerror(struct soap*);
  228. #define SOAP_TCP_SELECT_RCV 0x1
  229. #define SOAP_TCP_SELECT_SND 0x2
  230. #define SOAP_TCP_SELECT_ERR 0x4
  231. #define SOAP_TCP_SELECT_ALL 0x7
  232. #define SOAP_TCP_SELECT_PIP 0x8
  233. #if defined(WIN32)
  234. #define SOAP_SOCKBLOCK(fd) \
  235. { \
  236. u_long blocking = 0; \
  237. ioctlsocket(fd, FIONBIO, &blocking); \
  238. }
  239. #define SOAP_SOCKNONBLOCK(fd) \
  240. { \
  241. u_long nonblocking = 1; \
  242. ioctlsocket(fd, FIONBIO, &nonblocking); \
  243. }
  244. #elif defined(VXWORKS)
  245. #define SOAP_SOCKBLOCK(fd) \
  246. { \
  247. u_long blocking = 0; \
  248. ioctl(fd, FIONBIO, (int)(&blocking)); \
  249. }
  250. #define SOAP_SOCKNONBLOCK(fd) \
  251. { \
  252. u_long nonblocking = 1; \
  253. ioctl(fd, FIONBIO, (int)(&nonblocking)); \
  254. }
  255. #elif defined(__VMS)
  256. #define SOAP_SOCKBLOCK(fd) \
  257. { \
  258. int blocking = 0; \
  259. ioctl(fd, FIONBIO, &blocking); \
  260. }
  261. #define SOAP_SOCKNONBLOCK(fd) \
  262. { \
  263. int nonblocking = 1; \
  264. ioctl(fd, FIONBIO, &nonblocking); \
  265. }
  266. #elif defined(SYMBIAN)
  267. #define SOAP_SOCKBLOCK(fd) \
  268. { \
  269. long blocking = 0; \
  270. ioctl(fd, 0/*FIONBIO*/, &blocking); \
  271. }
  272. #define SOAP_SOCKNONBLOCK(fd) \
  273. { \
  274. long nonblocking = 1; \
  275. ioctl(fd, 0/*FIONBIO*/, &nonblocking); \
  276. }
  277. #else
  278. #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK);
  279. #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
  280. #endif
  281. #endif
  282. static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/";
  283. static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/";
  284. static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope";
  285. static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding";
  286. static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc";
  287. const union soap_double_nan soap_double_nan = {{0xFFFFFFFF, 0xFFFFFFFF}};
  288. const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  289. 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";
  290. #ifndef WITH_LEAN
  291. 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";
  292. /* Alternative indentation form for SOAP_XML_INDENT with spaces instead of tabs:
  293. static const char soap_indent[41] = "\n ";
  294. */
  295. #endif
  296. #ifndef SOAP_CANARY
  297. # define SOAP_CANARY (0xC0DE)
  298. #endif
  299. static const char soap_padding[4] = "\0\0\0";
  300. #define SOAP_STR_PADDING (soap_padding)
  301. #define SOAP_STR_EOS (soap_padding)
  302. #define SOAP_NON_NULL (soap_padding)
  303. #ifndef WITH_LEAN
  304. static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */
  305. {
  306. { 160, "nbsp" },
  307. { 161, "iexcl" },
  308. { 162, "cent" },
  309. { 163, "pound" },
  310. { 164, "curren" },
  311. { 165, "yen" },
  312. { 166, "brvbar" },
  313. { 167, "sect" },
  314. { 168, "uml" },
  315. { 169, "copy" },
  316. { 170, "ordf" },
  317. { 171, "laquo" },
  318. { 172, "not" },
  319. { 173, "shy" },
  320. { 174, "reg" },
  321. { 175, "macr" },
  322. { 176, "deg" },
  323. { 177, "plusmn" },
  324. { 178, "sup2" },
  325. { 179, "sup3" },
  326. { 180, "acute" },
  327. { 181, "micro" },
  328. { 182, "para" },
  329. { 183, "middot" },
  330. { 184, "cedil" },
  331. { 185, "sup1" },
  332. { 186, "ordm" },
  333. { 187, "raquo" },
  334. { 188, "frac14" },
  335. { 189, "frac12" },
  336. { 190, "frac34" },
  337. { 191, "iquest" },
  338. { 192, "Agrave" },
  339. { 193, "Aacute" },
  340. { 194, "Acirc" },
  341. { 195, "Atilde" },
  342. { 196, "Auml" },
  343. { 197, "Aring" },
  344. { 198, "AElig" },
  345. { 199, "Ccedil" },
  346. { 200, "Egrave" },
  347. { 201, "Eacute" },
  348. { 202, "Ecirc" },
  349. { 203, "Euml" },
  350. { 204, "Igrave" },
  351. { 205, "Iacute" },
  352. { 206, "Icirc" },
  353. { 207, "Iuml" },
  354. { 208, "ETH" },
  355. { 209, "Ntilde" },
  356. { 210, "Ograve" },
  357. { 211, "Oacute" },
  358. { 212, "Ocirc" },
  359. { 213, "Otilde" },
  360. { 214, "Ouml" },
  361. { 215, "times" },
  362. { 216, "Oslash" },
  363. { 217, "Ugrave" },
  364. { 218, "Uacute" },
  365. { 219, "Ucirc" },
  366. { 220, "Uuml" },
  367. { 221, "Yacute" },
  368. { 222, "THORN" },
  369. { 223, "szlig" },
  370. { 224, "agrave" },
  371. { 225, "aacute" },
  372. { 226, "acirc" },
  373. { 227, "atilde" },
  374. { 228, "auml" },
  375. { 229, "aring" },
  376. { 230, "aelig" },
  377. { 231, "ccedil" },
  378. { 232, "egrave" },
  379. { 233, "eacute" },
  380. { 234, "ecirc" },
  381. { 235, "euml" },
  382. { 236, "igrave" },
  383. { 237, "iacute" },
  384. { 238, "icirc" },
  385. { 239, "iuml" },
  386. { 240, "eth" },
  387. { 241, "ntilde" },
  388. { 242, "ograve" },
  389. { 243, "oacute" },
  390. { 244, "ocirc" },
  391. { 245, "otilde" },
  392. { 246, "ouml" },
  393. { 247, "divide" },
  394. { 248, "oslash" },
  395. { 249, "ugrave" },
  396. { 250, "uacute" },
  397. { 251, "ucirc" },
  398. { 252, "uuml" },
  399. { 253, "yacute" },
  400. { 254, "thorn" },
  401. { 255, "yuml" },
  402. { 0, NULL }
  403. };
  404. #endif
  405. #ifndef WITH_NOIO
  406. #ifndef WITH_LEAN
  407. static const struct soap_code_map h_error_codes[] =
  408. {
  409. #ifdef HOST_NOT_FOUND
  410. { HOST_NOT_FOUND, "Host not found" },
  411. #endif
  412. #ifdef TRY_AGAIN
  413. { TRY_AGAIN, "Try Again" },
  414. #endif
  415. #ifdef NO_RECOVERY
  416. { NO_RECOVERY, "No Recovery" },
  417. #endif
  418. #ifdef NO_DATA
  419. { NO_DATA, "No Data" },
  420. #endif
  421. #ifdef NO_ADDRESS
  422. { NO_ADDRESS, "No Address" },
  423. #endif
  424. { 0, NULL }
  425. };
  426. #endif
  427. #endif
  428. #ifndef WITH_NOHTTP
  429. #ifndef WITH_LEAN
  430. static const struct soap_code_map h_http_error_codes[] =
  431. {
  432. { 100, "Continue" },
  433. { 101, "Switching Protocols" },
  434. { 200, "OK" },
  435. { 201, "Created" },
  436. { 202, "Accepted" },
  437. { 203, "Non-Authoritative Information" },
  438. { 204, "No Content" },
  439. { 205, "Reset Content" },
  440. { 206, "Partial Content" },
  441. { 300, "Multiple Choices" },
  442. { 301, "Moved Permanently" },
  443. { 302, "Found" },
  444. { 303, "See Other" },
  445. { 304, "Not Modified" },
  446. { 305, "Use Proxy" },
  447. { 307, "Temporary Redirect" },
  448. { 400, "Bad Request" },
  449. { 401, "Unauthorized" },
  450. { 402, "Payment Required" },
  451. { 403, "Forbidden" },
  452. { 404, "Not Found" },
  453. { 405, "Method Not Allowed" },
  454. { 406, "Not Acceptable" },
  455. { 407, "Proxy Authentication Required" },
  456. { 408, "Request Time-out" },
  457. { 409, "Conflict" },
  458. { 410, "Gone" },
  459. { 411, "Length Required" },
  460. { 412, "Precondition Failed" },
  461. { 413, "Request Entity Too Large" },
  462. { 414, "Request-URI Too Large" },
  463. { 415, "Unsupported Media Type" },
  464. { 416, "Requested range not satisfiable" },
  465. { 417, "Expectation Failed" },
  466. { 422, "Unprocessable Entity" },
  467. { 426, "Upgrade Required" },
  468. { 428, "Precondition Required" },
  469. { 429, "Too Many Requests" },
  470. { 431, "Request Header Fields Too Large" },
  471. { 500, "Internal Server Error" },
  472. { 501, "Not Implemented" },
  473. { 502, "Bad Gateway" },
  474. { 503, "Service Unavailable" },
  475. { 504, "Gateway Time-out" },
  476. { 505, "HTTP Version not supported" },
  477. { 511, "Network Authentication Required" },
  478. { 0, NULL }
  479. };
  480. #endif
  481. #endif
  482. #ifdef WITH_OPENSSL
  483. static const struct soap_code_map h_ssl_error_codes[] =
  484. {
  485. #define _SSL_ERROR(e) { e, #e }
  486. _SSL_ERROR(SSL_ERROR_SSL),
  487. _SSL_ERROR(SSL_ERROR_ZERO_RETURN),
  488. _SSL_ERROR(SSL_ERROR_WANT_READ),
  489. _SSL_ERROR(SSL_ERROR_WANT_WRITE),
  490. _SSL_ERROR(SSL_ERROR_WANT_CONNECT),
  491. _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP),
  492. _SSL_ERROR(SSL_ERROR_SYSCALL),
  493. { 0, NULL }
  494. };
  495. #endif
  496. #ifndef WITH_LEANER
  497. static const struct soap_code_map mime_codes[] =
  498. {
  499. { SOAP_MIME_7BIT, "7bit" },
  500. { SOAP_MIME_8BIT, "8bit" },
  501. { SOAP_MIME_BINARY, "binary" },
  502. { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" },
  503. { SOAP_MIME_BASE64, "base64" },
  504. { SOAP_MIME_IETF_TOKEN, "ietf-token" },
  505. { SOAP_MIME_X_TOKEN, "x-token" },
  506. { 0, NULL }
  507. };
  508. #endif
  509. #ifdef WIN32
  510. static int tcp_done = 0;
  511. #endif
  512. #if (defined(_AIX43) || defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R)
  513. #ifndef h_errno
  514. extern int h_errno;
  515. #endif
  516. #endif
  517. /******************************************************************************/
  518. #ifndef WITH_NOIO
  519. static int
  520. fsend(struct soap *soap, const char *s, size_t n)
  521. {
  522. int nwritten, err;
  523. SOAP_SOCKET sk;
  524. soap->errnum = 0;
  525. #if defined(__cplusplus) && !defined(WITH_COMPAT)
  526. if (soap->os)
  527. {
  528. soap->os->write(s, (std::streamsize)n);
  529. if (soap->os->good())
  530. return SOAP_OK;
  531. return SOAP_EOF;
  532. }
  533. #endif
  534. sk = soap->sendsk;
  535. if (!soap_valid_socket(sk))
  536. sk = soap->socket;
  537. while (n)
  538. {
  539. if (soap_valid_socket(sk))
  540. {
  541. if (soap->send_timeout)
  542. {
  543. for (;;)
  544. {
  545. int r;
  546. #ifdef WITH_SELF_PIPE
  547. #ifdef WITH_OPENSSL
  548. if (soap->ssl)
  549. r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL | SOAP_TCP_SELECT_PIP, soap->send_timeout);
  550. else
  551. #endif
  552. #ifdef WITH_GNUTLS
  553. if (soap->session)
  554. r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL | SOAP_TCP_SELECT_PIP, soap->send_timeout);
  555. else
  556. #endif
  557. #ifdef WITH_SYSTEMSSL
  558. if (soap->ssl)
  559. r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL | SOAP_TCP_SELECT_PIP, soap->send_timeout);
  560. else
  561. #endif
  562. r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR | SOAP_TCP_SELECT_PIP, soap->send_timeout);
  563. if ((r & SOAP_TCP_SELECT_PIP)) /* abort if data is pending on pipe */
  564. {
  565. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection closed by self pipe\n"));
  566. return SOAP_EOF;
  567. }
  568. #else
  569. #ifdef WITH_OPENSSL
  570. if (soap->ssl)
  571. r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout);
  572. else
  573. #endif
  574. #ifdef WITH_GNUTLS
  575. if (soap->session)
  576. r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout);
  577. else
  578. #endif
  579. #ifdef WITH_SYSTEMSSL
  580. if (soap->ssl)
  581. r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout);
  582. else
  583. #endif
  584. r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout);
  585. #endif
  586. if (r > 0)
  587. break;
  588. if (!r)
  589. return SOAP_EOF;
  590. err = soap->errnum;
  591. if (!err)
  592. return soap->error;
  593. if (err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
  594. return SOAP_EOF;
  595. }
  596. }
  597. #ifndef WITH_LEAN
  598. if (soap->transfer_timeout)
  599. {
  600. time_t now = time(NULL);
  601. if ((soap->transfer_timeout > 0 && difftime(now, (time_t)soap->start) > (double)soap->transfer_timeout)
  602. || (soap->transfer_timeout < 0 && difftime(now, (time_t)soap->start) > -1000000.0 * (double)soap->transfer_timeout))
  603. return SOAP_EOF;
  604. }
  605. #endif
  606. #ifdef WITH_OPENSSL
  607. if (soap->ssl)
  608. nwritten = SSL_write(soap->ssl, s, (int)n);
  609. else if (soap->bio)
  610. nwritten = BIO_write(soap->bio, s, (int)n);
  611. else
  612. #endif
  613. #ifdef WITH_GNUTLS
  614. if (soap->session)
  615. nwritten = gnutls_record_send(soap->session, s, n);
  616. else
  617. #endif
  618. #ifdef WITH_SYSTEMSSL
  619. if (soap->ssl)
  620. {
  621. err = gsk_secure_socket_write(soap->ssl, (char*)s, n, &nwritten);
  622. if (err != GSK_OK)
  623. nwritten = 0;
  624. }
  625. else
  626. #endif
  627. #ifndef WITH_LEAN
  628. if ((soap->omode & SOAP_IO_UDP))
  629. {
  630. if (soap->peerlen)
  631. nwritten = sendto(sk, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, &soap->peer.addr, (SOAP_WINSOCKINT)soap->peerlen);
  632. else
  633. nwritten = send(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags);
  634. /* retry and back-off algorithm */
  635. /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */
  636. if (nwritten < 0)
  637. {
  638. int udp_repeat;
  639. int udp_delay;
  640. if ((soap->connect_flags & SO_BROADCAST))
  641. udp_repeat = 2; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */
  642. else
  643. udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */
  644. udp_delay = ((unsigned int)soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */
  645. do
  646. {
  647. tcp_select(soap, sk, SOAP_TCP_SELECT_ERR, -1000 * udp_delay);
  648. if (soap->peerlen)
  649. nwritten = sendto(sk, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, &soap->peer.addr, (SOAP_WINSOCKINT)soap->peerlen);
  650. else
  651. nwritten = send(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags);
  652. udp_delay <<= 1;
  653. if (udp_delay > 500) /* UDP_UPPER_DELAY */
  654. udp_delay = 500;
  655. } while (nwritten < 0 && --udp_repeat > 0);
  656. }
  657. if (nwritten < 0)
  658. {
  659. err = soap_socket_errno(sk);
  660. if (err && err != SOAP_EINTR)
  661. {
  662. soap->errnum = err;
  663. return SOAP_EOF;
  664. }
  665. nwritten = 0; /* and call write() again */
  666. }
  667. }
  668. else
  669. #endif
  670. #if !defined(AS400)
  671. nwritten = send(sk, s, (int)n, soap->socket_flags);
  672. #else
  673. nwritten = send(sk, (void*)s, n, soap->socket_flags);
  674. #endif
  675. if (nwritten <= 0)
  676. {
  677. int r = 0;
  678. err = soap_socket_errno(sk);
  679. #ifdef WITH_OPENSSL
  680. if (soap->ssl && (r = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
  681. {
  682. soap->errnum = err;
  683. return SOAP_EOF;
  684. }
  685. #endif
  686. #ifdef WITH_GNUTLS
  687. if (soap->session)
  688. {
  689. if (nwritten == GNUTLS_E_INTERRUPTED)
  690. err = SOAP_EINTR;
  691. else if (nwritten == GNUTLS_E_AGAIN)
  692. err = SOAP_EAGAIN;
  693. }
  694. #endif
  695. if (err == SOAP_EWOULDBLOCK || err == SOAP_EAGAIN)
  696. {
  697. #if defined(WITH_OPENSSL)
  698. if (soap->ssl && r == SSL_ERROR_WANT_READ)
  699. r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
  700. else
  701. #elif defined(WITH_GNUTLS)
  702. if (soap->session && !gnutls_record_get_direction(soap->session))
  703. r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
  704. else
  705. #endif
  706. r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
  707. if (!r && soap->send_timeout)
  708. return SOAP_EOF;
  709. if (r < 0)
  710. return SOAP_EOF;
  711. }
  712. else if (err && err != SOAP_EINTR)
  713. {
  714. soap->errnum = err;
  715. return SOAP_EOF;
  716. }
  717. nwritten = 0; /* and call write() again */
  718. }
  719. }
  720. else
  721. {
  722. #ifdef WITH_FASTCGI
  723. nwritten = fwrite((void*)s, 1, n, stdout);
  724. fflush(stdout);
  725. #else
  726. #ifdef UNDER_CE
  727. nwritten = fwrite(s, 1, n, soap->sendfd);
  728. #else
  729. #ifdef WMW_RPM_IO
  730. /* vxWorks compatible */
  731. if (soap->rpmreqid)
  732. nwritten = (httpBlockPut(soap->rpmreqid, (char*)s, n) == 0) ? n : -1;
  733. else
  734. #endif
  735. #ifdef WIN32
  736. nwritten = _write(soap->sendfd, s, (unsigned int)n);
  737. #else
  738. nwritten = write(soap->sendfd, s, (unsigned int)n);
  739. #endif
  740. #endif
  741. #endif
  742. if (nwritten <= 0)
  743. {
  744. #ifndef WITH_FASTCGI
  745. err = soap_errno;
  746. #else
  747. err = EOF;
  748. #endif
  749. if (err && err != SOAP_EINTR && err != SOAP_EWOULDBLOCK && err != SOAP_EAGAIN)
  750. {
  751. soap->errnum = err;
  752. return SOAP_EOF;
  753. }
  754. nwritten = 0; /* and call write() again */
  755. }
  756. }
  757. n -= nwritten;
  758. s += nwritten;
  759. }
  760. return SOAP_OK;
  761. }
  762. #endif
  763. /******************************************************************************/
  764. SOAP_FMAC1
  765. int
  766. SOAP_FMAC2
  767. soap_send_raw(struct soap *soap, const char *s, size_t n)
  768. {
  769. if (!n)
  770. return SOAP_OK;
  771. #ifndef WITH_LEANER
  772. if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE && (soap->mode & SOAP_IO_LENGTH) && (soap->error = soap->fpreparesend(soap, s, n)) != SOAP_OK)
  773. return soap->error;
  774. if (soap->ffiltersend && (soap->error = soap->ffiltersend(soap, &s, &n)) != SOAP_OK)
  775. return soap->error;
  776. #endif
  777. if ((soap->mode & SOAP_IO_LENGTH))
  778. {
  779. soap->count += n;
  780. }
  781. else if ((soap->mode & SOAP_IO))
  782. {
  783. size_t i = sizeof(soap->buf) - soap->bufidx;
  784. while (n >= i)
  785. {
  786. (void)soap_memcpy((void*)(soap->buf + soap->bufidx), i, (const void*)s, i);
  787. soap->bufidx = sizeof(soap->buf);
  788. if (soap_flush(soap))
  789. return soap->error;
  790. s += i;
  791. n -= i;
  792. i = sizeof(soap->buf);
  793. }
  794. (void)soap_memcpy((void*)(soap->buf + soap->bufidx), sizeof(soap->buf) - soap->bufidx, (const void*)s, n);
  795. soap->bufidx += n;
  796. }
  797. else
  798. {
  799. return soap_flush_raw(soap, s, n);
  800. }
  801. return SOAP_OK;
  802. }
  803. /******************************************************************************/
  804. SOAP_FMAC1
  805. int
  806. SOAP_FMAC2
  807. soap_flush(struct soap *soap)
  808. {
  809. size_t n = soap->bufidx;
  810. if (!n)
  811. return soap->error = soap->fsend(soap, SOAP_STR_EOS, 0); /* force a zero send for HTTP GET and DELETE */
  812. #ifndef WITH_LEANER
  813. if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
  814. {
  815. int r;
  816. if (soap->fpreparesend && (r = soap->fpreparesend(soap, soap->buf, n)) != SOAP_OK)
  817. return soap->error = r;
  818. }
  819. #endif
  820. soap->bufidx = 0;
  821. #ifdef WITH_ZLIB
  822. if ((soap->mode & SOAP_ENC_ZLIB) && soap->d_stream)
  823. {
  824. soap->d_stream->next_in = (Byte*)soap->buf;
  825. soap->d_stream->avail_in = (unsigned int)n;
  826. #ifdef WITH_GZIP
  827. soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n);
  828. #endif
  829. do
  830. {
  831. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream->avail_in));
  832. if (deflate(soap->d_stream, Z_NO_FLUSH) != Z_OK)
  833. {
  834. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
  835. return soap->error = SOAP_ZLIB_ERROR;
  836. }
  837. if (!soap->d_stream->avail_out)
  838. {
  839. if (soap_flush_raw(soap, soap->z_buf, sizeof(soap->buf)))
  840. return soap->error;
  841. soap->d_stream->next_out = (Byte*)soap->z_buf;
  842. soap->d_stream->avail_out = sizeof(soap->buf);
  843. }
  844. } while (soap->d_stream->avail_in);
  845. return SOAP_OK;
  846. }
  847. #endif
  848. return soap_flush_raw(soap, soap->buf, n);
  849. }
  850. /******************************************************************************/
  851. SOAP_FMAC1
  852. int
  853. SOAP_FMAC2
  854. soap_flush_raw(struct soap *soap, const char *s, size_t n)
  855. {
  856. if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
  857. {
  858. void *t;
  859. t = soap_push_block(soap, NULL, n);
  860. if (!t)
  861. return soap->error = SOAP_EOM;
  862. (void)soap_memcpy(t, n, (const void*)s, n);
  863. return SOAP_OK;
  864. }
  865. #ifndef WITH_LEANER
  866. if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
  867. {
  868. char t[24];
  869. (SOAP_SNPRINTF(t, sizeof(t), 20), &"\r\n%lX\r\n"[soap->chunksize ? 0 : 2], (unsigned long)n);
  870. DBGMSG(SENT, t, strlen(t));
  871. soap->error = soap->fsend(soap, t, strlen(t));
  872. if (soap->error)
  873. return soap->error;
  874. soap->chunksize += n;
  875. }
  876. DBGMSG(SENT, s, n);
  877. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send %u bytes to socket=%d/fd=%d\n", (unsigned int)n, (int)soap->socket, soap->sendfd));
  878. #endif
  879. return soap->error = soap->fsend(soap, s, n);
  880. }
  881. /******************************************************************************/
  882. SOAP_FMAC1
  883. int
  884. SOAP_FMAC2
  885. soap_send(struct soap *soap, const char *s)
  886. {
  887. if (s)
  888. return soap_send_raw(soap, s, strlen(s));
  889. return SOAP_OK;
  890. }
  891. /******************************************************************************/
  892. #ifndef WITH_LEANER
  893. SOAP_FMAC1
  894. int
  895. SOAP_FMAC2
  896. soap_send2(struct soap *soap, const char *s1, const char *s2)
  897. {
  898. if (soap_send(soap, s1))
  899. return soap->error;
  900. return soap_send(soap, s2);
  901. }
  902. #endif
  903. /******************************************************************************/
  904. #ifndef WITH_LEANER
  905. SOAP_FMAC1
  906. int
  907. SOAP_FMAC2
  908. soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3)
  909. {
  910. if (soap_send(soap, s1)
  911. || soap_send(soap, s2))
  912. return soap->error;
  913. return soap_send(soap, s3);
  914. }
  915. #endif
  916. /******************************************************************************/
  917. #ifndef WITH_LEANER
  918. SOAP_FMAC1
  919. int
  920. SOAP_FMAC2
  921. soap_query_send_key(struct soap *soap, const char *s)
  922. {
  923. if (!s)
  924. return SOAP_OK;
  925. if (!soap->body && soap_send_raw(soap, "&", 1))
  926. return soap->error;
  927. soap->body = 0;
  928. (void)soap_encode_url(s, soap->msgbuf, (int)sizeof(soap->msgbuf)); /* msgbuf length is max SOAP_TMPLEN or just 1024 bytes */
  929. return soap_send(soap, soap->msgbuf);
  930. }
  931. #endif
  932. /******************************************************************************/
  933. #ifndef WITH_LEANER
  934. SOAP_FMAC1
  935. int
  936. SOAP_FMAC2
  937. soap_query_send_val(struct soap *soap, const char *s)
  938. {
  939. if (!s)
  940. return SOAP_OK;
  941. if (soap_send_raw(soap, "=", 1))
  942. return soap->error;
  943. (void)soap_encode_url(s, soap->msgbuf, (int)sizeof(soap->msgbuf)); /* msgbuf length is max SOAP_TMPLEN or just 1024 bytes */
  944. return soap_send(soap, soap->msgbuf);
  945. }
  946. #endif
  947. /******************************************************************************/
  948. #ifndef WITH_LEANER
  949. SOAP_FMAC1
  950. char *
  951. SOAP_FMAC2
  952. soap_query(struct soap *soap)
  953. {
  954. return strchr(soap->path, '?');
  955. }
  956. #endif
  957. /******************************************************************************/
  958. #ifndef WITH_LEANER
  959. SOAP_FMAC1
  960. char *
  961. SOAP_FMAC2
  962. soap_query_key(struct soap *soap, char **s)
  963. {
  964. char *t = *s;
  965. (void)soap;
  966. if (t && *t)
  967. {
  968. *s = (char*)soap_query_decode(t, strlen(t), t + 1);
  969. return t;
  970. }
  971. return *s = NULL;
  972. }
  973. #endif
  974. /******************************************************************************/
  975. #ifndef WITH_LEANER
  976. SOAP_FMAC1
  977. char *
  978. SOAP_FMAC2
  979. soap_query_val(struct soap *soap, char **s)
  980. {
  981. char *t = *s;
  982. (void)soap;
  983. if (t && *t == '=')
  984. {
  985. *s = (char*)soap_query_decode(t, strlen(t), t + 1);
  986. return t;
  987. }
  988. return NULL;
  989. }
  990. #endif
  991. /******************************************************************************/
  992. #ifndef WITH_LEANER
  993. SOAP_FMAC1
  994. const char *
  995. SOAP_FMAC2
  996. soap_query_decode(char *buf, size_t len, const char *val)
  997. {
  998. const char *s;
  999. char *t;
  1000. for (s = val; *s; s++)
  1001. if (*s != ' ' && *s != '=')
  1002. break;
  1003. if (*s == '"')
  1004. {
  1005. t = buf;
  1006. s++;
  1007. while (*s && *s != '"' && --len)
  1008. *t++ = *s++;
  1009. *t = '\0';
  1010. do s++;
  1011. while (*s && *s != '&' && *s != '=');
  1012. }
  1013. else
  1014. {
  1015. t = buf;
  1016. while (*s && *s != '&' && *s != '=' && --len)
  1017. {
  1018. switch (*s)
  1019. {
  1020. case '+':
  1021. *t++ = ' ';
  1022. s++;
  1023. break;
  1024. case '\t':
  1025. case '\n':
  1026. case '\r':
  1027. case ' ':
  1028. s++;
  1029. break;
  1030. case '%':
  1031. *t++ = ((s[1] >= 'A' ? (s[1]&0x7) + 9 : s[1] - '0') << 4) + (s[2] >= 'A' ? (s[2]&0x7) + 9 : s[2] - '0');
  1032. s += 3;
  1033. break;
  1034. default:
  1035. *t++ = *s++;
  1036. }
  1037. }
  1038. *t = '\0';
  1039. }
  1040. return s;
  1041. }
  1042. #endif
  1043. /******************************************************************************/
  1044. #ifndef WITH_NOIO
  1045. static size_t
  1046. frecv(struct soap *soap, char *s, size_t n)
  1047. {
  1048. int r;
  1049. int retries = 100; /* max 100 retries with non-blocking sockets */
  1050. SOAP_SOCKET sk;
  1051. soap->errnum = 0;
  1052. #if defined(__cplusplus) && !defined(WITH_COMPAT)
  1053. if (soap->is) /* recv from C++ stream */
  1054. {
  1055. if (soap->is->good())
  1056. return (size_t)soap->is->read(s, (std::streamsize)n).gcount(); /* downcast to std::streamsize is OK: gcount() returns how much we got in s[] */
  1057. return 0;
  1058. }
  1059. #else
  1060. if (soap->is) /* recv from C buffer until NUL */
  1061. {
  1062. size_t l = strlen(soap->is);
  1063. if (l > n)
  1064. l = n;
  1065. (void)soap_memcpy((void*)s, n, soap->is, l);
  1066. soap->is += l;
  1067. return l;
  1068. }
  1069. #endif
  1070. sk = soap->recvsk;
  1071. if (!soap_valid_socket(sk))
  1072. sk = soap->socket;
  1073. if (soap_valid_socket(sk))
  1074. {
  1075. for (;;)
  1076. {
  1077. #if defined(WITH_OPENSSL) || defined(WITH_SYSTEMSSL)
  1078. int err = 0;
  1079. #endif
  1080. #ifdef WITH_OPENSSL
  1081. if (soap->recv_timeout && !soap->ssl) /* OpenSSL: sockets are nonblocking so go ahead to read */
  1082. #else
  1083. if (soap->recv_timeout)
  1084. #endif
  1085. {
  1086. for (;;)
  1087. {
  1088. #ifdef WITH_SELF_PIPE
  1089. r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR | SOAP_TCP_SELECT_PIP, soap->recv_timeout);
  1090. if ((r & SOAP_TCP_SELECT_PIP)) /* abort if data is pending on pipe */
  1091. {
  1092. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection closed by self pipe\n"));
  1093. return 0;
  1094. }
  1095. #else
  1096. r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout);
  1097. #endif
  1098. if (r > 0)
  1099. break;
  1100. if (!r)
  1101. return 0;
  1102. r = soap->errnum;
  1103. if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
  1104. return 0;
  1105. }
  1106. }
  1107. #ifndef WITH_LEAN
  1108. if (soap->transfer_timeout)
  1109. {
  1110. time_t now = time(NULL);
  1111. if ((soap->transfer_timeout > 0 && difftime(now, (time_t)soap->start) > (double)soap->transfer_timeout)
  1112. || (soap->transfer_timeout < 0 && difftime(now, (time_t)soap->start) > -1000000.0 * (double)soap->transfer_timeout))
  1113. return 0;
  1114. }
  1115. #endif
  1116. #ifdef WITH_OPENSSL
  1117. if (soap->ssl)
  1118. {
  1119. r = SSL_read(soap->ssl, s, (int)n);
  1120. if (r > 0)
  1121. return (size_t)r;
  1122. err = SSL_get_error(soap->ssl, r);
  1123. if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
  1124. return 0;
  1125. }
  1126. else if (soap->bio)
  1127. {
  1128. r = BIO_read(soap->bio, s, (int)n);
  1129. if (r > 0)
  1130. return (size_t)r;
  1131. return 0;
  1132. }
  1133. else
  1134. #endif
  1135. #ifdef WITH_GNUTLS
  1136. if (soap->session)
  1137. {
  1138. r = (int)gnutls_record_recv(soap->session, s, n);
  1139. if (r >= 0)
  1140. return (size_t)r;
  1141. }
  1142. else
  1143. #endif
  1144. #ifdef WITH_SYSTEMSSL
  1145. if (soap->ssl)
  1146. {
  1147. err = gsk_secure_socket_read(soap->ssl, s, n, &r);
  1148. if (err == GSK_OK && r > 0)
  1149. return (size_t)r;
  1150. if (err != GSK_OK && err != GSK_WOULD_BLOCK && err != GSK_WOULD_BLOCK_WRITE)
  1151. return 0;
  1152. }
  1153. else
  1154. #endif
  1155. {
  1156. #ifndef WITH_LEAN
  1157. if ((soap->omode & SOAP_IO_UDP))
  1158. {
  1159. SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer);
  1160. memset((void*)&soap->peer, 0, sizeof(soap->peer));
  1161. r = recvfrom(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags, &soap->peer.addr, &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) */
  1162. soap->peerlen = (size_t)k;
  1163. #ifdef WITH_IPV6
  1164. soap->ip = 0;
  1165. soap->ip6[0] = 0;
  1166. soap->ip6[1] = 0;
  1167. soap->ip6[2] = 0;
  1168. soap->ip6[3] = 0;
  1169. #else
  1170. soap->ip = ntohl(soap->peer.in.sin_addr.s_addr);
  1171. soap->ip6[0] = 0;
  1172. soap->ip6[1] = 0;
  1173. soap->ip6[2] = 0xFFFF;
  1174. soap->ip6[3] = soap->ip;
  1175. #endif
  1176. }
  1177. else
  1178. #endif
  1179. r = recv(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags); /* SOAP_WINSOCKINT cast is safe due to limited range of n in the engine (64K) */
  1180. if (r >= 0)
  1181. return (size_t)r;
  1182. r = soap_socket_errno(sk);
  1183. if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
  1184. {
  1185. soap->errnum = r;
  1186. return 0;
  1187. }
  1188. }
  1189. #if defined(WITH_OPENSSL)
  1190. if (soap->ssl && err == SSL_ERROR_WANT_WRITE)
  1191. r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
  1192. else
  1193. #elif defined(WITH_GNUTLS)
  1194. if (soap->session && gnutls_record_get_direction(soap->session))
  1195. r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
  1196. else
  1197. #elif defined(WITH_SYSTEMSSL)
  1198. if (soap->ssl && err == GSK_WOULD_BLOCK_WRITE)
  1199. r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
  1200. else
  1201. #endif
  1202. r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
  1203. if (!r && soap->recv_timeout)
  1204. return 0;
  1205. if (r < 0)
  1206. {
  1207. r = soap->errnum;
  1208. if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
  1209. return 0;
  1210. }
  1211. if (retries-- <= 0)
  1212. return 0;
  1213. }
  1214. }
  1215. #ifdef WITH_FASTCGI
  1216. return fread(s, 1, n, stdin);
  1217. #else
  1218. #ifdef UNDER_CE
  1219. return fread(s, 1, n, soap->recvfd);
  1220. #else
  1221. #ifdef WMW_RPM_IO
  1222. if (soap->rpmreqid)
  1223. r = httpBlockRead(soap->rpmreqid, s, n);
  1224. else
  1225. #endif
  1226. #ifdef WIN32
  1227. r = _read(soap->recvfd, s, (unsigned int)n);
  1228. #else
  1229. r = read(soap->recvfd, s, n);
  1230. #endif
  1231. if (r >= 0)
  1232. return (size_t)r;
  1233. soap->errnum = soap_errno;
  1234. return 0;
  1235. #endif
  1236. #endif
  1237. }
  1238. #endif
  1239. /******************************************************************************/
  1240. #ifndef WITH_NOHTTP
  1241. static soap_wchar
  1242. soap_getchunkchar(struct soap *soap)
  1243. {
  1244. if (soap->bufidx < soap->buflen)
  1245. return soap->buf[soap->bufidx++];
  1246. soap->bufidx = 0;
  1247. soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, sizeof(soap->buf));
  1248. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)soap->buflen, (int)soap->socket, soap->recvfd));
  1249. DBGMSG(RECV, soap->buf, soap->buflen);
  1250. if (soap->buflen)
  1251. return soap->buf[soap->bufidx++];
  1252. return EOF;
  1253. }
  1254. #endif
  1255. /******************************************************************************/
  1256. static int
  1257. soap_isxdigit(int c)
  1258. {
  1259. return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
  1260. }
  1261. /******************************************************************************/
  1262. SOAP_FMAC1
  1263. int
  1264. SOAP_FMAC2
  1265. soap_recv_raw(struct soap *soap)
  1266. {
  1267. size_t ret;
  1268. #if !defined(WITH_LEANER) || defined(WITH_ZLIB)
  1269. int r;
  1270. #endif
  1271. #ifdef WITH_ZLIB
  1272. if ((soap->mode & SOAP_ENC_ZLIB) && soap->d_stream)
  1273. {
  1274. if (soap->d_stream->next_out == Z_NULL)
  1275. {
  1276. soap->bufidx = soap->buflen = 0;
  1277. return EOF;
  1278. }
  1279. if (soap->d_stream->avail_in || !soap->d_stream->avail_out)
  1280. {
  1281. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n"));
  1282. soap->d_stream->next_out = (Byte*)soap->buf;
  1283. soap->d_stream->avail_out = sizeof(soap->buf);
  1284. r = inflate(soap->d_stream, Z_NO_FLUSH);
  1285. if (r == Z_NEED_DICT && soap->z_dict)
  1286. r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len);
  1287. if (r == Z_OK || r == Z_STREAM_END)
  1288. {
  1289. soap->bufidx = 0;
  1290. ret = soap->buflen = sizeof(soap->buf) - soap->d_stream->avail_out;
  1291. if (soap->zlib_in == SOAP_ZLIB_GZIP)
  1292. soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)ret);
  1293. if (r == Z_STREAM_END)
  1294. {
  1295. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
  1296. soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
  1297. soap->d_stream->next_out = Z_NULL;
  1298. }
  1299. if (ret)
  1300. {
  1301. if (soap->count + ret < soap->count)
  1302. return soap->error = SOAP_EOF;
  1303. soap->count += ret;
  1304. if (soap->recv_maxlength && soap->count > soap->recv_maxlength)
  1305. return soap->error = SOAP_EOF;
  1306. if (soap->count > SOAP_MAXINFLATESIZE && soap->z_ratio_in < SOAP_MINDEFLATERATIO)
  1307. {
  1308. soap->d_stream->msg = (char*)"caught SOAP_MINDEFLATERATIO explosive decompression guard (remedy: increase SOAP_MAXINFLATESIZE and/or decrease SOAP_MINDEFLATERATIO)";
  1309. return soap->error = SOAP_ZLIB_ERROR;
  1310. }
  1311. DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
  1312. DBGMSG(RECV, soap->buf, ret);
  1313. DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n----\n"));
  1314. #ifndef WITH_LEANER
  1315. if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)) != SOAP_OK)
  1316. return soap->error = r;
  1317. #endif
  1318. return SOAP_OK;
  1319. }
  1320. }
  1321. else if (r != Z_BUF_ERROR)
  1322. {
  1323. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
  1324. soap->d_stream->next_out = Z_NULL;
  1325. return soap->error = SOAP_ZLIB_ERROR;
  1326. }
  1327. }
  1328. zlib_again:
  1329. if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize)
  1330. {
  1331. (void)soap_memcpy((void*)soap->buf, sizeof(soap->buf), (const void*)soap->z_buf, sizeof(soap->buf));
  1332. soap->buflen = soap->z_buflen;
  1333. }
  1334. DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- compressed ----\n"));
  1335. }
  1336. #endif
  1337. #ifndef WITH_NOHTTP
  1338. if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */
  1339. {
  1340. for (;;)
  1341. {
  1342. soap_wchar c;
  1343. char *t, tmp[17];
  1344. if (soap->chunksize)
  1345. {
  1346. soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > sizeof(soap->buf) ? sizeof(soap->buf) : soap->chunksize);
  1347. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret));
  1348. DBGMSG(RECV, soap->buf, ret);
  1349. soap->bufidx = 0;
  1350. if (!ret)
  1351. {
  1352. soap->ahead = EOF;
  1353. return EOF;
  1354. }
  1355. soap->chunksize -= ret;
  1356. break;
  1357. }
  1358. if (!soap->chunkbuflen)
  1359. {
  1360. soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, sizeof(soap->buf));
  1361. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket=%d\n", (unsigned int)ret, (int)soap->socket));
  1362. DBGMSG(RECV, soap->buf, ret);
  1363. soap->bufidx = 0;
  1364. if (!ret)
  1365. {
  1366. soap->ahead = EOF;
  1367. return EOF;
  1368. }
  1369. }
  1370. else
  1371. {
  1372. soap->bufidx = soap->buflen;
  1373. }
  1374. soap->buflen = soap->chunkbuflen;
  1375. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen));
  1376. while (!soap_isxdigit((int)(c = soap_getchunkchar(soap))))
  1377. {
  1378. if ((int)c == EOF)
  1379. {
  1380. soap->ahead = EOF;
  1381. return EOF;
  1382. }
  1383. }
  1384. t = tmp;
  1385. do
  1386. {
  1387. *t++ = (char)c;
  1388. } while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && (size_t)(t - tmp) < sizeof(tmp)-1);
  1389. while ((int)c != EOF && c != '\n')
  1390. c = soap_getchunkchar(soap);
  1391. if ((int)c == EOF)
  1392. {
  1393. soap->ahead = EOF;
  1394. return EOF;
  1395. }
  1396. *t = '\0';
  1397. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunk size = %s (hex)\n", tmp));
  1398. soap->chunksize = (size_t)soap_strtoul(tmp, &t, 16);
  1399. if (!soap->chunksize)
  1400. {
  1401. soap->bufidx = soap->buflen = soap->chunkbuflen = 0;
  1402. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n"));
  1403. ret = 0;
  1404. soap->ahead = EOF;
  1405. break;
  1406. }
  1407. soap->buflen = soap->bufidx + soap->chunksize;
  1408. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp));
  1409. if (soap->buflen > soap->chunkbuflen)
  1410. {
  1411. soap->buflen = soap->chunkbuflen;
  1412. soap->chunksize -= soap->buflen - soap->bufidx;
  1413. soap->chunkbuflen = 0;
  1414. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx)));
  1415. }
  1416. else if (soap->chunkbuflen)
  1417. {
  1418. soap->chunksize = 0;
  1419. }
  1420. ret = soap->buflen - soap->bufidx;
  1421. if (ret)
  1422. break;
  1423. }
  1424. }
  1425. else
  1426. #endif
  1427. {
  1428. soap->bufidx = 0;
  1429. soap->buflen = ret = soap->frecv(soap, soap->buf, sizeof(soap->buf));
  1430. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)ret, (int)soap->socket, soap->recvfd));
  1431. DBGMSG(RECV, soap->buf, ret);
  1432. }
  1433. #ifdef WITH_ZLIB
  1434. if ((soap->mode & SOAP_ENC_ZLIB))
  1435. {
  1436. (void)soap_memcpy((void*)soap->z_buf, sizeof(soap->buf), (const void*)soap->buf, sizeof(soap->buf));
  1437. soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
  1438. soap->d_stream->avail_in = (unsigned int)ret;
  1439. soap->d_stream->next_out = (Byte*)soap->buf;
  1440. soap->d_stream->avail_out = sizeof(soap->buf);
  1441. r = inflate(soap->d_stream, Z_NO_FLUSH);
  1442. if (r == Z_NEED_DICT && soap->z_dict)
  1443. r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len);
  1444. if (r == Z_OK || r == Z_STREAM_END)
  1445. {
  1446. soap->bufidx = 0;
  1447. soap->z_buflen = soap->buflen;
  1448. soap->buflen = sizeof(soap->buf) - soap->d_stream->avail_out;
  1449. if (soap->zlib_in == SOAP_ZLIB_GZIP)
  1450. soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen);
  1451. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)soap->buflen));
  1452. if (ret && !soap->buflen && r != Z_STREAM_END)
  1453. goto zlib_again;
  1454. ret = soap->buflen;
  1455. if (r == Z_STREAM_END)
  1456. {
  1457. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
  1458. soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
  1459. soap->d_stream->next_out = Z_NULL;
  1460. }
  1461. if (soap->count + ret > SOAP_MAXINFLATESIZE && soap->z_ratio_in < SOAP_MINDEFLATERATIO)
  1462. {
  1463. soap->d_stream->msg = (char*)"caught SOAP_MINDEFLATERATIO explosive decompression guard (remedy: increase SOAP_MAXINFLATESIZE and/or decrease SOAP_MINDEFLATERATIO)";
  1464. return soap->error = SOAP_ZLIB_ERROR;
  1465. }
  1466. DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
  1467. DBGMSG(RECV, soap->buf, ret);
  1468. #ifndef WITH_LEANER
  1469. if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)) != SOAP_OK)
  1470. return soap->error = r;
  1471. #endif
  1472. }
  1473. else
  1474. {
  1475. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
  1476. soap->d_stream->next_out = Z_NULL;
  1477. return soap->error = SOAP_ZLIB_ERROR;
  1478. }
  1479. }
  1480. #endif
  1481. #ifndef WITH_LEANER
  1482. if (soap->fpreparerecv
  1483. #ifdef WITH_ZLIB
  1484. && soap->zlib_in == SOAP_ZLIB_NONE
  1485. #endif
  1486. && (r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, ret)))
  1487. return soap->error = r;
  1488. #endif
  1489. if (ret)
  1490. {
  1491. if (soap->count + ret < soap->count)
  1492. return EOF;
  1493. soap->count += ret;
  1494. if (soap->recv_maxlength && soap->count > soap->recv_maxlength)
  1495. return EOF;
  1496. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read count=" SOAP_ULONG_FORMAT " (+%lu)\n", soap->count, (unsigned long)ret));
  1497. return SOAP_OK;
  1498. }
  1499. return EOF;
  1500. }
  1501. /******************************************************************************/
  1502. SOAP_FMAC1
  1503. int
  1504. SOAP_FMAC2
  1505. soap_recv(struct soap *soap)
  1506. {
  1507. #ifndef WITH_LEANER
  1508. if ((soap->mode & SOAP_ENC_DIME))
  1509. {
  1510. if (soap->dime.buflen)
  1511. {
  1512. char *s;
  1513. int i;
  1514. unsigned char tmp[12];
  1515. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked SOAP in DIME is in buffer\n"));
  1516. soap->buflen = soap->dime.buflen;
  1517. soap->dime.buflen = 0;
  1518. soap->dime.chunksize = 0;
  1519. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3));
  1520. for (i = -(long)soap->dime.size&3; i > 0; i--)
  1521. {
  1522. soap->bufidx++;
  1523. if (soap->bufidx >= soap->buflen)
  1524. if (soap_recv_raw(soap))
  1525. return EOF;
  1526. }
  1527. if (!(soap->dime.flags & SOAP_DIME_CF))
  1528. return SOAP_OK;
  1529. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next SOAP in DIME chunk\n"));
  1530. s = (char*)tmp;
  1531. for (i = 12; i > 0; i--)
  1532. {
  1533. *s++ = soap->buf[soap->bufidx++];
  1534. if (soap->bufidx >= soap->buflen)
  1535. if (soap_recv_raw(soap))
  1536. return EOF;
  1537. }
  1538. if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION)
  1539. return soap->error = SOAP_DIME_MISMATCH;
  1540. soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0);
  1541. soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
  1542. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get SOAP in DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size));
  1543. soap->dime.chunksize = soap->dime.size;
  1544. if (soap->buflen - soap->bufidx >= soap->dime.size)
  1545. {
  1546. if ((soap->dime.flags & SOAP_DIME_ME))
  1547. {
  1548. soap->mode &= ~SOAP_ENC_DIME;
  1549. }
  1550. else
  1551. {
  1552. soap->dime.buflen = soap->buflen;
  1553. soap->buflen = soap->bufidx + soap->dime.chunksize;
  1554. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME (%u bytes buffered)\n", (unsigned int)soap->buflen));
  1555. }
  1556. }
  1557. else
  1558. {
  1559. soap->dime.chunksize -= soap->buflen - soap->bufidx;
  1560. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME (%u bytes in chunk left)\n", (unsigned int)soap->dime.chunksize));
  1561. }
  1562. return SOAP_OK;
  1563. }
  1564. if (soap->dime.chunksize)
  1565. {
  1566. if (soap_recv_raw(soap))
  1567. return EOF;
  1568. if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
  1569. {
  1570. if ((soap->dime.flags & SOAP_DIME_ME))
  1571. {
  1572. soap->dime.chunksize = 0;
  1573. soap->mode &= ~SOAP_ENC_DIME;
  1574. }
  1575. else
  1576. {
  1577. soap->dime.buflen = soap->buflen;
  1578. soap->buflen = soap->bufidx + soap->dime.chunksize;
  1579. soap->dime.chunksize = 0;
  1580. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME (%u bytes buffered)\n", (unsigned int)soap->buflen));
  1581. }
  1582. }
  1583. else
  1584. {
  1585. soap->dime.chunksize -= soap->buflen - soap->bufidx;
  1586. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME (%u bytes in chunk left)\n", (unsigned int)soap->dime.chunksize));
  1587. }
  1588. return SOAP_OK;
  1589. }
  1590. }
  1591. if (soap->ffilterrecv)
  1592. {
  1593. int err;
  1594. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Filter recverror = %d bufidx = %lu buflen = %lu\n", soap->recverror, (unsigned long)soap->bufidx, (unsigned long)soap->buflen));
  1595. if (soap->recverror)
  1596. {
  1597. soap->bufidx = soap->buflen = 0;
  1598. }
  1599. else
  1600. {
  1601. soap->bufidx = soap->buflen = 0;
  1602. err = soap->ffilterrecv(soap, soap->buf, &soap->buflen, sizeof(soap->buf));
  1603. if (err)
  1604. {
  1605. if (err == SOAP_EOF)
  1606. return SOAP_EOF;
  1607. return soap->error = err;
  1608. }
  1609. if (soap->buflen)
  1610. {
  1611. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Filtered output continued %lu bytes\n", (unsigned long)soap->buflen));
  1612. return SOAP_OK;
  1613. }
  1614. soap->recverror = soap_recv_raw(soap);
  1615. soap->buflen -= soap->bufidx; /* chunked may set bufidx > 0 to skip hex chunk length */
  1616. }
  1617. while (soap->ffilterrecv)
  1618. {
  1619. err = soap->ffilterrecv(soap, soap->buf + soap->bufidx, &soap->buflen, sizeof(soap->buf) - soap->bufidx);
  1620. if (err)
  1621. {
  1622. if (err == SOAP_EOF)
  1623. return SOAP_EOF;
  1624. return soap->error = err;
  1625. }
  1626. if (soap->buflen)
  1627. {
  1628. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Filtered output %lu bytes\n", (unsigned long)soap->buflen));
  1629. soap->buflen += soap->bufidx;
  1630. return SOAP_OK;
  1631. }
  1632. if (soap->recverror)
  1633. {
  1634. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Returning postponed error %d\n", soap->recverror));
  1635. return soap->recverror;
  1636. }
  1637. soap->recverror = soap_recv_raw(soap);
  1638. soap->buflen -= soap->bufidx; /* chunked may set bufidx > 0 to skip hex chunk length */
  1639. }
  1640. }
  1641. return soap->recverror = soap_recv_raw(soap);
  1642. #else
  1643. return soap_recv_raw(soap);
  1644. #endif
  1645. }
  1646. /******************************************************************************/
  1647. SOAP_FMAC1
  1648. soap_wchar
  1649. SOAP_FMAC2
  1650. soap_getchar(struct soap *soap)
  1651. {
  1652. soap_wchar c;
  1653. c = soap->ahead;
  1654. if (c)
  1655. {
  1656. if ((int)c != EOF)
  1657. soap->ahead = 0;
  1658. return c;
  1659. }
  1660. return soap_get1(soap);
  1661. }
  1662. /******************************************************************************/
  1663. SOAP_FMAC1
  1664. const struct soap_code_map*
  1665. SOAP_FMAC2
  1666. soap_code(const struct soap_code_map *code_map, const char *str)
  1667. {
  1668. if (code_map && str)
  1669. {
  1670. while (code_map->string)
  1671. {
  1672. if (!strcmp(str, code_map->string)) /* case sensitive */
  1673. return code_map;
  1674. code_map++;
  1675. }
  1676. }
  1677. return NULL;
  1678. }
  1679. /******************************************************************************/
  1680. SOAP_FMAC1
  1681. LONG64
  1682. SOAP_FMAC2
  1683. soap_code_int(const struct soap_code_map *code_map, const char *str, LONG64 other)
  1684. {
  1685. if (code_map)
  1686. {
  1687. while (code_map->string)
  1688. {
  1689. if (!soap_tag_cmp(str, code_map->string)) /* case insensitive */
  1690. return code_map->code;
  1691. code_map++;
  1692. }
  1693. }
  1694. return other;
  1695. }
  1696. /******************************************************************************/
  1697. SOAP_FMAC1
  1698. const char*
  1699. SOAP_FMAC2
  1700. soap_code_str(const struct soap_code_map *code_map, long code)
  1701. {
  1702. if (!code_map)
  1703. return NULL;
  1704. while (code_map->code != code && code_map->string)
  1705. code_map++;
  1706. return code_map->string;
  1707. }
  1708. /******************************************************************************/
  1709. SOAP_FMAC1
  1710. LONG64
  1711. SOAP_FMAC2
  1712. soap_code_bits(const struct soap_code_map *code_map, const char *str)
  1713. {
  1714. LONG64 bits = 0;
  1715. if (code_map)
  1716. {
  1717. while (str && *str)
  1718. {
  1719. const struct soap_code_map *p;
  1720. for (p = code_map; p->string; p++)
  1721. {
  1722. size_t n = strlen(p->string);
  1723. if (!strncmp(p->string, str, n) && soap_coblank((soap_wchar)str[n]))
  1724. {
  1725. bits |= p->code;
  1726. str += n;
  1727. while (*str > 0 && *str <= 32)
  1728. str++;
  1729. break;
  1730. }
  1731. }
  1732. if (!p->string)
  1733. return 0;
  1734. }
  1735. }
  1736. return bits;
  1737. }
  1738. /******************************************************************************/
  1739. SOAP_FMAC1
  1740. const char*
  1741. SOAP_FMAC2
  1742. soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long code)
  1743. {
  1744. char *t = soap->tmpbuf;
  1745. if (code_map)
  1746. {
  1747. while (code_map->string)
  1748. {
  1749. if ((code_map->code & code))
  1750. {
  1751. const char *s = code_map->string;
  1752. if (t != soap->tmpbuf)
  1753. *t++ = ' ';
  1754. while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
  1755. *t++ = *s++;
  1756. if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
  1757. break;
  1758. }
  1759. code_map++;
  1760. }
  1761. }
  1762. *t = '\0';
  1763. return soap->tmpbuf;
  1764. }
  1765. /******************************************************************************/
  1766. SOAP_FMAC1
  1767. int
  1768. SOAP_FMAC2
  1769. soap_binary_search_string(const char **a, int n, const char *s)
  1770. {
  1771. int min = 0, max = n-1;
  1772. while (min <= max)
  1773. {
  1774. int mid = (min+max)/2;
  1775. int r = strcmp(s, a[mid]);
  1776. if (r < 0)
  1777. max = mid - 1;
  1778. else if (r > 0)
  1779. min = mid + 1;
  1780. else
  1781. return mid;
  1782. }
  1783. return -1;
  1784. }
  1785. /******************************************************************************/
  1786. static soap_wchar
  1787. soap_char(struct soap *soap)
  1788. {
  1789. char tmp[8];
  1790. int i;
  1791. soap_wchar c;
  1792. char *s = tmp;
  1793. for (i = 0; i < (int)sizeof(tmp)-1; i++)
  1794. {
  1795. c = soap_get1(soap);
  1796. if (c == ';' || (int)c == EOF)
  1797. break;
  1798. *s++ = (char)c;
  1799. }
  1800. *s = '\0';
  1801. if (*tmp == '#')
  1802. {
  1803. if (tmp[1] == 'x' || tmp[1] == 'X')
  1804. return (soap_wchar)soap_strtol(tmp + 2, NULL, 16);
  1805. return (soap_wchar)soap_strtol(tmp + 1, NULL, 10);
  1806. }
  1807. if (!strcmp(tmp, "lt"))
  1808. return '<';
  1809. if (!strcmp(tmp, "gt"))
  1810. return '>';
  1811. if (!strcmp(tmp, "amp"))
  1812. return '&';
  1813. if (!strcmp(tmp, "quot"))
  1814. return '"';
  1815. if (!strcmp(tmp, "apos"))
  1816. return '\'';
  1817. #ifndef WITH_LEAN
  1818. return (soap_wchar)soap_code_int(html_entity_codes, tmp, (LONG64)SOAP_UNKNOWN_CHAR);
  1819. #else
  1820. return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */
  1821. #endif
  1822. }
  1823. /******************************************************************************/
  1824. #ifdef WITH_LEAN
  1825. soap_wchar
  1826. soap_get0(struct soap *soap)
  1827. {
  1828. if (soap->bufidx >= soap->buflen && soap_recv(soap))
  1829. return EOF;
  1830. return (unsigned char)soap->buf[soap->bufidx];
  1831. }
  1832. #endif
  1833. /******************************************************************************/
  1834. #ifdef WITH_LEAN
  1835. soap_wchar
  1836. soap_get1(struct soap *soap)
  1837. {
  1838. if (soap->bufidx >= soap->buflen && soap_recv(soap))
  1839. return EOF;
  1840. return (unsigned char)soap->buf[soap->bufidx++];
  1841. }
  1842. #endif
  1843. /******************************************************************************/
  1844. SOAP_FMAC1
  1845. soap_wchar
  1846. SOAP_FMAC2
  1847. soap_get(struct soap *soap)
  1848. {
  1849. soap_wchar c;
  1850. c = soap->ahead;
  1851. if (c)
  1852. {
  1853. if ((int)c != EOF)
  1854. soap->ahead = 0;
  1855. }
  1856. else
  1857. {
  1858. c = soap_get1(soap);
  1859. }
  1860. while ((int)c != EOF)
  1861. {
  1862. if (soap->cdata)
  1863. {
  1864. if (c == ']')
  1865. {
  1866. c = soap_get1(soap);
  1867. if (c == ']')
  1868. {
  1869. c = soap_get0(soap);
  1870. if (c == '>')
  1871. {
  1872. soap->cdata = 0;
  1873. c = soap_get1(soap);
  1874. c = soap_get1(soap);
  1875. }
  1876. else
  1877. {
  1878. soap_unget(soap, ']');
  1879. return ']';
  1880. }
  1881. }
  1882. else
  1883. {
  1884. soap_revget1(soap);
  1885. return ']';
  1886. }
  1887. }
  1888. else
  1889. {
  1890. return c;
  1891. }
  1892. }
  1893. switch (c)
  1894. {
  1895. case '<':
  1896. do
  1897. {
  1898. c = soap_get1(soap);
  1899. } while (soap_coblank(c));
  1900. if (c == '!' || c == '?' || c == '%')
  1901. {
  1902. int k = 1;
  1903. if (c == '!')
  1904. {
  1905. c = soap_get1(soap);
  1906. if (c == '[')
  1907. {
  1908. do
  1909. {
  1910. c = soap_get1(soap);
  1911. } while ((int)c != EOF && c != '[');
  1912. if ((int)c == EOF)
  1913. break;
  1914. soap->cdata = 1;
  1915. c = soap_get1(soap);
  1916. continue;
  1917. }
  1918. if (c == '-' && (c = soap_get1(soap)) == '-')
  1919. {
  1920. do
  1921. {
  1922. c = soap_get1(soap);
  1923. if (c == '-' && (c = soap_get1(soap)) == '-')
  1924. break;
  1925. } while ((int)c != EOF);
  1926. }
  1927. }
  1928. else if (c == '?')
  1929. {
  1930. c = soap_getpi(soap);
  1931. }
  1932. while ((int)c != EOF)
  1933. {
  1934. if (c == '<')
  1935. {
  1936. k++;
  1937. }
  1938. else if (c == '>')
  1939. {
  1940. if (--k <= 0)
  1941. break;
  1942. }
  1943. c = soap_get1(soap);
  1944. }
  1945. if ((int)c == EOF)
  1946. break;
  1947. c = soap_get1(soap);
  1948. continue;
  1949. }
  1950. if (c == '/')
  1951. return SOAP_TT;
  1952. soap_revget1(soap);
  1953. return SOAP_LT;
  1954. case '>':
  1955. return SOAP_GT;
  1956. case '"':
  1957. return SOAP_QT;
  1958. case '\'':
  1959. return SOAP_AP;
  1960. case '&':
  1961. return soap_char(soap) | 0x80000000;
  1962. }
  1963. break;
  1964. }
  1965. return c;
  1966. }
  1967. /******************************************************************************/
  1968. static soap_wchar
  1969. soap_getpi(struct soap *soap)
  1970. {
  1971. char buf[64];
  1972. char *s = buf;
  1973. size_t i = sizeof(buf);
  1974. soap_wchar c;
  1975. while ((int)(c = soap_getchar(soap)) != EOF && c != '?')
  1976. {
  1977. if (i > 1)
  1978. {
  1979. if (soap_coblank(c))
  1980. c = ' ';
  1981. *s++ = (char)c;
  1982. i--;
  1983. }
  1984. }
  1985. *s = '\0';
  1986. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <?%s?>\n", buf));
  1987. if (!strncmp(buf, "xml ", 4))
  1988. {
  1989. s = strstr(buf, " encoding=");
  1990. if (s && s[10])
  1991. {
  1992. if (!soap_tag_cmp(s + 11, "iso-8859-1*")
  1993. || !soap_tag_cmp(s + 11, "latin1*"))
  1994. {
  1995. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n"));
  1996. soap->mode |= SOAP_ENC_LATIN;
  1997. }
  1998. else if (!soap_tag_cmp(s + 11, "utf-8*"))
  1999. {
  2000. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n"));
  2001. soap->mode &= ~SOAP_ENC_LATIN;
  2002. }
  2003. }
  2004. }
  2005. if ((int)c != EOF)
  2006. c = soap_getchar(soap);
  2007. return c;
  2008. }
  2009. /******************************************************************************/
  2010. #ifndef WITH_LEANER
  2011. SOAP_FMAC1
  2012. int
  2013. SOAP_FMAC2
  2014. soap_move(struct soap *soap, ULONG64 n)
  2015. {
  2016. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving " SOAP_ULONG_FORMAT " bytes forward\n", n));
  2017. for (; n; n--)
  2018. if ((int)soap_getchar(soap) == EOF)
  2019. return SOAP_EOF;
  2020. return SOAP_OK;
  2021. }
  2022. #endif
  2023. /******************************************************************************/
  2024. #ifndef WITH_LEANER
  2025. SOAP_FMAC1
  2026. ULONG64
  2027. SOAP_FMAC2
  2028. soap_tell(struct soap *soap)
  2029. {
  2030. return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0);
  2031. }
  2032. #endif
  2033. /******************************************************************************/
  2034. SOAP_FMAC1
  2035. int
  2036. SOAP_FMAC2
  2037. soap_pututf8(struct soap *soap, unsigned long c)
  2038. {
  2039. char tmp[24];
  2040. if ((c < 0x7F && c > 0x1F))
  2041. {
  2042. *tmp = (char)c;
  2043. return soap_send_raw(soap, tmp, 1);
  2044. }
  2045. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  2046. if (!(c == 0x09 || c == 0x0A || c == 0x0D || (c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF)))
  2047. c = SOAP_UNKNOWN_UNICODE_CHAR;
  2048. #endif
  2049. #ifndef WITH_LEAN
  2050. if (c > 0x9F)
  2051. {
  2052. char *t = tmp;
  2053. if (c < 0x0800)
  2054. {
  2055. *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
  2056. }
  2057. else
  2058. {
  2059. if (c < 0x010000)
  2060. {
  2061. *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
  2062. }
  2063. else
  2064. {
  2065. if (c < 0x200000)
  2066. {
  2067. *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
  2068. }
  2069. else
  2070. {
  2071. if (c < 0x04000000)
  2072. {
  2073. *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
  2074. }
  2075. else
  2076. {
  2077. *t++ = (char)(0xFC | ((c >> 30) & 0x01));
  2078. *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
  2079. }
  2080. *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
  2081. }
  2082. *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
  2083. }
  2084. *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
  2085. }
  2086. *t++ = (char)(0x80 | (c & 0x3F));
  2087. *t = '\0';
  2088. }
  2089. else
  2090. #endif
  2091. (SOAP_SNPRINTF(tmp, sizeof(tmp), 20), "&#x%lX;", c);
  2092. return soap_send(soap, tmp);
  2093. }
  2094. /******************************************************************************/
  2095. SOAP_FMAC1
  2096. soap_wchar
  2097. SOAP_FMAC2
  2098. soap_getutf8(struct soap *soap)
  2099. {
  2100. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  2101. soap_wchar c, c1, c2, c3;
  2102. #else
  2103. soap_wchar c, c1, c2, c3, c4;
  2104. #endif
  2105. c = soap->ahead;
  2106. if (c >= 0x80)
  2107. soap->ahead = 0;
  2108. else
  2109. c = (soap_wchar)soap_get(soap);
  2110. if (c < 0x80 || c > 0xFF || (soap->mode & SOAP_ENC_LATIN))
  2111. return c;
  2112. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  2113. c1 = (soap_wchar)soap_get1(soap);
  2114. if (c <= 0xC1 || (c1 & 0xC0) != 0x80)
  2115. {
  2116. soap_revget1(soap);
  2117. return SOAP_UNKNOWN_UNICODE_CHAR;
  2118. }
  2119. c1 &= 0x3F;
  2120. if (c < 0xE0)
  2121. return (((c & 0x1F) << 6) | c1);
  2122. c2 = (soap_wchar)soap_get1(soap);
  2123. if ((c == 0xE0 && c1 < 0x20) || (c2 & 0xC0) != 0x80)
  2124. {
  2125. soap_revget1(soap);
  2126. return SOAP_UNKNOWN_UNICODE_CHAR;
  2127. }
  2128. c2 &= 0x3F;
  2129. if (c < 0xF0)
  2130. return (((c & 0x0F) << 12) | (c1 << 6) | c2);
  2131. c3 = (soap_wchar)soap_get1(soap);
  2132. if ((c == 0xF0 && c1 < 0x10) || (c == 0xF4 && c1 >= 0x10) || c >= 0xF5 || (c3 & 0xC0) != 0x80)
  2133. {
  2134. soap_revget1(soap);
  2135. return SOAP_UNKNOWN_UNICODE_CHAR;
  2136. }
  2137. return (((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | (c3 & 0x3F));
  2138. #else
  2139. c1 = (soap_wchar)soap_get1(soap);
  2140. if (c < 0xC0 || (c1 & 0xC0) != 0x80)
  2141. {
  2142. soap_revget1(soap);
  2143. /* doesn't look like this is UTF-8, try continue as if ISO-8859-1 */
  2144. return c;
  2145. }
  2146. c1 &= 0x3F;
  2147. if (c < 0xE0)
  2148. return ((soap_wchar)(c & 0x1F) << 6) | c1;
  2149. c2 = (soap_wchar)soap_get1(soap) & 0x3F;
  2150. if (c < 0xF0)
  2151. return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2;
  2152. c3 = (soap_wchar)soap_get1(soap) & 0x3F;
  2153. if (c < 0xF8)
  2154. return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
  2155. c4 = (soap_wchar)soap_get1(soap) & 0x3F;
  2156. if (c < 0xFC)
  2157. return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
  2158. return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F);
  2159. #endif
  2160. }
  2161. /******************************************************************************/
  2162. SOAP_FMAC1
  2163. size_t
  2164. SOAP_FMAC2
  2165. soap_utf8len(const char *s)
  2166. {
  2167. size_t l = 0;
  2168. while (*s)
  2169. if ((*s++ & 0xC0) != 0x80)
  2170. l++;
  2171. return l;
  2172. }
  2173. /******************************************************************************/
  2174. SOAP_FMAC1
  2175. int
  2176. SOAP_FMAC2
  2177. soap_puthex(struct soap *soap, const unsigned char *s, int n)
  2178. {
  2179. char d[2 * SOAP_BINARY_BUFLEN], *p = d;
  2180. #ifdef WITH_DOM
  2181. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  2182. {
  2183. soap->dom->text = soap_s2hex(soap, s, NULL, n);
  2184. if (!soap->dom->text)
  2185. return soap->error;
  2186. return SOAP_OK;
  2187. }
  2188. #endif
  2189. for (; n > 0; n--)
  2190. {
  2191. int m = *s++;
  2192. p[0] = (char)((m >> 4) + (m > 159 ? '7' : '0'));
  2193. m &= 0x0F;
  2194. p[1] = (char)(m + (m > 9 ? '7' : '0'));
  2195. p += 2;
  2196. if (p - d == sizeof(d))
  2197. {
  2198. if (soap_send_raw(soap, d, sizeof(d)))
  2199. return soap->error;
  2200. p = d;
  2201. }
  2202. }
  2203. if (p != d && soap_send_raw(soap, d, p - d))
  2204. return soap->error;
  2205. return SOAP_OK;
  2206. }
  2207. /******************************************************************************/
  2208. SOAP_FMAC1
  2209. unsigned char*
  2210. SOAP_FMAC2
  2211. soap_gethex(struct soap *soap, int *n)
  2212. {
  2213. size_t l = 0;
  2214. #ifdef WITH_DOM
  2215. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  2216. {
  2217. soap->dom->text = soap_string_in(soap, 0, -1, -1, NULL);
  2218. return (unsigned char*)soap_hex2s(soap, soap->dom->text, NULL, 0, n);
  2219. }
  2220. #endif
  2221. #ifdef WITH_FAST
  2222. soap->labidx = 0;
  2223. for (;;)
  2224. {
  2225. char *s;
  2226. size_t i, k;
  2227. if (soap_append_lab(soap, NULL, 0))
  2228. return NULL;
  2229. s = soap->labbuf + soap->labidx;
  2230. k = soap->lablen - soap->labidx;
  2231. soap->labidx = soap->lablen;
  2232. for (i = 0; i < k; i++)
  2233. {
  2234. char d1, d2;
  2235. soap_wchar c;
  2236. c = soap_get(soap);
  2237. if (soap_isxdigit(c))
  2238. {
  2239. d1 = (char)c;
  2240. c = soap_get(soap);
  2241. if (soap_isxdigit(c))
  2242. {
  2243. d2 = (char)c;
  2244. }
  2245. else
  2246. {
  2247. soap->error = SOAP_TYPE;
  2248. return NULL;
  2249. }
  2250. }
  2251. else
  2252. {
  2253. unsigned char *p = NULL;
  2254. l = soap->lablen + i - k;
  2255. soap_unget(soap, c);
  2256. if (n)
  2257. *n = (int)l;
  2258. if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
  2259. {
  2260. soap->error = SOAP_LENGTH;
  2261. }
  2262. else
  2263. {
  2264. p = (unsigned char*)soap_malloc(soap, l);
  2265. if (p)
  2266. (void)soap_memcpy((void*)p, l, (const void*)soap->labbuf, l);
  2267. }
  2268. return p;
  2269. }
  2270. *s++ = (char)(((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'));
  2271. }
  2272. l = soap->lablen;
  2273. if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
  2274. {
  2275. soap->error = SOAP_LENGTH;
  2276. return NULL;
  2277. }
  2278. }
  2279. #else
  2280. if (soap_alloc_block(soap) == NULL)
  2281. return NULL;
  2282. for (;;)
  2283. {
  2284. int i;
  2285. char *s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN);
  2286. if (!s)
  2287. {
  2288. soap_end_block(soap, NULL);
  2289. return NULL;
  2290. }
  2291. for (i = 0; i < SOAP_BLKLEN; i++)
  2292. {
  2293. char d1, d2;
  2294. soap_wchar c = soap_get(soap);
  2295. if (soap_isxdigit(c))
  2296. {
  2297. d1 = (char)c;
  2298. c = soap_get(soap);
  2299. if (soap_isxdigit(c))
  2300. d2 = (char)c;
  2301. else
  2302. {
  2303. soap_end_block(soap, NULL);
  2304. soap->error = SOAP_TYPE;
  2305. return NULL;
  2306. }
  2307. }
  2308. else
  2309. {
  2310. unsigned char *p;
  2311. soap_unget(soap, c);
  2312. if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
  2313. {
  2314. soap->error = SOAP_LENGTH;
  2315. soap_end_block(soap, NULL);
  2316. return NULL;
  2317. }
  2318. if (n)
  2319. *n = (int)soap_size_block(soap, NULL, i);
  2320. p = (unsigned char*)soap_save_block(soap, NULL, NULL, 0);
  2321. return p;
  2322. }
  2323. *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
  2324. l++;
  2325. }
  2326. if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
  2327. {
  2328. soap->error = SOAP_LENGTH;
  2329. soap_end_block(soap, NULL);
  2330. return NULL;
  2331. }
  2332. }
  2333. #endif
  2334. }
  2335. /******************************************************************************/
  2336. SOAP_FMAC1
  2337. int
  2338. SOAP_FMAC2
  2339. soap_putbase64(struct soap *soap, const unsigned char *s, int n)
  2340. {
  2341. char d[4 * SOAP_BINARY_BUFLEN], *p = d;
  2342. if (!s)
  2343. return SOAP_OK;
  2344. #ifdef WITH_DOM
  2345. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  2346. {
  2347. soap->dom->text = soap_s2base64(soap, s, NULL, n);
  2348. if (!soap->dom->text)
  2349. return soap->error;
  2350. return SOAP_OK;
  2351. }
  2352. #endif
  2353. for (; n > 2; n -= 3, s += 3)
  2354. {
  2355. p[0] = soap_base64o[(s[0] & 0xFC) >> 2];
  2356. p[1] = soap_base64o[((s[0] & 0x03) << 4) | ((s[1] & 0xF0) >> 4)];
  2357. p[2] = soap_base64o[((s[1] & 0x0F) << 2) | ((s[2] & 0xC0) >> 6)];
  2358. p[3] = soap_base64o[s[2] & 0x3F];
  2359. p += 4;
  2360. if (p - d == sizeof(d))
  2361. {
  2362. if (soap_send_raw(soap, d, sizeof(d)))
  2363. return soap->error;
  2364. p = d;
  2365. }
  2366. }
  2367. if (n == 2)
  2368. {
  2369. p[0] = soap_base64o[(s[0] & 0xFC) >> 2];
  2370. p[1] = soap_base64o[((s[0] & 0x03) << 4) | ((s[1] & 0xF0) >> 4)];
  2371. p[2] = soap_base64o[(s[1] & 0x0F) << 2];
  2372. p[3] = '=';
  2373. p += 4;
  2374. }
  2375. else if (n == 1)
  2376. {
  2377. p[0] = soap_base64o[(s[0] & 0xFC) >> 2];
  2378. p[1] = soap_base64o[(s[0] & 0x03) << 4];
  2379. p[2] = '=';
  2380. p[3] = '=';
  2381. p += 4;
  2382. }
  2383. if (p != d && soap_send_raw(soap, d, p - d))
  2384. return soap->error;
  2385. return SOAP_OK;
  2386. }
  2387. /******************************************************************************/
  2388. SOAP_FMAC1
  2389. unsigned char*
  2390. SOAP_FMAC2
  2391. soap_getbase64(struct soap *soap, int *n, int malloc_flag)
  2392. {
  2393. size_t l = 0;
  2394. (void)malloc_flag;
  2395. #ifdef WITH_DOM
  2396. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  2397. {
  2398. soap->dom->text = soap_string_in(soap, 0, -1, -1, NULL);
  2399. return (unsigned char*)soap_base642s(soap, soap->dom->text, NULL, 0, n);
  2400. }
  2401. #endif
  2402. #ifdef WITH_FAST
  2403. soap->labidx = 0;
  2404. for (;;)
  2405. {
  2406. size_t i, k;
  2407. char *s;
  2408. if (soap_append_lab(soap, NULL, 2))
  2409. return NULL;
  2410. s = soap->labbuf + soap->labidx;
  2411. k = soap->lablen - soap->labidx;
  2412. soap->labidx = 3 * (soap->lablen / 3);
  2413. if (k > 2)
  2414. {
  2415. for (i = 0; i < k - 2; i += 3)
  2416. {
  2417. unsigned long m = 0;
  2418. int j = 0;
  2419. do
  2420. {
  2421. soap_wchar c = soap_get(soap);
  2422. if (c < SOAP_AP)
  2423. c &= 0x7FFFFFFF;
  2424. if (c == '=' || c < 0)
  2425. {
  2426. unsigned char *p = NULL;
  2427. switch (j)
  2428. {
  2429. case 2:
  2430. *s++ = (char)((m >> 4) & 0xFF);
  2431. i++;
  2432. break;
  2433. case 3:
  2434. *s++ = (char)((m >> 10) & 0xFF);
  2435. *s++ = (char)((m >> 2) & 0xFF);
  2436. i += 2;
  2437. }
  2438. l = soap->lablen + i - k;
  2439. if (n)
  2440. *n = (int)l;
  2441. if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
  2442. soap->error = SOAP_LENGTH;
  2443. else
  2444. {
  2445. p = (unsigned char*)soap_malloc(soap, l);
  2446. if (p)
  2447. (void)soap_memcpy((void*)p, l, (const void*)soap->labbuf, l);
  2448. }
  2449. if (c >= 0)
  2450. {
  2451. while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
  2452. continue;
  2453. }
  2454. soap_unget(soap, c);
  2455. return p;
  2456. }
  2457. c -= '+';
  2458. if (c >= 0 && c <= 79)
  2459. {
  2460. int b = soap_base64i[c];
  2461. if (b >= 64)
  2462. {
  2463. soap->error = SOAP_TYPE;
  2464. return NULL;
  2465. }
  2466. m = (m << 6) + b;
  2467. j++;
  2468. }
  2469. else if (!soap_coblank(c + '+'))
  2470. {
  2471. soap->error = SOAP_TYPE;
  2472. return NULL;
  2473. }
  2474. } while (j < 4);
  2475. *s++ = (char)((m >> 16) & 0xFF);
  2476. *s++ = (char)((m >> 8) & 0xFF);
  2477. *s++ = (char)(m & 0xFF);
  2478. }
  2479. l = soap->lablen;
  2480. if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
  2481. {
  2482. soap->error = SOAP_LENGTH;
  2483. return NULL;
  2484. }
  2485. }
  2486. }
  2487. #else
  2488. if (soap_alloc_block(soap) == NULL)
  2489. return NULL;
  2490. for (;;)
  2491. {
  2492. int i;
  2493. char *s = (char*)soap_push_block(soap, NULL, 3 * SOAP_BLKLEN); /* must be multiple of 3 */
  2494. if (!s)
  2495. {
  2496. soap_end_block(soap, NULL);
  2497. return NULL;
  2498. }
  2499. for (i = 0; i < SOAP_BLKLEN; i++)
  2500. {
  2501. unsigned long m = 0;
  2502. int j = 0;
  2503. do
  2504. {
  2505. soap_wchar c = soap_get(soap);
  2506. if (c < SOAP_AP)
  2507. c &= 0x7FFFFFFF;
  2508. if (c == '=' || c < 0)
  2509. {
  2510. unsigned char *p;
  2511. i *= 3;
  2512. switch (j)
  2513. {
  2514. case 2:
  2515. *s++ = (char)((m >> 4) & 0xFF);
  2516. i++;
  2517. l++;
  2518. break;
  2519. case 3:
  2520. *s++ = (char)((m >> 10) & 0xFF);
  2521. *s++ = (char)((m >> 2) & 0xFF);
  2522. l += 2;
  2523. i += 2;
  2524. }
  2525. if (n)
  2526. *n = (int)soap_size_block(soap, NULL, i);
  2527. if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
  2528. {
  2529. soap->error = SOAP_LENGTH;
  2530. soap_end_block(soap, NULL);
  2531. return NULL;
  2532. }
  2533. p = (unsigned char*)soap_save_block(soap, NULL, NULL, 0);
  2534. if (c >= 0)
  2535. {
  2536. while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
  2537. continue;
  2538. }
  2539. soap_unget(soap, c);
  2540. return p;
  2541. }
  2542. c -= '+';
  2543. if (c >= 0 && c <= 79)
  2544. {
  2545. int b = soap_base64i[c];
  2546. if (b >= 64)
  2547. {
  2548. soap->error = SOAP_TYPE;
  2549. return NULL;
  2550. }
  2551. m = (m << 6) + b;
  2552. j++;
  2553. }
  2554. else if (!soap_coblank(c + '+'))
  2555. {
  2556. soap->error = SOAP_TYPE;
  2557. return NULL;
  2558. }
  2559. } while (j < 4);
  2560. *s++ = (char)((m >> 16) & 0xFF);
  2561. *s++ = (char)((m >> 8) & 0xFF);
  2562. *s++ = (char)(m & 0xFF);
  2563. l += 3;
  2564. }
  2565. if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
  2566. {
  2567. soap->error = SOAP_LENGTH;
  2568. soap_end_block(soap, NULL);
  2569. return NULL;
  2570. }
  2571. }
  2572. #endif
  2573. }
  2574. /******************************************************************************/
  2575. #ifndef WITH_LEANER
  2576. SOAP_FMAC1
  2577. int
  2578. SOAP_FMAC2
  2579. soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
  2580. {
  2581. /* Check MTOM xop:Include element (within hex/base64Binary) */
  2582. /* TODO: this code to be obsoleted with new import/xop.h conventions */
  2583. short body = soap->body; /* should save type too? */
  2584. if (!soap_peek_element(soap))
  2585. {
  2586. if (!soap_element_begin_in(soap, ":Include", 0, NULL))
  2587. {
  2588. if (soap_attachment_forward(soap, ptr, size, id, type, options)
  2589. || (soap->body && soap_element_end_in(soap, ":Include")))
  2590. return soap->error;
  2591. }
  2592. else if (soap->error == SOAP_TAG_MISMATCH)
  2593. soap_retry(soap);
  2594. else
  2595. return soap->error;
  2596. }
  2597. soap->body = body;
  2598. return SOAP_OK;
  2599. }
  2600. #endif
  2601. /******************************************************************************/
  2602. #ifndef WITH_LEANER
  2603. SOAP_FMAC1
  2604. int
  2605. SOAP_FMAC2
  2606. soap_attachment_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
  2607. {
  2608. struct soap_xlist *xp;
  2609. *ptr = NULL;
  2610. *size = 0;
  2611. *id = NULL;
  2612. *type = NULL;
  2613. *options = NULL;
  2614. if (!*soap->href)
  2615. return SOAP_OK;
  2616. *id = soap_strdup(soap, soap->href);
  2617. xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist));
  2618. if (!xp)
  2619. return soap->error = SOAP_EOM;
  2620. xp->next = soap->xlist;
  2621. xp->ptr = ptr;
  2622. xp->size = size;
  2623. xp->id = *id;
  2624. xp->type = type;
  2625. xp->options = options;
  2626. soap->xlist = xp;
  2627. return SOAP_OK;
  2628. }
  2629. #endif
  2630. /******************************************************************************/
  2631. SOAP_FMAC1
  2632. void *
  2633. SOAP_FMAC2
  2634. soap_memdup(struct soap *soap, const void *s, size_t n)
  2635. {
  2636. void *t = NULL;
  2637. if (s)
  2638. {
  2639. t = soap_malloc(soap, n);
  2640. if (t)
  2641. (void)soap_memcpy(t, n, s, n);
  2642. }
  2643. return t;
  2644. }
  2645. /******************************************************************************/
  2646. SOAP_FMAC1
  2647. char *
  2648. SOAP_FMAC2
  2649. soap_strdup(struct soap *soap, const char *s)
  2650. {
  2651. char *t = NULL;
  2652. if (s)
  2653. {
  2654. size_t n = strlen(s) + 1;
  2655. if (n > 0)
  2656. {
  2657. t = (char*)soap_malloc(soap, n);
  2658. if (t)
  2659. {
  2660. (void)soap_memcpy((void*)t, n, (const void*)s, n);
  2661. t[n - 1] = '\0';
  2662. }
  2663. }
  2664. }
  2665. return t;
  2666. }
  2667. /******************************************************************************/
  2668. SOAP_FMAC1
  2669. wchar_t *
  2670. SOAP_FMAC2
  2671. soap_wstrdup(struct soap *soap, const wchar_t *s)
  2672. {
  2673. wchar_t *t = NULL;
  2674. if (s)
  2675. {
  2676. size_t n = 0, m;
  2677. while (s[n])
  2678. n++;
  2679. n++;
  2680. m = sizeof(wchar_t) * n;
  2681. if (n > 0)
  2682. {
  2683. t = (wchar_t*)soap_malloc(soap, m);
  2684. if (t)
  2685. {
  2686. (void)soap_memcpy((void*)t, m, (const void*)s, m);
  2687. t[n - 1] = L'\0';
  2688. }
  2689. }
  2690. }
  2691. return t;
  2692. }
  2693. /******************************************************************************/
  2694. SOAP_FMAC1
  2695. char *
  2696. SOAP_FMAC2
  2697. soap_strtrim(struct soap *soap, char *s)
  2698. {
  2699. (void)soap;
  2700. if (s)
  2701. {
  2702. char *t;
  2703. while ((*s >= 9 && *s <= 13) || *s == 32)
  2704. s++;
  2705. t = s;
  2706. while (*t)
  2707. t++;
  2708. while (--t > s && ((*t >= 9 && *t <= 13) || *t == 32))
  2709. continue;
  2710. t[1] = '\0';
  2711. }
  2712. return s;
  2713. }
  2714. /******************************************************************************/
  2715. SOAP_FMAC1
  2716. wchar_t *
  2717. SOAP_FMAC2
  2718. soap_wstrtrim(struct soap *soap, wchar_t *s)
  2719. {
  2720. (void)soap;
  2721. if (s)
  2722. {
  2723. wchar_t *t;
  2724. while ((*s >= 9 && *s <= 13) || *s == 32)
  2725. s++;
  2726. t = s;
  2727. while (*t)
  2728. t++;
  2729. while (--t > s && ((*t >= 9 && *t <= 13) || *t == 32))
  2730. continue;
  2731. t[1] = L'\0';
  2732. }
  2733. return s;
  2734. }
  2735. /******************************************************************************/
  2736. SOAP_FMAC1
  2737. struct soap_blist*
  2738. SOAP_FMAC2
  2739. soap_alloc_block(struct soap *soap)
  2740. {
  2741. struct soap_blist *p;
  2742. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", (void*)soap->blist));
  2743. p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist));
  2744. if (!p)
  2745. {
  2746. soap->error = SOAP_EOM;
  2747. return NULL;
  2748. }
  2749. p->next = soap->blist;
  2750. p->head = NULL;
  2751. p->size = 0;
  2752. p->item = 0;
  2753. soap->blist = p;
  2754. return p;
  2755. }
  2756. /******************************************************************************/
  2757. SOAP_FMAC1
  2758. void*
  2759. SOAP_FMAC2
  2760. soap_push_block(struct soap *soap, struct soap_blist *b, size_t n)
  2761. {
  2762. struct soap_bhead *p;
  2763. if (!b)
  2764. b = soap->blist;
  2765. if (!b
  2766. || b->size + n < b->size
  2767. || sizeof(struct soap_bhead) + n < n
  2768. || (SOAP_MAXALLOCSIZE > 0 && sizeof(struct soap_bhead) + n > SOAP_MAXALLOCSIZE))
  2769. {
  2770. soap->error = SOAP_EOM;
  2771. return NULL;
  2772. }
  2773. p = (struct soap_bhead*)SOAP_MALLOC(soap, sizeof(struct soap_bhead) + n);
  2774. if (!p)
  2775. {
  2776. soap->error = SOAP_EOM;
  2777. return NULL;
  2778. }
  2779. p->next = b->head;
  2780. b->head = p;
  2781. p->size = n;
  2782. b->size += n;
  2783. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block %p of %u bytes on %lu previous blocks (%lu bytes total)\n", (void*)p, (unsigned int)n, (unsigned long)b->item, (unsigned long)b->size));
  2784. b->item++;
  2785. return (void*)(p + 1); /* skip block header and point to n allocated bytes */
  2786. }
  2787. /******************************************************************************/
  2788. SOAP_FMAC1
  2789. void*
  2790. SOAP_FMAC2
  2791. soap_push_block_max(struct soap *soap, struct soap_blist *b, size_t n)
  2792. {
  2793. if (b && b->item >= soap->maxoccurs) /* restrict block array length */
  2794. {
  2795. soap->error = SOAP_OCCURS;
  2796. return NULL;
  2797. }
  2798. return soap_push_block(soap, b, n);
  2799. }
  2800. /******************************************************************************/
  2801. SOAP_FMAC1
  2802. void
  2803. SOAP_FMAC2
  2804. soap_pop_block(struct soap *soap, struct soap_blist *b)
  2805. {
  2806. struct soap_bhead *p;
  2807. if (!b)
  2808. b = soap->blist;
  2809. if (!b || !b->head)
  2810. return;
  2811. p = b->head;
  2812. b->size -= p->size;
  2813. b->head = p->next;
  2814. b->item--;
  2815. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block %p (%lu items of %lu bytes total)\n", (void*)p, (unsigned long)b->item, (unsigned long)b->size));
  2816. SOAP_FREE(soap, p);
  2817. }
  2818. /******************************************************************************/
  2819. SOAP_FMAC1
  2820. void
  2821. SOAP_FMAC2
  2822. soap_update_pointers(struct soap *soap, const char *dst, const char *src, size_t len)
  2823. {
  2824. const void *start = src, *end = src + len;
  2825. #ifndef WITH_LEANER
  2826. struct soap_xlist *xp;
  2827. #endif
  2828. #ifndef WITH_NOIDREF
  2829. if ((soap->version && !(soap->imode & SOAP_XML_TREE)) || (soap->mode & SOAP_XML_GRAPH))
  2830. {
  2831. int i;
  2832. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update pointers %p (%lu bytes) -> %p\n", (void*)src, (unsigned long)len, (void*)dst));
  2833. for (i = 0; i < SOAP_IDHASH; i++)
  2834. {
  2835. struct soap_ilist *ip;
  2836. for (ip = soap->iht[i]; ip; ip = ip->next)
  2837. {
  2838. struct soap_flist *fp;
  2839. void *p, **q;
  2840. if (ip->shaky)
  2841. {
  2842. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update shaky id='%s'\n", ip->id));
  2843. if (ip->ptr && ip->ptr >= start && ip->ptr < end)
  2844. {
  2845. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update ptr %p -> %p\n", ip->ptr, (void*)((const char*)ip->ptr + (dst-src))));
  2846. ip->ptr = (void*)((const char*)ip->ptr + (dst-src));
  2847. }
  2848. for (q = &ip->link; q; q = (void**)p)
  2849. {
  2850. p = *q;
  2851. if (p && p >= start && p < end)
  2852. {
  2853. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p -> %p\n", ip->id, p, (void*)((const char*)p + (dst-src))));
  2854. *q = (void*)((const char*)p + (dst-src));
  2855. }
  2856. }
  2857. for (q = &ip->copy; q; q = (void**)p)
  2858. {
  2859. p = *q;
  2860. if (p && p >= start && p < end)
  2861. {
  2862. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p -> %p\n", ip->id, p, (void*)((const char*)p + (dst-src))));
  2863. *q = (void*)((const char*)p + (dst-src));
  2864. }
  2865. }
  2866. for (fp = ip->flist; fp; fp = fp->next)
  2867. {
  2868. if (fp->ptr >= start && fp->ptr < end)
  2869. {
  2870. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' target type=%d %p -> %p\n", ip->id, fp->type, fp->ptr, (void*)((char*)fp->ptr + (dst-src))));
  2871. fp->ptr = (void*)((const char*)fp->ptr + (dst-src));
  2872. }
  2873. }
  2874. if (ip->smart && ip->smart >= start && ip->smart < end)
  2875. {
  2876. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Smart shared pointer update %p -> %p\n", ip->smart, (void*)((const char*)ip->smart + (dst-src))));
  2877. ip->smart = (void*)((const char*)ip->smart + (dst-src));
  2878. }
  2879. }
  2880. }
  2881. }
  2882. }
  2883. #else
  2884. (void)soap; (void)start; (void)end; (void)dst; (void)src;
  2885. #endif
  2886. #ifndef WITH_LEANER
  2887. for (xp = soap->xlist; xp; xp = xp->next)
  2888. {
  2889. if (xp->ptr && (void*)xp->ptr >= start && (void*)xp->ptr < end)
  2890. {
  2891. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update attachment id='%s' %p -> %p\n", xp->id ? xp->id : SOAP_STR_EOS, (void*)xp->ptr, (void*)((char*)xp->ptr + (dst-src))));
  2892. xp->ptr = (unsigned char**)((char*)xp->ptr + (dst-src));
  2893. xp->size = (int*)((char*)xp->size + (dst-src));
  2894. xp->type = (char**)((char*)xp->type + (dst-src));
  2895. xp->options = (char**)((char*)xp->options + (dst-src));
  2896. }
  2897. }
  2898. #endif
  2899. }
  2900. /******************************************************************************/
  2901. #ifndef WITH_NOIDREF
  2902. static int
  2903. soap_has_copies(struct soap *soap, const char *start, const char *end)
  2904. {
  2905. int i;
  2906. struct soap_ilist *ip = NULL;
  2907. struct soap_flist *fp = NULL;
  2908. const char *p;
  2909. for (i = 0; i < SOAP_IDHASH; i++)
  2910. {
  2911. for (ip = soap->iht[i]; ip; ip = ip->next)
  2912. {
  2913. for (p = (const char*)ip->copy; p; p = *(const char**)p)
  2914. if (p >= start && p < end)
  2915. return SOAP_ERR;
  2916. for (fp = ip->flist; fp; fp = fp->next)
  2917. if (fp->type == ip->type && (const char*)fp->ptr >= start && (const char*)fp->ptr < end)
  2918. return SOAP_ERR;
  2919. }
  2920. }
  2921. return SOAP_OK;
  2922. }
  2923. #endif
  2924. /******************************************************************************/
  2925. #ifndef WITH_NOIDREF
  2926. SOAP_FMAC1
  2927. int
  2928. SOAP_FMAC2
  2929. soap_resolve(struct soap *soap)
  2930. {
  2931. int i;
  2932. short flag;
  2933. const char *id;
  2934. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded refs\n"));
  2935. for (i = 0; i < SOAP_IDHASH; i++)
  2936. {
  2937. struct soap_ilist *ip;
  2938. for (ip = soap->iht[i]; ip; ip = ip->next)
  2939. {
  2940. if (ip->ptr)
  2941. {
  2942. void **q;
  2943. struct soap_flist *fp, **fpp = &ip->flist;
  2944. if (ip->spine)
  2945. ip->spine[0] = ip->ptr;
  2946. q = (void**)ip->link;
  2947. ip->link = NULL;
  2948. DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s' type=%d\n", ip->id, ip->type));
  2949. while (q)
  2950. {
  2951. void *p = *q;
  2952. *q = ip->ptr;
  2953. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... link %p -> %p\n", (void*)q, ip->ptr));
  2954. q = (void**)p;
  2955. }
  2956. while ((fp = *fpp))
  2957. {
  2958. if (fp->level > 0 && fp->finsert)
  2959. {
  2960. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... insert type=%d link %p -> %p\n", fp->type, fp->ptr, ip->ptr));
  2961. if (ip->spine && fp->level <= SOAP_MAXPTRS)
  2962. fp->finsert(soap, ip->type, fp->type, fp->ptr, fp->index, &ip->spine[fp->level - 1], &ip->smart);
  2963. else if (fp->level == 1)
  2964. fp->finsert(soap, ip->type, fp->type, fp->ptr, fp->index, &ip->ptr, &ip->smart);
  2965. else if (fp->level <= SOAP_MAXPTRS)
  2966. {
  2967. int i;
  2968. ip->spine = (void**)soap_malloc(soap, SOAP_MAXPTRS * sizeof(void*));
  2969. if (!ip->spine)
  2970. return soap->error = SOAP_EOM;
  2971. ip->spine[0] = ip->ptr;
  2972. for (i = 1; i < SOAP_MAXPTRS; i++)
  2973. ip->spine[i] = &ip->spine[i - 1];
  2974. fp->finsert(soap, ip->type, fp->type, fp->ptr, fp->index, &ip->spine[fp->level - 1], &ip->smart);
  2975. }
  2976. *fpp = fp->next;
  2977. SOAP_FREE(soap, fp);
  2978. }
  2979. else
  2980. fpp = &fp->next;
  2981. }
  2982. }
  2983. else if (*ip->id == '#')
  2984. {
  2985. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing id='%s'\n", ip->id));
  2986. soap_strcpy(soap->id, sizeof(soap->id), ip->id + 1);
  2987. return soap->error = SOAP_MISSING_ID;
  2988. }
  2989. }
  2990. }
  2991. do
  2992. {
  2993. flag = 0;
  2994. id = NULL;
  2995. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n"));
  2996. for (i = 0; i < SOAP_IDHASH; i++)
  2997. {
  2998. struct soap_ilist *ip;
  2999. for (ip = soap->iht[i]; ip; ip = ip->next)
  3000. {
  3001. if (ip->copy || ip->flist)
  3002. {
  3003. if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size))
  3004. {
  3005. struct soap_flist *fp;
  3006. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving id='%s' type=%d ptr=%p size=%lu ...\n", ip->id, ip->type, ip->ptr, (unsigned long)ip->size));
  3007. if (ip->copy)
  3008. {
  3009. void *p, **q = (void**)ip->copy;
  3010. DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id));
  3011. ip->copy = NULL;
  3012. do
  3013. {
  3014. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, (void*)q, (unsigned int)ip->size));
  3015. p = *q;
  3016. (void)soap_memcpy((void*)q, ip->size, (const void*)ip->ptr, ip->size);
  3017. q = (void**)p;
  3018. } while (q);
  3019. flag = 1;
  3020. }
  3021. while ((fp = ip->flist))
  3022. {
  3023. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data type=%d target type=%d location=%p level=%u id='%s'\n", ip->type, fp->type, ip->ptr, fp->level, ip->id));
  3024. if (fp->level == 0)
  3025. {
  3026. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%lu bytes)\n", ip->ptr, fp->ptr, (unsigned long)ip->size));
  3027. if (fp->finsert)
  3028. fp->finsert(soap, ip->type, fp->type, fp->ptr, fp->index, ip->ptr, &ip->smart);
  3029. else
  3030. (void)soap_memcpy((void*)fp->ptr, ip->size, (const void*)ip->ptr, ip->size);
  3031. }
  3032. ip->flist = fp->next;
  3033. SOAP_FREE(soap, fp);
  3034. flag = 1;
  3035. }
  3036. }
  3037. else if (*ip->id == '#')
  3038. id = ip->id;
  3039. }
  3040. }
  3041. }
  3042. } while (flag);
  3043. if (id)
  3044. {
  3045. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution error: forwarded data for id='%s' could not be propagated, please report this problem to the gSOAP developers\n", id));
  3046. return soap_id_nullify(soap, id);
  3047. }
  3048. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n"));
  3049. return SOAP_OK;
  3050. }
  3051. #endif
  3052. /******************************************************************************/
  3053. SOAP_FMAC1
  3054. size_t
  3055. SOAP_FMAC2
  3056. soap_size_block(struct soap *soap, struct soap_blist *b, size_t n)
  3057. {
  3058. if (!b)
  3059. b = soap->blist;
  3060. if (b->head)
  3061. {
  3062. b->size -= b->head->size - n;
  3063. b->head->size = n;
  3064. }
  3065. return b->size;
  3066. }
  3067. /******************************************************************************/
  3068. SOAP_FMAC1
  3069. char*
  3070. SOAP_FMAC2
  3071. soap_first_block(struct soap *soap, struct soap_blist *b)
  3072. {
  3073. struct soap_bhead *p, *q, *r;
  3074. if (!b)
  3075. b = soap->blist;
  3076. p = b->head;
  3077. if (!p)
  3078. return NULL;
  3079. r = NULL;
  3080. do
  3081. {
  3082. q = p->next;
  3083. p->next = r;
  3084. r = p;
  3085. p = q;
  3086. } while (p);
  3087. b->head = r;
  3088. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block %p\n", (void*)(r + 1)));
  3089. return (char*)(r + 1);
  3090. }
  3091. /******************************************************************************/
  3092. SOAP_FMAC1
  3093. char*
  3094. SOAP_FMAC2
  3095. soap_next_block(struct soap *soap, struct soap_blist *b)
  3096. {
  3097. struct soap_bhead *p;
  3098. if (!b)
  3099. b = soap->blist;
  3100. p = b->head;
  3101. if (p)
  3102. {
  3103. b->head = p->next;
  3104. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block %p, deleting current block\n", (void*)(b->head ? b->head + 1 : NULL)));
  3105. SOAP_FREE(soap, p);
  3106. if (b->head)
  3107. return (char*)(b->head + 1);
  3108. }
  3109. return NULL;
  3110. }
  3111. /******************************************************************************/
  3112. SOAP_FMAC1
  3113. size_t
  3114. SOAP_FMAC2
  3115. soap_block_size(struct soap *soap, struct soap_blist *b)
  3116. {
  3117. if (!b)
  3118. b = soap->blist;
  3119. return b->head->size;
  3120. }
  3121. /******************************************************************************/
  3122. SOAP_FMAC1
  3123. void
  3124. SOAP_FMAC2
  3125. soap_end_block(struct soap *soap, struct soap_blist *b)
  3126. {
  3127. struct soap_bhead *p, *q;
  3128. if (!b)
  3129. b = soap->blist;
  3130. if (b)
  3131. {
  3132. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n"));
  3133. for (p = b->head; p; p = q)
  3134. {
  3135. q = p->next;
  3136. SOAP_FREE(soap, p);
  3137. }
  3138. if (soap->blist == b)
  3139. soap->blist = b->next;
  3140. else
  3141. {
  3142. struct soap_blist *bp;
  3143. for (bp = soap->blist; bp; bp = bp->next)
  3144. {
  3145. if (bp->next == b)
  3146. {
  3147. bp->next = b->next;
  3148. break;
  3149. }
  3150. }
  3151. }
  3152. SOAP_FREE(soap, b);
  3153. }
  3154. DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restored previous block sequence\n"));
  3155. #ifndef WITH_NOIDREF
  3156. if (!soap->blist && ((soap->version && !(soap->imode & SOAP_XML_TREE)) || (soap->mode & SOAP_XML_GRAPH)))
  3157. {
  3158. int i;
  3159. struct soap_ilist *ip = NULL;
  3160. for (i = 0; i < SOAP_IDHASH; i++)
  3161. for (ip = soap->iht[i]; ip; ip = ip->next)
  3162. ip->shaky = 0;
  3163. }
  3164. #endif
  3165. }
  3166. /******************************************************************************/
  3167. SOAP_FMAC1
  3168. char*
  3169. SOAP_FMAC2
  3170. soap_save_block(struct soap *soap, struct soap_blist *b, char *p, int flag)
  3171. {
  3172. size_t n;
  3173. char *q, *s;
  3174. if (!b)
  3175. b = soap->blist;
  3176. if (b->size)
  3177. {
  3178. if (!p)
  3179. p = (char*)soap_malloc(soap, b->size);
  3180. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all %lu blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned long)b->item, (unsigned int)b->size, (void*)b->head, (void*)p));
  3181. if (p)
  3182. {
  3183. s = p;
  3184. for (q = soap_first_block(soap, b); q; q = soap_next_block(soap, b))
  3185. {
  3186. n = soap_block_size(soap, b);
  3187. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, (void*)q, (void*)s));
  3188. if (flag)
  3189. soap_update_pointers(soap, s, q, n);
  3190. (void)soap_memcpy((void*)s, n, (const void*)q, n);
  3191. s += n;
  3192. }
  3193. }
  3194. else
  3195. soap->error = SOAP_EOM;
  3196. }
  3197. soap_end_block(soap, b);
  3198. return p;
  3199. }
  3200. /******************************************************************************/
  3201. SOAP_FMAC1
  3202. char *
  3203. SOAP_FMAC2
  3204. soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim)
  3205. {
  3206. int i;
  3207. const char *t = ",%d";
  3208. if (!type)
  3209. return NULL;
  3210. if (soap->version == 2)
  3211. t = " %d";
  3212. if (soap->version != 2 && offset)
  3213. {
  3214. (SOAP_SNPRINTF(soap->type, sizeof(soap->type) - 1, strlen(type) + 20), "%s[%d", type, size[0] + offset[0]);
  3215. for (i = 1; i < dim; i++)
  3216. {
  3217. size_t l = strlen(soap->type);
  3218. (SOAP_SNPRINTF(soap->type + l, sizeof(soap->type) - l - 1, 20), t, size[i] + offset[i]);
  3219. }
  3220. }
  3221. else
  3222. {
  3223. (SOAP_SNPRINTF(soap->type, sizeof(soap->type) - 1, strlen(type) + 20), "%s[%d", type, size[0]);
  3224. for (i = 1; i < dim; i++)
  3225. {
  3226. size_t l = strlen(soap->type);
  3227. (SOAP_SNPRINTF(soap->type + l, sizeof(soap->type) - l - 1, 20), t, size[i]);
  3228. }
  3229. }
  3230. soap_strcat(soap->type, sizeof(soap->type), "]");
  3231. return soap->type;
  3232. }
  3233. /******************************************************************************/
  3234. SOAP_FMAC1
  3235. char *
  3236. SOAP_FMAC2
  3237. soap_putoffsets(struct soap *soap, const int *offset, int dim)
  3238. {
  3239. int i;
  3240. soap->arrayOffset[0] = '\0';
  3241. if (soap->version == 1)
  3242. {
  3243. (SOAP_SNPRINTF(soap->arrayOffset, sizeof(soap->arrayOffset) - 1, 20), "[%d", offset[0]);
  3244. for (i = 1; i < dim; i++)
  3245. {
  3246. size_t l = strlen(soap->arrayOffset);
  3247. (SOAP_SNPRINTF(soap->arrayOffset + l, sizeof(soap->arrayOffset) - l - 1, 20), ",%d", offset[i]);
  3248. }
  3249. soap_strcat(soap->arrayOffset, sizeof(soap->arrayOffset), "]");
  3250. }
  3251. return soap->arrayOffset;
  3252. }
  3253. /******************************************************************************/
  3254. SOAP_FMAC1
  3255. size_t
  3256. SOAP_FMAC2
  3257. soap_size(const int *size, int dim)
  3258. {
  3259. int i;
  3260. size_t n = 0;
  3261. if (size[0] <= 0)
  3262. return 0;
  3263. n = (size_t)size[0];
  3264. for (i = 1; i < dim; i++)
  3265. {
  3266. if (size[i] <= 0)
  3267. return 0;
  3268. n *= (size_t)size[i];
  3269. }
  3270. return (size_t)n;
  3271. }
  3272. /******************************************************************************/
  3273. SOAP_FMAC1
  3274. size_t
  3275. SOAP_FMAC2
  3276. soap_getsizes(const char *attr, int *size, int dim)
  3277. {
  3278. size_t i, k, n;
  3279. if (!*attr)
  3280. return 0;
  3281. i = strlen(attr);
  3282. n = 1;
  3283. do
  3284. {
  3285. for (; i > 0; i--)
  3286. if (attr[i - 1] == '[' || attr[i - 1] == ',' || attr[i - 1] == ' ')
  3287. break;
  3288. n *= k = (size_t)soap_strtoul(attr + i, NULL, 10);
  3289. size[--dim] = (int)k;
  3290. if (n > SOAP_MAXARRAYSIZE)
  3291. return 0;
  3292. } while (dim > 0 && --i > 0 && attr[i] != '[');
  3293. return n;
  3294. }
  3295. /******************************************************************************/
  3296. SOAP_FMAC1
  3297. int
  3298. SOAP_FMAC2
  3299. soap_getoffsets(const char *attr, const int *size, int *offset, int dim)
  3300. {
  3301. int i, j = 0;
  3302. if (offset)
  3303. {
  3304. for (i = 0; i < dim && attr && *attr; i++)
  3305. {
  3306. attr++;
  3307. j *= size[i];
  3308. j += offset[i] = (int)soap_strtol(attr, NULL, 10);
  3309. attr = strchr(attr, ',');
  3310. }
  3311. }
  3312. else
  3313. {
  3314. for (i = 0; i < dim && attr && *attr; i++)
  3315. {
  3316. attr++;
  3317. j *= size[i];
  3318. j += (int)soap_strtol(attr, NULL, 10);
  3319. attr = strchr(attr, ',');
  3320. }
  3321. }
  3322. return j;
  3323. }
  3324. /******************************************************************************/
  3325. SOAP_FMAC1
  3326. int
  3327. SOAP_FMAC2
  3328. soap_getposition(const char *attr, int *pos)
  3329. {
  3330. int i, n;
  3331. if (!*attr)
  3332. return -1;
  3333. n = 0;
  3334. i = 1;
  3335. do
  3336. {
  3337. pos[n++] = (int)soap_strtol(attr + i, NULL, 10);
  3338. while (attr[i] && attr[i] != ',' && attr[i] != ']')
  3339. i++;
  3340. if (attr[i] == ',')
  3341. i++;
  3342. } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']');
  3343. return n;
  3344. }
  3345. /******************************************************************************/
  3346. SOAP_FMAC1
  3347. struct soap_nlist *
  3348. SOAP_FMAC2
  3349. soap_push_namespace(struct soap *soap, const char *id, const char *ns)
  3350. {
  3351. struct soap_nlist *np = NULL;
  3352. struct Namespace *p;
  3353. short i = -1;
  3354. size_t n, k;
  3355. n = strlen(id);
  3356. k = strlen(ns) + 1;
  3357. p = soap->local_namespaces;
  3358. if (p)
  3359. {
  3360. for (i = 0; p->id; p++, i++)
  3361. {
  3362. if (p->ns && !strcmp(ns, p->ns))
  3363. break;
  3364. if (p->out)
  3365. {
  3366. if (!strcmp(ns, p->out))
  3367. break;
  3368. }
  3369. else if (p->in)
  3370. {
  3371. if (!soap_tag_cmp(ns, p->in))
  3372. {
  3373. if (SOAP_MAXALLOCSIZE <= 0 || k <= SOAP_MAXALLOCSIZE)
  3374. p->out = (char*)SOAP_MALLOC(soap, k);
  3375. if (p->out)
  3376. soap_strcpy(p->out, k, ns);
  3377. break;
  3378. }
  3379. }
  3380. }
  3381. if (!p->id)
  3382. i = -1;
  3383. }
  3384. if (i >= 0)
  3385. k = 0;
  3386. if (sizeof(struct soap_nlist) + n + k > n && (SOAP_MAXALLOCSIZE <= 0 || sizeof(struct soap_nlist) + n + k <= SOAP_MAXALLOCSIZE))
  3387. np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k);
  3388. if (!np)
  3389. {
  3390. soap->error = SOAP_EOM;
  3391. return NULL;
  3392. }
  3393. np->next = soap->nlist;
  3394. soap->nlist = np;
  3395. np->level = soap->level;
  3396. np->index = i;
  3397. soap_strcpy((char*)np->id, n + 1, id);
  3398. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s'='%s'\n", soap->level, id, ns));
  3399. if (i < 0)
  3400. {
  3401. np->ns = np->id + n + 1;
  3402. soap_strcpy((char*)np->ns, k, ns);
  3403. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns));
  3404. }
  3405. else
  3406. {
  3407. np->ns = NULL;
  3408. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id));
  3409. }
  3410. return np;
  3411. }
  3412. /******************************************************************************/
  3413. SOAP_FMAC1
  3414. void
  3415. SOAP_FMAC2
  3416. soap_pop_namespace(struct soap *soap)
  3417. {
  3418. struct soap_nlist *np, *nq;
  3419. for (np = soap->nlist; np && np->level >= soap->level; np = nq)
  3420. {
  3421. nq = np->next;
  3422. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop namespace binding (level=%u) '%s' level=%u\n", soap->level, np->id, np->level));
  3423. SOAP_FREE(soap, np);
  3424. }
  3425. soap->nlist = np;
  3426. }
  3427. /******************************************************************************/
  3428. SOAP_FMAC1
  3429. int
  3430. SOAP_FMAC2
  3431. soap_match_namespace(struct soap *soap, const char *id1, const char *id2, size_t n1, size_t n2)
  3432. {
  3433. struct soap_nlist *np = soap->nlist;
  3434. const char *s;
  3435. // std::cerr<<"Sassan Debug1: "<<np->ns<<std::endl;
  3436. while (np && (strncmp(np->id, id1, n1) || np->id[n1]))
  3437. np = np->next;
  3438. // 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;
  3439. if (np)
  3440. {
  3441. if (!(soap->mode & SOAP_XML_IGNORENS) && (n2 > 0 || !np->ns || *np->ns))
  3442. {
  3443. if (np->index < 0
  3444. || ((s = soap->local_namespaces[np->index].id) && (strncmp(s, id2, n2) || (s[n2] && s[n2] != '_'))))
  3445. return SOAP_NAMESPACE;
  3446. }
  3447. return SOAP_OK;
  3448. }
  3449. if (n1 == 0)
  3450. return n2 == 0 || (soap->mode & SOAP_XML_IGNORENS) ? SOAP_OK : SOAP_NAMESPACE;
  3451. if ((n1 == 3 && n1 == n2 && !strncmp(id1, "xml", 3) && !strncmp(id1, id2, 3))
  3452. || (soap->mode & SOAP_XML_IGNORENS))
  3453. return SOAP_OK;
  3454. return soap->error = SOAP_SYNTAX_ERROR;
  3455. }
  3456. /******************************************************************************/
  3457. SOAP_FMAC1
  3458. const char*
  3459. SOAP_FMAC2
  3460. soap_current_namespace_tag(struct soap *soap, const char *tag)
  3461. {
  3462. struct soap_nlist *np;
  3463. const char *s;
  3464. if (!tag || !strncmp(tag, "xml", 3))
  3465. return NULL;
  3466. np = soap->nlist;
  3467. s = strchr(tag, ':');
  3468. if (!s)
  3469. {
  3470. while (np && *np->id) /* find default namespace, if present */
  3471. np = np->next;
  3472. }
  3473. else
  3474. {
  3475. while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag]))
  3476. np = np->next;
  3477. if (!np)
  3478. soap->error = SOAP_NAMESPACE;
  3479. }
  3480. if (np)
  3481. {
  3482. if (np->index >= 0)
  3483. return soap->namespaces[np->index].ns;
  3484. if (np->ns)
  3485. {
  3486. s = np->ns;
  3487. if (*s)
  3488. return soap_strdup(soap, s);
  3489. do
  3490. np = np->next;
  3491. while (np && *np->id); /* find if there is any other default namespace */
  3492. if (np)
  3493. return soap_strdup(soap, s);
  3494. }
  3495. }
  3496. return NULL;
  3497. }
  3498. /******************************************************************************/
  3499. SOAP_FMAC1
  3500. const char*
  3501. SOAP_FMAC2
  3502. soap_current_namespace_att(struct soap *soap, const char *tag)
  3503. {
  3504. struct soap_nlist *np;
  3505. const char *s;
  3506. if (!tag || !strncmp(tag, "xml", 3))
  3507. return NULL;
  3508. s = strchr(tag, ':');
  3509. if (!s)
  3510. return NULL;
  3511. np = soap->nlist;
  3512. while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag]))
  3513. np = np->next;
  3514. if (!np)
  3515. soap->error = SOAP_NAMESPACE;
  3516. if (np)
  3517. {
  3518. if (np->index >= 0)
  3519. return soap->namespaces[np->index].ns;
  3520. if (np->ns && *np->ns)
  3521. return soap_strdup(soap, np->ns);
  3522. }
  3523. return NULL;
  3524. }
  3525. /******************************************************************************/
  3526. SOAP_FMAC1
  3527. int
  3528. SOAP_FMAC2
  3529. soap_tag_cmp(const char *s, const char *t)
  3530. {
  3531. for (;;)
  3532. {
  3533. int c1 = *s;
  3534. int c2 = *t;
  3535. if (!c1 || c1 == '"')
  3536. break;
  3537. if (c2 != '-')
  3538. {
  3539. if (c1 != c2)
  3540. {
  3541. if (c1 >= 'A' && c1 <= 'Z')
  3542. c1 += 'a' - 'A';
  3543. if (c2 >= 'A' && c2 <= 'Z')
  3544. c2 += 'a' - 'A';
  3545. }
  3546. if (c1 != c2)
  3547. {
  3548. if (c2 != '*')
  3549. return 1;
  3550. c2 = *++t;
  3551. if (!c2)
  3552. return 0;
  3553. if (c2 >= 'A' && c2 <= 'Z')
  3554. c2 += 'a' - 'A';
  3555. for (;;)
  3556. {
  3557. c1 = *s;
  3558. if (!c1 || c1 == '"')
  3559. break;
  3560. if (c1 >= 'A' && c1 <= 'Z')
  3561. c1 += 'a' - 'A';
  3562. if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1))
  3563. return 0;
  3564. s++;
  3565. }
  3566. break;
  3567. }
  3568. }
  3569. s++;
  3570. t++;
  3571. }
  3572. if (*t == '*' && !t[1])
  3573. return 0;
  3574. return *t;
  3575. }
  3576. /******************************************************************************/
  3577. SOAP_FMAC1
  3578. int
  3579. SOAP_FMAC2
  3580. soap_match_tag(struct soap *soap, const char *tag1, const char *tag2)
  3581. {
  3582. const char *s, *t;
  3583. int err;
  3584. if (!tag1 || !tag2 || !*tag2)
  3585. return SOAP_OK;
  3586. s = strchr(tag1, ':');
  3587. t = strchr(tag2, ':');
  3588. if (t)
  3589. {
  3590. if (s)
  3591. {
  3592. if (t[1] && SOAP_STRCMP(s + 1, t + 1))
  3593. return SOAP_TAG_MISMATCH;
  3594. if (t != tag2 && !(soap->mode & SOAP_XML_IGNORENS))
  3595. {
  3596. // err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2);
  3597. err=SOAP_OK;
  3598. // std::cerr<<"soap_match_namespace err: "<<err<<std::endl;
  3599. if (err)
  3600. {
  3601. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sassan Debug '%s' and '%s' r\n", tag1, tag2));
  3602. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
  3603. if (err == SOAP_NAMESPACE)
  3604. return SOAP_TAG_MISMATCH;
  3605. return err;
  3606. }
  3607. }
  3608. }
  3609. else if (!t[1])
  3610. {
  3611. if ((soap->mode & SOAP_XML_IGNORENS) || soap_match_namespace(soap, tag1, tag2, 0, t - tag2))
  3612. return SOAP_TAG_MISMATCH;
  3613. }
  3614. else if (SOAP_STRCMP(tag1, t + 1))
  3615. {
  3616. return SOAP_TAG_MISMATCH;
  3617. }
  3618. else if (t != tag2)
  3619. {
  3620. err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2);
  3621. if (err)
  3622. {
  3623. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
  3624. if (err == SOAP_NAMESPACE)
  3625. return SOAP_TAG_MISMATCH;
  3626. return err;
  3627. }
  3628. }
  3629. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2));
  3630. return SOAP_OK;
  3631. }
  3632. if (s)
  3633. {
  3634. if (!(soap->mode & SOAP_XML_IGNORENS) || SOAP_STRCMP(s + 1, tag2)) /* always fails (except when ignoring ns) */
  3635. return SOAP_TAG_MISMATCH;
  3636. }
  3637. else if (SOAP_STRCMP(tag1, tag2)
  3638. #ifndef WITH_NOEMPTYNAMESPACES
  3639. || ((soap->mode & SOAP_XML_STRICT) && !(soap->mode & SOAP_XML_IGNORENS) && soap_match_namespace(soap, tag1, tag2, 0, 0)) /* strict checking: default namespace must be null namespace */
  3640. #endif
  3641. )
  3642. {
  3643. return SOAP_TAG_MISMATCH;
  3644. }
  3645. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2));
  3646. return SOAP_OK;
  3647. }
  3648. /******************************************************************************/
  3649. SOAP_FMAC1
  3650. int
  3651. SOAP_FMAC2
  3652. soap_match_att(struct soap *soap, const char *tag1, const char *tag2)
  3653. {
  3654. const char *s, *t;
  3655. int err;
  3656. if (!tag1 || !tag2 || !*tag2)
  3657. return SOAP_OK;
  3658. s = strchr(tag1, ':');
  3659. t = strchr(tag2, ':');
  3660. if (t)
  3661. {
  3662. if (s)
  3663. {
  3664. if (t[1] && SOAP_STRCMP(s + 1, t + 1))
  3665. return SOAP_TAG_MISMATCH;
  3666. if (t != tag2 && !(soap->mode & SOAP_XML_IGNORENS))
  3667. {
  3668. err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2);
  3669. if (err)
  3670. {
  3671. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Atts '%s' and '%s' match but namespaces differ\n", tag1, tag2));
  3672. if (err == SOAP_NAMESPACE)
  3673. return SOAP_TAG_MISMATCH;
  3674. return err;
  3675. }
  3676. }
  3677. }
  3678. else if (!t[1] || t != tag2 || SOAP_STRCMP(tag1, t + 1))
  3679. return SOAP_TAG_MISMATCH;
  3680. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Atts and (default) namespaces match: '%s' '%s'\n", tag1, tag2));
  3681. return SOAP_OK;
  3682. }
  3683. if (s)
  3684. {
  3685. if (!(soap->mode & SOAP_XML_IGNORENS) || SOAP_STRCMP(s + 1, tag2)) /* always fails (except when ignoring ns) */
  3686. return SOAP_TAG_MISMATCH;
  3687. }
  3688. else if (SOAP_STRCMP(tag1, tag2))
  3689. return SOAP_TAG_MISMATCH;
  3690. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Atts match: '%s' '%s'\n", tag1, tag2));
  3691. return SOAP_OK;
  3692. }
  3693. /******************************************************************************/
  3694. SOAP_FMAC1
  3695. int
  3696. SOAP_FMAC2
  3697. soap_match_array(struct soap *soap, const char *type)
  3698. {
  3699. if (type && *soap->arrayType)
  3700. {
  3701. if (soap->version == 1 || !strchr(type, '['))
  3702. {
  3703. if (soap_match_tag(soap, soap->arrayType, type)
  3704. && soap_match_tag(soap, soap->arrayType, "xsd:anyType")
  3705. && soap_match_tag(soap, soap->arrayType, "xsd:ur-type"))
  3706. {
  3707. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SOAP array type mismatch: '%s' '%s'\n", soap->arrayType, type));
  3708. return SOAP_TAG_MISMATCH;
  3709. }
  3710. }
  3711. }
  3712. return SOAP_OK;
  3713. }
  3714. /******************************************************************************\
  3715. *
  3716. * SSL/TLS
  3717. *
  3718. \******************************************************************************/
  3719. #ifdef WITH_OPENSSL
  3720. SOAP_FMAC1
  3721. int
  3722. SOAP_FMAC2
  3723. soap_rand()
  3724. {
  3725. int r;
  3726. if (!soap_ssl_init_done)
  3727. soap_ssl_init();
  3728. #if OPENSSL_VERSION_NUMBER < 0x10100000L
  3729. RAND_pseudo_bytes((unsigned char*)&r, sizeof(int));
  3730. #else
  3731. RAND_bytes((unsigned char*)&r, sizeof(int));
  3732. #endif
  3733. return r;
  3734. }
  3735. #endif
  3736. /******************************************************************************/
  3737. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_SYSTEMSSL)
  3738. SOAP_FMAC1
  3739. int
  3740. SOAP_FMAC2
  3741. #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
  3742. 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)
  3743. #else
  3744. 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)
  3745. #endif
  3746. {
  3747. int err;
  3748. soap->keyfile = keyfile;
  3749. #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
  3750. soap->keyid = keyid; /* vxWorks compatible */
  3751. #endif
  3752. soap->password = password;
  3753. soap->cafile = cafile;
  3754. soap->capath = capath;
  3755. #ifdef WITH_OPENSSL
  3756. soap->dhfile = dhfile;
  3757. soap->randfile = randfile;
  3758. if (!soap->fsslverify)
  3759. soap->fsslverify = ssl_verify_callback;
  3760. #endif
  3761. soap->ssl_flags = flags | (dhfile == NULL ? SOAP_SSL_RSA : 0);
  3762. #ifdef WITH_GNUTLS
  3763. (void)randfile; (void)sid;
  3764. if (dhfile)
  3765. {
  3766. char *s;
  3767. int n = (int)soap_strtoul(dhfile, &s, 10);
  3768. if (!soap->dh_params)
  3769. gnutls_dh_params_init(&soap->dh_params);
  3770. /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
  3771. if (n >= 512 && s && *s == '\0')
  3772. gnutls_dh_params_generate2(soap->dh_params, (unsigned int)n);
  3773. else
  3774. {
  3775. unsigned int dparams_len;
  3776. unsigned char dparams_buf[1024];
  3777. FILE *fd = fopen(dhfile, "r");
  3778. if (!fd)
  3779. return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR);
  3780. dparams_len = (unsigned int)fread(dparams_buf, 1, sizeof(dparams_buf), fd);
  3781. fclose(fd);
  3782. gnutls_datum_t dparams = {
  3783. dparams_buf, dparams_len };
  3784. if (gnutls_dh_params_import_pkcs3(soap->dh_params, &dparams, GNUTLS_X509_FMT_PEM))
  3785. return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR);
  3786. }
  3787. }
  3788. else
  3789. {
  3790. #if GNUTLS_VERSION_NUMBER < 0x030300
  3791. if (!soap->rsa_params)
  3792. gnutls_rsa_params_init(&soap->rsa_params);
  3793. gnutls_rsa_params_generate2(soap->rsa_params, SOAP_SSL_RSA_BITS);
  3794. #endif
  3795. }
  3796. if (soap->session)
  3797. {
  3798. gnutls_deinit(soap->session);
  3799. soap->session = NULL;
  3800. }
  3801. if (soap->xcred)
  3802. {
  3803. gnutls_certificate_free_credentials(soap->xcred);
  3804. soap->xcred = NULL;
  3805. }
  3806. #endif
  3807. #ifdef WITH_SYSTEMSSL
  3808. (void)randfile; (void)sid;
  3809. if (soap->ctx)
  3810. gsk_environment_close(&soap->ctx);
  3811. #endif
  3812. err = soap->fsslauth(soap);
  3813. #ifdef WITH_OPENSSL
  3814. if (!err)
  3815. {
  3816. if (sid)
  3817. SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, (unsigned int)strlen(sid));
  3818. else
  3819. SSL_CTX_set_session_cache_mode(soap->ctx, SSL_SESS_CACHE_OFF);
  3820. }
  3821. #endif
  3822. return err;
  3823. }
  3824. #endif
  3825. /******************************************************************************/
  3826. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_SYSTEMSSL)
  3827. SOAP_FMAC1
  3828. int
  3829. SOAP_FMAC2
  3830. #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
  3831. 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)
  3832. #else
  3833. 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)
  3834. #endif
  3835. {
  3836. soap->keyfile = keyfile;
  3837. #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
  3838. soap->keyid = keyid; /* vxWorks compatible */
  3839. #endif
  3840. soap->password = password;
  3841. soap->cafile = cafile;
  3842. soap->capath = capath;
  3843. soap->ssl_flags = SOAP_SSL_CLIENT | flags;
  3844. #ifdef WITH_OPENSSL
  3845. soap->dhfile = NULL;
  3846. soap->randfile = randfile;
  3847. if (!soap->fsslverify)
  3848. soap->fsslverify = (flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) == 0 ? ssl_verify_callback : ssl_verify_callback_allow_expired_certificate;
  3849. #endif
  3850. #ifdef WITH_GNUTLS
  3851. (void)randfile;
  3852. if (soap->session)
  3853. {
  3854. gnutls_deinit(soap->session);
  3855. soap->session = NULL;
  3856. }
  3857. if (soap->xcred)
  3858. {
  3859. gnutls_certificate_free_credentials(soap->xcred);
  3860. soap->xcred = NULL;
  3861. }
  3862. #endif
  3863. #ifdef WITH_SYSTEMSSL
  3864. (void)randfile;
  3865. if (soap->ctx)
  3866. gsk_environment_close(&soap->ctx);
  3867. #endif
  3868. return soap->fsslauth(soap);
  3869. }
  3870. #endif
  3871. /******************************************************************************/
  3872. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
  3873. SOAP_FMAC1
  3874. int
  3875. SOAP_FMAC2
  3876. soap_ssl_crl(struct soap *soap, const char *crlfile)
  3877. {
  3878. #ifdef WITH_OPENSSL
  3879. if (crlfile && soap->ctx)
  3880. {
  3881. #if OPENSSL_VERSION_NUMBER > 0x00907000L
  3882. X509_STORE *store = SSL_CTX_get_cert_store(soap->ctx);
  3883. if (*crlfile)
  3884. {
  3885. int ret;
  3886. X509_LOOKUP *lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
  3887. if (!lookup)
  3888. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't create X509_LOOKUP object", SOAP_SSL_ERROR);
  3889. ret = X509_load_crl_file(lookup, crlfile, X509_FILETYPE_PEM);
  3890. if (ret <= 0)
  3891. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CRL PEM file", SOAP_SSL_ERROR);
  3892. }
  3893. X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
  3894. #endif
  3895. }
  3896. else
  3897. soap->crlfile = crlfile; /* activate later when store is available */
  3898. #endif
  3899. #ifdef WITH_GNUTLS
  3900. if (crlfile && soap->xcred)
  3901. {
  3902. if (*crlfile)
  3903. if (gnutls_certificate_set_x509_crl_file(soap->xcred, crlfile, GNUTLS_X509_FMT_PEM) < 0)
  3904. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CRL PEM file", SOAP_SSL_ERROR);
  3905. }
  3906. else
  3907. {
  3908. soap->crlfile = crlfile; /* activate later when xcred is available */
  3909. }
  3910. #endif
  3911. return SOAP_OK;
  3912. }
  3913. #endif
  3914. /******************************************************************************/
  3915. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
  3916. SOAP_FMAC1
  3917. void
  3918. SOAP_FMAC2
  3919. soap_ssl_init()
  3920. {
  3921. /* Note: for multi-threaded applications, the main program should call soap_ssl_init() before any threads are started */
  3922. if (!soap_ssl_init_done)
  3923. {
  3924. soap_ssl_init_done = 1;
  3925. #ifdef WITH_OPENSSL
  3926. SSL_library_init();
  3927. OpenSSL_add_all_algorithms(); /* we keep ciphers and digests for the program's lifetime */
  3928. #ifndef WITH_LEAN
  3929. SSL_load_error_strings();
  3930. #endif
  3931. #if !defined(WIN32) && !defined(CYGWIN) && !defined(__MINGW32__) && !defined(__MINGW64__)
  3932. if (!RAND_load_file("/dev/urandom", 1024))
  3933. #else
  3934. if (1)
  3935. #endif
  3936. {
  3937. /* if /dev/urandom does not exist we need to do at least some pertubations to seed the OpenSSL PRNG */
  3938. char buf[1024];
  3939. RAND_seed(buf, sizeof(buf));
  3940. #ifdef HAVE_RANDOM
  3941. srandom((unsigned long)time(NULL));
  3942. #else
  3943. srand((unsigned int)time(NULL));
  3944. #endif
  3945. do
  3946. {
  3947. #ifdef HAVE_RANDOM
  3948. long r = random(); /* we actually do no use random() anywhere, except to help seed the OpenSSL PRNG */
  3949. RAND_seed(&r, sizeof(long));
  3950. #else
  3951. int r = rand(); /* we actually do no use rand() anywhere, except to help seed the OpenSSL PRNG */
  3952. RAND_seed(&r, sizeof(int));
  3953. #endif
  3954. } while (!RAND_status());
  3955. }
  3956. #endif
  3957. #ifdef WITH_GNUTLS
  3958. # if GNUTLS_VERSION_NUMBER < 0x020b00
  3959. # if defined(HAVE_PTHREAD_H)
  3960. gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
  3961. # elif defined(HAVE_PTH_H)
  3962. gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
  3963. # endif
  3964. gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0);
  3965. gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
  3966. gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); /* libgcrypt init done */
  3967. # endif
  3968. # if GNUTLS_VERSION_NUMBER < 0x030300
  3969. gnutls_global_init();
  3970. # endif
  3971. #endif
  3972. }
  3973. }
  3974. #endif
  3975. /******************************************************************************/
  3976. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
  3977. SOAP_FMAC1
  3978. void
  3979. SOAP_FMAC2
  3980. soap_ssl_noinit()
  3981. {
  3982. /* Call this first to bypass SSL init is SSL is already initialized elsewhere */
  3983. soap_ssl_init_done = 1;
  3984. }
  3985. #endif
  3986. /******************************************************************************/
  3987. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
  3988. SOAP_FMAC1
  3989. const char *
  3990. SOAP_FMAC2
  3991. soap_ssl_error(struct soap *soap, int ret, int err)
  3992. {
  3993. #ifdef WITH_OPENSSL
  3994. const char *msg = soap_code_str(h_ssl_error_codes, err);
  3995. if (!msg)
  3996. return ERR_error_string(err, soap->msgbuf);
  3997. (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(msg) + 1), "%s\n", msg);
  3998. if (ERR_peek_error())
  3999. {
  4000. unsigned long r;
  4001. while ((r = ERR_get_error()))
  4002. {
  4003. size_t l = strlen(soap->msgbuf);
  4004. ERR_error_string_n(r, soap->msgbuf + l, sizeof(soap->msgbuf) - l);
  4005. l = strlen(soap->msgbuf);
  4006. if (l + 1 < sizeof(soap->msgbuf))
  4007. {
  4008. soap->msgbuf[l++] = '\n';
  4009. soap->msgbuf[l] = '\0';
  4010. }
  4011. if (ERR_GET_REASON(r) == SSL_R_CERTIFICATE_VERIFY_FAILED && l < sizeof(soap->msgbuf))
  4012. {
  4013. const char *s = X509_verify_cert_error_string(SSL_get_verify_result(soap->ssl));
  4014. (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, strlen(s)), "%s", s);
  4015. }
  4016. }
  4017. }
  4018. else
  4019. {
  4020. size_t l = strlen(soap->msgbuf);
  4021. switch (ret)
  4022. {
  4023. case 0:
  4024. 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.");
  4025. break;
  4026. case -1:
  4027. {
  4028. const char *s = strerror(soap_errno);
  4029. (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, strlen(s) + 42), "Error observed by underlying SSL/TLS BIO: %s", s);
  4030. }
  4031. break;
  4032. }
  4033. }
  4034. ERR_clear_error();
  4035. return soap->msgbuf;
  4036. #endif
  4037. #ifdef WITH_GNUTLS
  4038. (void)soap;
  4039. (void)err;
  4040. return gnutls_strerror(ret);
  4041. #endif
  4042. }
  4043. #endif
  4044. /******************************************************************************/
  4045. #ifdef WITH_SYSTEMSSL
  4046. static int
  4047. ssl_recv(int sk, void *s, int n, char *user)
  4048. {
  4049. (void)user;
  4050. return recv(sk, s, n, 0);
  4051. }
  4052. #endif
  4053. /******************************************************************************/
  4054. #ifdef WITH_SYSTEMSSL
  4055. static int
  4056. ssl_send(int sk, void *s, int n, char *user)
  4057. {
  4058. (void)user;
  4059. return send(sk, s, n, 0);
  4060. }
  4061. #endif
  4062. /******************************************************************************/
  4063. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_SYSTEMSSL)
  4064. static int
  4065. ssl_auth_init(struct soap *soap)
  4066. {
  4067. #ifdef WITH_OPENSSL
  4068. #if OPENSSL_VERSION_NUMBER >= 0x10101000L
  4069. int minv = 0, maxv = 0;
  4070. #endif
  4071. long flags = SSL_OP_ALL;
  4072. int mode;
  4073. #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
  4074. EVP_PKEY* pkey; /* vxWorks compatible */
  4075. #endif
  4076. if (!soap_ssl_init_done)
  4077. soap_ssl_init();
  4078. ERR_clear_error();
  4079. if (!soap->ctx)
  4080. {
  4081. #if OPENSSL_VERSION_NUMBER >= 0x10100000L
  4082. /* TLS_method: a TLS/SSL connection established may understand the SSLv3, TLSv1, TLSv1.1 and TLSv1.2 protocols. */
  4083. soap->ctx = SSL_CTX_new(TLS_method());
  4084. #else
  4085. /* SSLv23_method: a TLS/SSL connection established may understand the SSLv3, TLSv1, TLSv1.1 and TLSv1.2 protocols. */
  4086. soap->ctx = SSL_CTX_new(SSLv23_method());
  4087. #endif
  4088. if (!soap->ctx)
  4089. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't setup context", SOAP_SSL_ERROR);
  4090. /* The following alters the behavior of SSL read/write: */
  4091. #if 0
  4092. SSL_CTX_set_mode(soap->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY);
  4093. #endif
  4094. }
  4095. if (soap->randfile)
  4096. {
  4097. if (!RAND_load_file(soap->randfile, -1))
  4098. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't load randomness", SOAP_SSL_ERROR);
  4099. }
  4100. if (soap->cafile || soap->capath)
  4101. {
  4102. if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath))
  4103. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA PEM file", SOAP_SSL_ERROR);
  4104. if (soap->cafile && (soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
  4105. SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile));
  4106. }
  4107. if (!(soap->ssl_flags & SOAP_SSL_NO_DEFAULT_CA_PATH))
  4108. {
  4109. if (!SSL_CTX_set_default_verify_paths(soap->ctx))
  4110. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read default CA PEM file and/or directory", SOAP_SSL_ERROR);
  4111. }
  4112. if (soap->crlfile)
  4113. {
  4114. if (soap_ssl_crl(soap, soap->crlfile))
  4115. return soap->error;
  4116. }
  4117. /* This code assumes a typical scenario with key and cert in one PEM file, see alternative code below */
  4118. #if 1
  4119. if (soap->keyfile)
  4120. {
  4121. if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
  4122. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't find or read certificate in private key PEM file", SOAP_SSL_ERROR);
  4123. if (soap->password)
  4124. {
  4125. SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
  4126. SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
  4127. }
  4128. #ifndef WM_SECURE_KEY_STORAGE
  4129. if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
  4130. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read private key PEM file", SOAP_SSL_ERROR);
  4131. #endif
  4132. }
  4133. #else
  4134. /* Suggested alternative approach to check the key file for cert only when cafile==NULL */
  4135. if (soap->password)
  4136. {
  4137. SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
  4138. SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
  4139. }
  4140. if (!soap->cafile)
  4141. {
  4142. if (soap->keyfile)
  4143. {
  4144. if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
  4145. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't find or read certificate in private key PEM file", SOAP_SSL_ERROR);
  4146. if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
  4147. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read private key PEM file", SOAP_SSL_ERROR);
  4148. }
  4149. }
  4150. else /* use cafile for (server) cert and keyfile for (server) key */
  4151. {
  4152. if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile))
  4153. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA PEM file", SOAP_SSL_ERROR);
  4154. if (soap->keyfile)
  4155. if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
  4156. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read private key PEM file", SOAP_SSL_ERROR);
  4157. }
  4158. #endif
  4159. #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
  4160. /* vxWorks compatible */
  4161. pkey = ipcom_key_db_pkey_get(soap->keyid);
  4162. if (!pkey)
  4163. return soap_set_receiver_error(soap, "SSL error", "Can't find key", SOAP_SSL_ERROR);
  4164. if (!SSL_CTX_use_PrivateKey(soap->ctx, pkey))
  4165. return soap_set_receiver_error(soap, "SSL error", "Can't read key", SOAP_SSL_ERROR);
  4166. #endif
  4167. if ((soap->ssl_flags & SOAP_SSL_RSA))
  4168. {
  4169. #if OPENSSL_VERSION_NUMBER >= 0x10002000L
  4170. if (SSL_CTX_need_tmp_RSA(soap->ctx))
  4171. {
  4172. unsigned long e = RSA_F4;
  4173. BIGNUM *bne = BN_new();
  4174. RSA *rsa = RSA_new();
  4175. 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))
  4176. {
  4177. if (bne)
  4178. BN_free(bne);
  4179. if (rsa)
  4180. RSA_free(rsa);
  4181. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't generate RSA key", SOAP_SSL_ERROR);
  4182. }
  4183. BN_free(bne);
  4184. RSA_free(rsa);
  4185. }
  4186. #else
  4187. RSA *rsa = RSA_generate_key(SOAP_SSL_RSA_BITS, RSA_F4, NULL, NULL);
  4188. if (!rsa || !SSL_CTX_set_tmp_rsa(soap->ctx, rsa))
  4189. {
  4190. if (rsa)
  4191. RSA_free(rsa);
  4192. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't generate RSA key", SOAP_SSL_ERROR);
  4193. }
  4194. RSA_free(rsa);
  4195. #endif
  4196. }
  4197. else if (soap->dhfile)
  4198. {
  4199. DH *dh = NULL;
  4200. char *s;
  4201. int n = (int)soap_strtoul(soap->dhfile, &s, 10);
  4202. /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
  4203. if (n >= 512 && s && *s == '\0')
  4204. {
  4205. #if OPENSSL_VERSION_NUMBER >= 0x10002000L
  4206. dh = DH_new();
  4207. if (!DH_generate_parameters_ex(dh, n, 2/*or 5*/, NULL))
  4208. {
  4209. DH_free(dh);
  4210. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't generate DH parameters", SOAP_SSL_ERROR);
  4211. }
  4212. #elif defined(VXWORKS)
  4213. dh = DH_new();
  4214. DH_generate_parameters_ex(dh, n, 2/*or 5*/, NULL);
  4215. #else
  4216. dh = DH_generate_parameters(n, 2/*or 5*/, NULL, NULL);
  4217. #endif
  4218. }
  4219. else
  4220. {
  4221. BIO *bio;
  4222. bio = BIO_new_file(soap->dhfile, "r");
  4223. if (!bio)
  4224. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read DH PEM file", SOAP_SSL_ERROR);
  4225. dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
  4226. BIO_free(bio);
  4227. }
  4228. if (!dh || DH_check(dh, &n) != 1 || SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0)
  4229. {
  4230. if (dh)
  4231. DH_free(dh);
  4232. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set DH parameters", SOAP_SSL_ERROR);
  4233. }
  4234. DH_free(dh);
  4235. }
  4236. /* enable all TSLv1 protocols and disable SSLv3 by default if no SSL/TLS flags are set */
  4237. if (!(soap->ssl_flags & SOAP_SSLv3_TLSv1))
  4238. soap->ssl_flags = SOAP_TLSv1;
  4239. #if OPENSSL_VERSION_NUMBER >= 0x10101000L
  4240. if ((soap->ssl_flags & SOAP_SSLv3))
  4241. minv = SSL3_VERSION;
  4242. else if ((soap->ssl_flags & SOAP_TLSv1_0))
  4243. minv = TLS1_VERSION;
  4244. else if ((soap->ssl_flags & SOAP_TLSv1_1))
  4245. minv = TLS1_1_VERSION;
  4246. else if ((soap->ssl_flags & SOAP_TLSv1_2))
  4247. minv = TLS1_2_VERSION;
  4248. else if ((soap->ssl_flags & SOAP_TLSv1_3))
  4249. minv = TLS1_3_VERSION;
  4250. if ((soap->ssl_flags & SOAP_TLSv1_3) && OpenSSL_version_num() >= 0x10101000L)
  4251. maxv = TLS1_3_VERSION;
  4252. else if ((soap->ssl_flags & SOAP_TLSv1_2))
  4253. maxv = TLS1_2_VERSION;
  4254. else if ((soap->ssl_flags & SOAP_TLSv1_1))
  4255. maxv = TLS1_1_VERSION;
  4256. else if ((soap->ssl_flags & SOAP_TLSv1_0))
  4257. maxv = TLS1_VERSION;
  4258. else
  4259. maxv = SSL3_VERSION;
  4260. if (!SSL_CTX_set_min_proto_version(soap->ctx, minv)
  4261. || !SSL_CTX_set_max_proto_version(soap->ctx, maxv))
  4262. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set protocol version", SOAP_SSL_ERROR);
  4263. #else
  4264. /* disable SSL v2 by default and enable specific protos */
  4265. flags = SSL_OP_NO_SSLv2;
  4266. if (!(soap->ssl_flags & SOAP_SSLv3))
  4267. flags |= SSL_OP_NO_SSLv3;
  4268. #if OPENSSL_VERSION_NUMBER >= 0x10001000L
  4269. if (!(soap->ssl_flags & SOAP_TLSv1_0))
  4270. flags |= SSL_OP_NO_TLSv1;
  4271. if (!(soap->ssl_flags & SOAP_TLSv1_1))
  4272. flags |= SSL_OP_NO_TLSv1_1;
  4273. if (!(soap->ssl_flags & SOAP_TLSv1_2))
  4274. flags |= SSL_OP_NO_TLSv1_2;
  4275. #endif
  4276. #endif
  4277. #ifdef SSL_OP_NO_TICKET
  4278. /* TLS extension is enabled by default in OPENSSL v0.9.8k disable it by */
  4279. flags |= SSL_OP_NO_TICKET;
  4280. #endif
  4281. SSL_CTX_set_options(soap->ctx, flags);
  4282. if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
  4283. mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
  4284. else if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
  4285. mode = SSL_VERIFY_PEER;
  4286. else
  4287. mode = SSL_VERIFY_NONE;
  4288. SSL_CTX_set_verify(soap->ctx, mode, soap->fsslverify);
  4289. #if OPENSSL_VERSION_NUMBER < 0x00905100L
  4290. SSL_CTX_set_verify_depth(soap->ctx, 1);
  4291. #else
  4292. SSL_CTX_set_verify_depth(soap->ctx, 9);
  4293. #endif
  4294. #endif
  4295. #ifdef WITH_GNUTLS
  4296. int ret;
  4297. char priority[80];
  4298. soap_strcpy(priority, sizeof(priority), "PERFORMANCE");
  4299. if (!soap_ssl_init_done)
  4300. soap_ssl_init();
  4301. if (!soap->xcred)
  4302. {
  4303. if (gnutls_certificate_allocate_credentials(&soap->xcred) != GNUTLS_E_SUCCESS)
  4304. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't allocate credentials or trust", SOAP_SSL_ERROR);
  4305. #if GNUTLS_VERSION_NUMBER >= 0x030300
  4306. gnutls_certificate_set_x509_system_trust(soap->xcred);
  4307. #endif
  4308. if (soap->cafile)
  4309. {
  4310. if (gnutls_certificate_set_x509_trust_file(soap->xcred, soap->cafile, GNUTLS_X509_FMT_PEM) < 0)
  4311. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA PEM file", SOAP_SSL_ERROR);
  4312. }
  4313. if (soap->crlfile)
  4314. {
  4315. if (soap_ssl_crl(soap, soap->crlfile))
  4316. return soap->error;
  4317. }
  4318. if (soap->keyfile)
  4319. {
  4320. 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 */
  4321. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read private key PEM file", SOAP_SSL_ERROR);
  4322. }
  4323. }
  4324. if ((soap->ssl_flags & SOAP_SSL_CLIENT))
  4325. {
  4326. gnutls_init(&soap->session, GNUTLS_CLIENT);
  4327. if (soap->cafile || soap->crlfile || soap->keyfile)
  4328. {
  4329. ret = gnutls_priority_set_direct(soap->session, "PERFORMANCE", NULL);
  4330. if (ret != GNUTLS_E_SUCCESS)
  4331. return soap_set_receiver_error(soap, soap_ssl_error(soap, ret, 0), "SSL/TLS set priority error", SOAP_SSL_ERROR);
  4332. gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred);
  4333. }
  4334. else
  4335. {
  4336. if (!soap->acred)
  4337. gnutls_anon_allocate_client_credentials(&soap->acred);
  4338. ret = gnutls_priority_set_direct(soap->session, "PERFORMANCE:+ANON-DH:!ARCFOUR-128", NULL);
  4339. if (ret != GNUTLS_E_SUCCESS)
  4340. return soap_set_receiver_error(soap, soap_ssl_error(soap, ret, 0), "SSL/TLS set priority error", SOAP_SSL_ERROR);
  4341. gnutls_credentials_set(soap->session, GNUTLS_CRD_ANON, soap->acred);
  4342. }
  4343. }
  4344. else if (!soap->keyfile)
  4345. {
  4346. return soap_set_receiver_error(soap, "SSL/TLS error", "No key file: anonymous server authentication not supported in this release", SOAP_SSL_ERROR);
  4347. }
  4348. else
  4349. {
  4350. #if GNUTLS_VERSION_NUMBER < 0x030300
  4351. int protocol_priority[] = { 0, 0, 0, 0, 0 };
  4352. int *protocol = protocol_priority;
  4353. if ((soap->ssl_flags & SOAP_SSL_RSA) && soap->rsa_params)
  4354. gnutls_certificate_set_rsa_export_params(soap->xcred, soap->rsa_params);
  4355. #endif
  4356. if (!(soap->ssl_flags & SOAP_SSL_RSA) && soap->dh_params)
  4357. gnutls_certificate_set_dh_params(soap->xcred, soap->dh_params);
  4358. if (!soap->cache)
  4359. gnutls_priority_init(&soap->cache, "NORMAL", NULL);
  4360. gnutls_init(&soap->session, GNUTLS_SERVER);
  4361. gnutls_priority_set(soap->session, soap->cache);
  4362. gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred);
  4363. if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
  4364. gnutls_certificate_server_set_request(soap->session, GNUTLS_CERT_REQUEST);
  4365. gnutls_session_enable_compatibility_mode(soap->session);
  4366. /* enable all TSLv1 protocols and disable SSLv3 by default if no SSL/TLS flags are set */
  4367. if (!(soap->ssl_flags & SOAP_SSLv3_TLSv1))
  4368. soap->ssl_flags = SOAP_TLSv1;
  4369. #if GNUTLS_VERSION_NUMBER < 0x030300
  4370. if ((soap->ssl_flags & SOAP_SSLv3))
  4371. *protocol++ = GNUTLS_SSL3;
  4372. if ((soap->ssl_flags & SOAP_TLSv1_0))
  4373. *protocol++ = GNUTLS_TLS1_0;
  4374. if ((soap->ssl_flags & SOAP_TLSv1_1))
  4375. *protocol++ = GNUTLS_TLS1_1;
  4376. if ((soap->ssl_flags & SOAP_TLSv1_2))
  4377. *protocol++ = GNUTLS_TLS1_2;
  4378. if (gnutls_protocol_set_priority(soap->session, protocol_priority) != GNUTLS_E_SUCCESS)
  4379. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set protocol", SOAP_SSL_ERROR);
  4380. #else
  4381. soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "NORMAL:+VERS-ALL");
  4382. if (!(soap->ssl_flags & SOAP_TLSv1_0))
  4383. soap_strcat(soap->tmpbuf, sizeof(soap->tmpbuf), ":-VERS-TLS1.0");
  4384. if (!(soap->ssl_flags & SOAP_TLSv1_1))
  4385. soap_strcat(soap->tmpbuf, sizeof(soap->tmpbuf), ":-VERS-TLS1.1");
  4386. if (!(soap->ssl_flags & SOAP_TLSv1_2))
  4387. soap_strcat(soap->tmpbuf, sizeof(soap->tmpbuf), ":-VERS-TLS1.2");
  4388. if (gnutls_priority_set_direct(soap->session, soap->tmpbuf, NULL) != GNUTLS_E_SUCCESS)
  4389. return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set protocol priority", SOAP_SSL_ERROR);
  4390. #endif
  4391. }
  4392. #endif
  4393. #ifdef WITH_SYSTEMSSL
  4394. if (!soap->ctx)
  4395. {
  4396. int err;
  4397. err = gsk_environment_open(&soap->ctx);
  4398. if (err == GSK_OK)
  4399. err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_SSLV2, GSK_PROTOCOL_SSLV2_OFF);
  4400. /* enable all TSLv1 protocols and disable SSLv3 by default if no SSL/TLS flags are set */
  4401. if (!(soap->ssl_flags & SOAP_SSLv3_TLSv1))
  4402. soap->ssl_flags = SOAP_TLSv1;
  4403. if (err == GSK_OK)
  4404. {
  4405. if ((soap->ssl_flags & SOAP_SSLv3))
  4406. err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_SSLV3, GSK_PROTOCOL_SSLV3_ON);
  4407. else
  4408. err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_SSLV3, GSK_PROTOCOL_SSLV3_OFF);
  4409. }
  4410. if (err == GSK_OK)
  4411. {
  4412. if ((soap->ssl_flags & SOAP_TLSv1_0))
  4413. err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_ON);
  4414. else
  4415. err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_OFF);
  4416. }
  4417. if (err == GSK_OK)
  4418. {
  4419. if ((soap->ssl_flags & SOAP_TLSv1_1))
  4420. err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_1_ON);
  4421. else
  4422. err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_1_OFF);
  4423. }
  4424. if (err == GSK_OK)
  4425. {
  4426. if ((soap->ssl_flags & SOAP_TLSv1_2))
  4427. err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_2_ON);
  4428. else
  4429. err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_2_OFF);
  4430. }
  4431. if (err == GSK_OK)
  4432. err = gsk_attribute_set_buffer(soap->ctx, GSK_KEYRING_FILE, soap->keyfile, 0); /* keyfile is a keyring .kdb file */
  4433. if (err == GSK_OK)
  4434. err = gsk_attribute_set_buffer(soap->ctx, GSK_KEYRING_PW, soap->password, 0); /* locked by password */
  4435. if (err == GSK_OK)
  4436. err = gsk_environment_init(soap->ctx);
  4437. if (err != GSK_OK)
  4438. return soap_set_receiver_error(soap, gsk_strerror(err), "SYSTEM SSL error in ssl_auth_init()", SOAP_SSL_ERROR);
  4439. }
  4440. #endif
  4441. return SOAP_OK;
  4442. }
  4443. #endif
  4444. /******************************************************************************/
  4445. #ifdef WITH_OPENSSL
  4446. static int
  4447. ssl_password(char *buf, int num, int rwflag, void *userdata)
  4448. {
  4449. (void)rwflag;
  4450. if (!buf || !userdata)
  4451. return 0;
  4452. soap_strcpy(buf, (size_t)num, (char*)userdata);
  4453. return (int)strlen(buf);
  4454. }
  4455. #endif
  4456. /******************************************************************************/
  4457. #ifdef WITH_OPENSSL
  4458. static int
  4459. ssl_verify_callback(int ok, X509_STORE_CTX *store)
  4460. {
  4461. (void)store;
  4462. #ifdef SOAP_DEBUG
  4463. if (!ok)
  4464. {
  4465. char buf[1024];
  4466. int err = X509_STORE_CTX_get_error(store);
  4467. X509 *cert = X509_STORE_CTX_get_current_cert(store);
  4468. 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));
  4469. X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf)-1);
  4470. fprintf(stderr, " certificate issuer: %s\n", buf);
  4471. X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)-1);
  4472. fprintf(stderr, " certificate subject: %s\n", buf);
  4473. /* accept self-signed certificates and certificates out of date */
  4474. switch (err)
  4475. {
  4476. case X509_V_ERR_CERT_NOT_YET_VALID:
  4477. case X509_V_ERR_CERT_HAS_EXPIRED:
  4478. case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
  4479. case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
  4480. case X509_V_ERR_UNABLE_TO_GET_CRL:
  4481. case X509_V_ERR_CRL_NOT_YET_VALID:
  4482. case X509_V_ERR_CRL_HAS_EXPIRED:
  4483. X509_STORE_CTX_set_error(store, X509_V_OK);
  4484. ok = 1;
  4485. 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");
  4486. }
  4487. }
  4488. #endif
  4489. /* Note: return 1 to try to continue, but unsafe progress will be terminated by OpenSSL */
  4490. return ok;
  4491. }
  4492. #endif
  4493. /******************************************************************************/
  4494. #ifdef WITH_OPENSSL
  4495. static int
  4496. ssl_verify_callback_allow_expired_certificate(int ok, X509_STORE_CTX *store)
  4497. {
  4498. ok = ssl_verify_callback(ok, store);
  4499. if (!ok)
  4500. {
  4501. /* accept self signed certificates, expired certificates, and certficiates w/o CRL */
  4502. switch (X509_STORE_CTX_get_error(store))
  4503. {
  4504. case X509_V_ERR_CERT_NOT_YET_VALID:
  4505. case X509_V_ERR_CERT_HAS_EXPIRED:
  4506. case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
  4507. case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
  4508. case X509_V_ERR_UNABLE_TO_GET_CRL:
  4509. case X509_V_ERR_CRL_NOT_YET_VALID:
  4510. case X509_V_ERR_CRL_HAS_EXPIRED:
  4511. X509_STORE_CTX_set_error(store, X509_V_OK);
  4512. ok = 1;
  4513. }
  4514. }
  4515. /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
  4516. return ok;
  4517. }
  4518. #endif
  4519. /******************************************************************************/
  4520. #ifdef WITH_GNUTLS
  4521. static const char *
  4522. ssl_verify(struct soap *soap, const char *host)
  4523. {
  4524. unsigned int status;
  4525. const char *err = NULL;
  4526. int r = gnutls_certificate_verify_peers2(soap->session, &status);
  4527. if (r < 0)
  4528. err = "Certificate verify error";
  4529. else if ((status & GNUTLS_CERT_INVALID))
  4530. err = "The certificate is not trusted";
  4531. else if ((status & GNUTLS_CERT_SIGNER_NOT_FOUND))
  4532. err = "The certificate hasn't got a known issuer";
  4533. else if ((status & GNUTLS_CERT_REVOKED))
  4534. err = "The certificate has been revoked";
  4535. else if (gnutls_certificate_type_get(soap->session) == GNUTLS_CRT_X509)
  4536. {
  4537. gnutls_x509_crt_t cert;
  4538. const gnutls_datum_t *cert_list;
  4539. unsigned int cert_list_size;
  4540. if (gnutls_x509_crt_init(&cert) < 0)
  4541. err = "Could not get X509 certificates";
  4542. else if ((cert_list = gnutls_certificate_get_peers(soap->session, &cert_list_size)) == NULL)
  4543. err = "Could not get X509 certificates";
  4544. else if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
  4545. err = "Error parsing X509 certificate";
  4546. else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_expiration_time(cert) < time(NULL))
  4547. err = "The certificate has expired";
  4548. else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_activation_time(cert) > time(NULL))
  4549. err = "The certificate is not yet activated";
  4550. else if (host && !(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK))
  4551. {
  4552. if (!gnutls_x509_crt_check_hostname(cert, host))
  4553. err = "Certificate host name mismatch";
  4554. }
  4555. gnutls_x509_crt_deinit(cert);
  4556. }
  4557. return err;
  4558. }
  4559. #endif
  4560. /******************************************************************************/
  4561. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
  4562. #ifndef WITH_NOIO
  4563. SOAP_FMAC1
  4564. int
  4565. SOAP_FMAC2
  4566. soap_ssl_accept(struct soap *soap)
  4567. {
  4568. SOAP_SOCKET sk = soap->socket;
  4569. #ifdef WITH_OPENSSL
  4570. BIO *bio;
  4571. int err = SSL_ERROR_NONE;
  4572. int retries, r, s;
  4573. ERR_clear_error();
  4574. if (!soap_valid_socket(sk))
  4575. return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
  4576. soap->ssl_flags &= ~SOAP_SSL_CLIENT;
  4577. if (!soap->ctx && (soap->error = soap->fsslauth(soap)) != SOAP_OK)
  4578. return soap_closesock(soap);
  4579. if (!soap->ssl)
  4580. {
  4581. soap->ssl = SSL_new(soap->ctx);
  4582. if (!soap->ssl)
  4583. {
  4584. soap_closesock(soap);
  4585. return soap_set_receiver_error(soap, "SSL/TLS error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
  4586. }
  4587. }
  4588. else
  4589. {
  4590. SSL_clear(soap->ssl);
  4591. }
  4592. bio = BIO_new_socket((int)sk, BIO_NOCLOSE);
  4593. SSL_set_bio(soap->ssl, bio, bio);
  4594. /* Default timeout: 10 sec retries, 100 times 0.1 sec */
  4595. retries = 100;
  4596. if (soap->recv_timeout || soap->send_timeout)
  4597. {
  4598. int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout;
  4599. if (t > 0)
  4600. retries = 10 * t;
  4601. else if (t > -100000)
  4602. retries = 1;
  4603. else
  4604. retries = t/-100000;
  4605. }
  4606. SOAP_SOCKNONBLOCK(sk)
  4607. while ((r = SSL_accept(soap->ssl)) <= 0)
  4608. {
  4609. err = SSL_get_error(soap->ssl, r);
  4610. if (err == SSL_ERROR_WANT_ACCEPT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
  4611. {
  4612. if (err == SSL_ERROR_WANT_READ)
  4613. s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
  4614. else
  4615. s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
  4616. if (s < 0)
  4617. break;
  4618. }
  4619. else
  4620. {
  4621. soap->errnum = soap_socket_errno(sk);
  4622. break;
  4623. }
  4624. if (retries-- <= 0)
  4625. break;
  4626. }
  4627. if (!soap->recv_timeout && !soap->send_timeout)
  4628. SOAP_SOCKBLOCK(sk)
  4629. if (r <= 0)
  4630. {
  4631. soap_set_receiver_error(soap, soap_ssl_error(soap, r, err), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
  4632. return soap_closesock(soap);
  4633. }
  4634. if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
  4635. {
  4636. X509 *peer;
  4637. int err;
  4638. if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
  4639. {
  4640. soap_closesock(soap);
  4641. 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);
  4642. }
  4643. peer = SSL_get_peer_certificate(soap->ssl);
  4644. if (!peer)
  4645. {
  4646. soap_closesock(soap);
  4647. return soap_set_sender_error(soap, "SSL/TLS error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR);
  4648. }
  4649. X509_free(peer);
  4650. }
  4651. #endif
  4652. #ifdef WITH_GNUTLS
  4653. int retries, r, s;
  4654. if (!soap_valid_socket(sk))
  4655. return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
  4656. soap->ssl_flags &= ~SOAP_SSL_CLIENT;
  4657. if (!soap->session && (soap->error = soap->fsslauth(soap)) != SOAP_OK)
  4658. return soap_closesock(soap);
  4659. gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)sk);
  4660. /* default timeout: 10 sec retries, 100 times 0.1 sec */
  4661. retries = 100;
  4662. if (soap->recv_timeout || soap->send_timeout)
  4663. {
  4664. int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout;
  4665. if (t > 0)
  4666. retries = 10 * t;
  4667. else if (t > -100000)
  4668. retries = 1;
  4669. else
  4670. retries = t/-100000;
  4671. }
  4672. SOAP_SOCKNONBLOCK(sk)
  4673. while ((r = gnutls_handshake(soap->session)))
  4674. {
  4675. /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */
  4676. if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED)
  4677. {
  4678. if (!gnutls_record_get_direction(soap->session))
  4679. s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
  4680. else
  4681. s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
  4682. if (s < 0)
  4683. break;
  4684. }
  4685. else
  4686. {
  4687. soap->errnum = soap_socket_errno(sk);
  4688. break;
  4689. }
  4690. if (retries-- <= 0)
  4691. break;
  4692. }
  4693. if (!soap->recv_timeout && !soap->send_timeout)
  4694. SOAP_SOCKBLOCK(sk)
  4695. if (r)
  4696. {
  4697. soap_set_receiver_error(soap, soap_ssl_error(soap, r, 0), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
  4698. return soap_closesock(soap);
  4699. }
  4700. if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
  4701. {
  4702. const char *err = ssl_verify(soap, NULL);
  4703. if (err)
  4704. {
  4705. soap_closesock(soap);
  4706. return soap_set_receiver_error(soap, "SSL/TLS error", err, SOAP_SSL_ERROR);
  4707. }
  4708. }
  4709. #endif
  4710. #ifdef WITH_SYSTEMSSL
  4711. gsk_iocallback local_io = { ssl_recv, ssl_send, NULL, NULL, NULL, NULL };
  4712. int retries, r, s;
  4713. if (!soap_valid_socket(sk))
  4714. return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
  4715. soap->ssl_flags &= ~SOAP_SSL_CLIENT;
  4716. /* default timeout: 10 sec retries, 100 times 0.1 sec */
  4717. retries = 100;
  4718. if (soap->recv_timeout || soap->send_timeout)
  4719. {
  4720. int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout;
  4721. if (t > 0)
  4722. retries = 10 * t;
  4723. else if (t > -100000)
  4724. retries = 1;
  4725. else
  4726. retries = t/-100000;
  4727. }
  4728. SOAP_SOCKNONBLOCK(sk)
  4729. r = gsk_secure_socket_open(soap->ctx, &soap->ssl);
  4730. if (r == GSK_OK)
  4731. r = gsk_attribute_set_numeric_value(soap->ssl, GSK_FD, sk);
  4732. if (r == GSK_OK)
  4733. r = gsk_attribute_set_buffer(soap->ssl, GSK_KEYRING_LABEL, soap->cafile, 0);
  4734. if (r == GSK_OK)
  4735. r = gsk_attribute_set_enum(soap->ssl, GSK_SESSION_TYPE, GSK_SERVER_SESSION);
  4736. if (r == GSK_OK)
  4737. r = gsk_attribute_set_buffer(soap->ssl, GSK_V3_CIPHER_SPECS_EXPANDED, "0035002F000A", 0);
  4738. if (r == GSK_OK)
  4739. r = gsk_attribute_set_enum(soap->ssl, GSK_V3_CIPHERS, GSK_V3_CIPHERS_CHAR4);
  4740. if (r == GSK_OK)
  4741. r = gsk_attribute_set_callback(soap->ssl, GSK_IO_CALLBACK, &local_io);
  4742. if (r != GSK_OK)
  4743. return soap_set_receiver_error(soap, gsk_strerror(r), "SYSTEM SSL error in soap_ssl_accept()", SOAP_SSL_ERROR);
  4744. while ((r = gsk_secure_socket_init(soap->ssl)) != GSK_OK)
  4745. {
  4746. if (r == GSK_WOULD_BLOCK_READ || r == GSK_WOULD_BLOCK_WRITE)
  4747. {
  4748. if (r == GSK_WOULD_BLOCK_READ)
  4749. s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
  4750. else
  4751. s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
  4752. if (s < 0)
  4753. break;
  4754. }
  4755. else
  4756. {
  4757. soap->errnum = soap_socket_errno(sk);
  4758. break;
  4759. }
  4760. if (retries-- <= 0)
  4761. break;
  4762. }
  4763. if (!soap->recv_timeout && !soap->send_timeout)
  4764. SOAP_SOCKBLOCK(sk)
  4765. if (r != GSK_OK)
  4766. {
  4767. soap_set_receiver_error(soap, gsk_strerror(r), "gsk_secure_socket_init() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
  4768. return soap_closesock(soap);
  4769. }
  4770. #endif
  4771. soap->imode |= SOAP_ENC_SSL;
  4772. soap->omode |= SOAP_ENC_SSL;
  4773. return SOAP_OK;
  4774. }
  4775. #endif
  4776. #endif
  4777. /******************************************************************************\
  4778. *
  4779. * TCP/UDP [SSL/TLS] IPv4 and IPv6
  4780. *
  4781. \******************************************************************************/
  4782. #ifndef WITH_NOIO
  4783. static int
  4784. tcp_init(struct soap *soap)
  4785. {
  4786. soap->errmode = 1;
  4787. #ifdef WIN32
  4788. if (tcp_done)
  4789. return 0;
  4790. else
  4791. {
  4792. WSADATA w;
  4793. if (WSAStartup(MAKEWORD(1, 1), &w))
  4794. return -1;
  4795. tcp_done = 1;
  4796. }
  4797. #endif
  4798. return 0;
  4799. }
  4800. #endif
  4801. /******************************************************************************/
  4802. #ifndef WITH_NOIO
  4803. static const char*
  4804. tcp_error(struct soap *soap)
  4805. {
  4806. const char *msg = NULL;
  4807. switch (soap->errmode)
  4808. {
  4809. case 0:
  4810. msg = soap_strerror(soap);
  4811. break;
  4812. case 1:
  4813. msg = "WSAStartup failed";
  4814. break;
  4815. case 2:
  4816. {
  4817. #ifndef WITH_LEAN
  4818. msg = soap_code_str(h_error_codes, soap->errnum);
  4819. if (!msg)
  4820. #endif
  4821. {
  4822. (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), 37), "TCP/UDP IP error %d", soap->errnum);
  4823. msg = soap->msgbuf;
  4824. }
  4825. }
  4826. }
  4827. return msg;
  4828. }
  4829. #endif
  4830. /******************************************************************************/
  4831. #if !defined(WITH_IPV6) || defined(WITH_COOKIES)
  4832. #ifndef WITH_NOIO
  4833. static int
  4834. tcp_gethostbyname(struct soap *soap, const char *addr, struct hostent *hostent, struct in_addr *inaddr)
  4835. {
  4836. #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__)))
  4837. int r;
  4838. char *tmpbuf = soap->tmpbuf;
  4839. size_t tmplen = sizeof(soap->tmpbuf);
  4840. #elif (defined(_AIX43) || defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R)
  4841. struct hostent_data ht_data;
  4842. #elif defined(HAVE_GETHOSTBYNAME_R)
  4843. char *tmpbuf = soap->tmpbuf;
  4844. size_t tmplen = sizeof(soap->tmpbuf);
  4845. #endif
  4846. #ifdef VXWORKS
  4847. int hostint; /* vxWorks compatible */
  4848. #endif
  4849. if (inaddr)
  4850. {
  4851. soap_int32 iadd = -1;
  4852. #ifdef AS400
  4853. iadd = inet_addr((void*)addr);
  4854. #else
  4855. iadd = inet_addr((char*)addr);
  4856. #endif
  4857. if (iadd != -1)
  4858. {
  4859. if (soap_memcpy((void*)inaddr, sizeof(struct in_addr), (const void*)&iadd, sizeof(iadd)))
  4860. return soap->error = SOAP_EOM;
  4861. return SOAP_OK;
  4862. }
  4863. }
  4864. #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__)))
  4865. while ((r = gethostbyname_r(addr, hostent, tmpbuf, tmplen, &hostent, &soap->errnum)) < 0)
  4866. {
  4867. if (tmpbuf != soap->tmpbuf)
  4868. SOAP_FREE(soap, tmpbuf);
  4869. if (r != SOAP_ERANGE)
  4870. {
  4871. hostent = NULL;
  4872. break;
  4873. }
  4874. tmplen *= 2;
  4875. tmpbuf = (char*)SOAP_MALLOC(soap, tmplen);
  4876. if (!tmpbuf)
  4877. break;
  4878. }
  4879. #elif (defined(_AIX43) || defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R)
  4880. memset((void*)&ht_data, 0, sizeof(ht_data));
  4881. if (gethostbyname_r(addr, hostent, &ht_data) < 0)
  4882. {
  4883. hostent = NULL;
  4884. soap->errnum = h_errno;
  4885. }
  4886. #elif defined(HAVE_GETHOSTBYNAME_R)
  4887. hostent = gethostbyname_r(addr, hostent, tmpbuf, tmplen, &soap->errnum);
  4888. #elif defined(VXWORKS)
  4889. /* vxWorks compatible */
  4890. /* If the DNS resolver library resolvLib has been configured in the vxWorks
  4891. * image, a query for the host IP address is sent to the DNS server, if the
  4892. * name was not found in the local host table. */
  4893. hostint = hostGetByName((char*)addr);
  4894. if (hostint == ERROR)
  4895. {
  4896. hostent = NULL;
  4897. soap->errnum = soap_errno;
  4898. }
  4899. #else
  4900. #ifdef AS400
  4901. hostent = gethostbyname((void*)addr);
  4902. #else
  4903. hostent = gethostbyname((char*)addr);
  4904. #endif
  4905. if (!hostent)
  4906. soap->errnum = h_errno;
  4907. #endif
  4908. if (!hostent)
  4909. {
  4910. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n"));
  4911. return SOAP_ERR;
  4912. }
  4913. if (inaddr)
  4914. {
  4915. #ifdef VXWORKS
  4916. inaddr->s_addr = hostint; /* vxWorks compatible */
  4917. #else
  4918. if (soap_memcpy((void*)inaddr, sizeof(struct in_addr), (const void*)hostent->h_addr, (size_t)hostent->h_length))
  4919. {
  4920. #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__)))
  4921. if (tmpbuf && tmpbuf != soap->tmpbuf)
  4922. SOAP_FREE(soap, tmpbuf);
  4923. #endif
  4924. return soap->error = SOAP_EOM;
  4925. }
  4926. #endif
  4927. }
  4928. #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__)))
  4929. if (tmpbuf && tmpbuf != soap->tmpbuf)
  4930. SOAP_FREE(soap, tmpbuf);
  4931. #endif
  4932. return SOAP_OK;
  4933. }
  4934. #endif
  4935. #endif
  4936. /******************************************************************************/
  4937. #if !defined(WITH_IPV6)
  4938. #ifndef WITH_NOIO
  4939. static int
  4940. tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr)
  4941. {
  4942. struct hostent hostent;
  4943. return tcp_gethostbyname(soap, addr, &hostent, inaddr);
  4944. }
  4945. #endif
  4946. #endif
  4947. /******************************************************************************/
  4948. #ifndef WITH_NOIO
  4949. static SOAP_SOCKET
  4950. tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port)
  4951. {
  4952. #ifdef WITH_IPV6
  4953. struct addrinfo hints, *res, *ressave;
  4954. #endif
  4955. SOAP_SOCKET sk;
  4956. int err = 0;
  4957. #ifndef WITH_LEAN
  4958. int set = 1;
  4959. #endif
  4960. #if !defined(WITH_LEAN) || defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_SYSTEMSSL)
  4961. int retries;
  4962. #endif
  4963. soap->errnum = 0;
  4964. soap->errmode = 0;
  4965. if (soap_valid_socket(soap->socket))
  4966. {
  4967. if ((soap->omode & SOAP_IO_UDP) && soap->socket == soap->master)
  4968. {
  4969. #ifdef IP_MULTICAST_TTL
  4970. #ifndef WITH_IPV6
  4971. soap->errmode = 2;
  4972. if (soap->fresolve(soap, host, &soap->peer.in.sin_addr))
  4973. {
  4974. soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR);
  4975. soap->fclosesocket(soap, soap->socket);
  4976. return soap->socket = SOAP_INVALID_SOCKET;
  4977. }
  4978. soap->peer.in.sin_port = htons((short)port);
  4979. soap->errmode = 0;
  4980. #else
  4981. if (getaddrinfo(host, soap_int2s(soap, port), &hints, &res) || !res)
  4982. {
  4983. soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR);
  4984. soap->fclosesocket(soap, soap->socket);
  4985. return soap->socket = SOAP_INVALID_SOCKET;
  4986. }
  4987. if (soap_memcpy((void*)&soap->peer.storage, sizeof(soap->peer.storage), (const void*)res->ai_addr, res->ai_addrlen))
  4988. {
  4989. soap->error = SOAP_EOM;
  4990. soap->fclosesocket(soap, soap->socket);
  4991. freeaddrinfo(res);
  4992. return soap->socket = SOAP_INVALID_SOCKET;
  4993. }
  4994. soap->peerlen = res->ai_addrlen;
  4995. freeaddrinfo(res);
  4996. #endif
  4997. if (soap->ipv4_multicast_ttl)
  4998. {
  4999. unsigned char ttl = soap->ipv4_multicast_ttl;
  5000. if (setsockopt(soap->socket, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl)))
  5001. {
  5002. soap->errnum = soap_socket_errno(soap->socket);
  5003. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR);
  5004. soap->fclosesocket(soap, soap->socket);
  5005. return soap->socket = SOAP_INVALID_SOCKET;
  5006. }
  5007. }
  5008. if (soap->ipv4_multicast_if && !soap->ipv6_multicast_if)
  5009. {
  5010. if (setsockopt(soap->socket, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
  5011. #ifndef WINDOWS
  5012. {
  5013. soap->errnum = soap_socket_errno(soap->socket);
  5014. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
  5015. soap->fclosesocket(soap, soap->socket);
  5016. return soap->socket = SOAP_INVALID_SOCKET;
  5017. }
  5018. #else
  5019. #ifndef IP_MULTICAST_IF
  5020. #define IP_MULTICAST_IF 2
  5021. #endif
  5022. if (setsockopt(soap->socket, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
  5023. {
  5024. soap->errnum = soap_socket_errno(soap->socket);
  5025. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
  5026. soap->fclosesocket(soap, soap->socket);
  5027. return soap->socket = SOAP_INVALID_SOCKET;
  5028. }
  5029. #endif
  5030. }
  5031. #endif
  5032. return soap->socket;
  5033. }
  5034. soap->fclosesocket(soap, soap->socket);
  5035. soap->socket = SOAP_INVALID_SOCKET;
  5036. }
  5037. if (tcp_init(soap))
  5038. {
  5039. soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR);
  5040. return SOAP_INVALID_SOCKET;
  5041. }
  5042. soap->errmode = 0;
  5043. #ifdef WITH_IPV6
  5044. memset((void*)&hints, 0, sizeof(hints));
  5045. hints.ai_family = PF_UNSPEC;
  5046. #ifndef WITH_LEAN
  5047. if ((soap->omode & SOAP_IO_UDP))
  5048. hints.ai_socktype = SOCK_DGRAM;
  5049. else
  5050. #endif
  5051. hints.ai_socktype = SOCK_STREAM;
  5052. soap->errmode = 2;
  5053. if (soap->proxy_host)
  5054. err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res);
  5055. else
  5056. err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res);
  5057. if (err || !res)
  5058. {
  5059. soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR);
  5060. return SOAP_INVALID_SOCKET;
  5061. }
  5062. ressave = res;
  5063. again:
  5064. sk = soap->socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
  5065. soap->error = SOAP_OK;
  5066. soap->errmode = 0;
  5067. #else
  5068. #ifndef WITH_LEAN
  5069. again:
  5070. #endif
  5071. #ifndef WITH_LEAN
  5072. if ((soap->omode & SOAP_IO_UDP))
  5073. sk = soap->socket = socket(AF_INET, SOCK_DGRAM, 0);
  5074. else
  5075. #endif
  5076. sk = soap->socket = socket(AF_INET, SOCK_STREAM, 0);
  5077. #endif
  5078. if (!soap_valid_socket(sk))
  5079. {
  5080. #ifdef WITH_IPV6
  5081. if (res->ai_next)
  5082. {
  5083. res = res->ai_next;
  5084. goto again;
  5085. }
  5086. #endif
  5087. soap->errnum = soap_socket_errno(sk);
  5088. soap_set_receiver_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR);
  5089. #ifdef WITH_IPV6
  5090. freeaddrinfo(ressave);
  5091. #endif
  5092. return SOAP_INVALID_SOCKET;
  5093. }
  5094. #ifdef WITH_SOCKET_CLOSE_ON_EXIT
  5095. #ifdef WIN32
  5096. #ifndef UNDER_CE
  5097. SetHandleInformation((HANDLE)sk, HANDLE_FLAG_INHERIT, 0);
  5098. #endif
  5099. #else
  5100. fcntl(sk, F_SETFD, 1);
  5101. #endif
  5102. #endif
  5103. #ifndef WITH_LEAN
  5104. if ((soap->connect_flags & SO_LINGER))
  5105. {
  5106. struct linger linger;
  5107. memset((void*)&linger, 0, sizeof(linger));
  5108. linger.l_onoff = 1;
  5109. linger.l_linger = soap->linger_time;
  5110. if (setsockopt(sk, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
  5111. {
  5112. soap->errnum = soap_socket_errno(sk);
  5113. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR);
  5114. soap->fclosesocket(soap, sk);
  5115. #ifdef WITH_IPV6
  5116. freeaddrinfo(ressave);
  5117. #endif
  5118. return soap->socket = SOAP_INVALID_SOCKET;
  5119. }
  5120. }
  5121. if ((soap->connect_flags & ~SO_LINGER) && setsockopt(sk, SOL_SOCKET, soap->connect_flags & ~SO_LINGER, (char*)&set, sizeof(int)))
  5122. {
  5123. soap->errnum = soap_socket_errno(sk);
  5124. #ifdef WITH_IPV6
  5125. freeaddrinfo(ressave);
  5126. #endif
  5127. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR);
  5128. soap->fclosesocket(soap, sk);
  5129. return soap->socket = SOAP_INVALID_SOCKET;
  5130. }
  5131. #ifndef UNDER_CE
  5132. if ((soap->keep_alive || soap->tcp_keep_alive) && setsockopt(sk, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
  5133. {
  5134. soap->errnum = soap_socket_errno(sk);
  5135. #ifdef WITH_IPV6
  5136. freeaddrinfo(ressave);
  5137. #endif
  5138. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR);
  5139. soap->fclosesocket(soap, sk);
  5140. return soap->socket = SOAP_INVALID_SOCKET;
  5141. }
  5142. if (soap->sndbuf > 0 && setsockopt(sk, SOL_SOCKET, SO_SNDBUF, (char*)&soap->sndbuf, sizeof(int)))
  5143. {
  5144. soap->errnum = soap_socket_errno(sk);
  5145. #ifdef WITH_IPV6
  5146. freeaddrinfo(ressave);
  5147. #endif
  5148. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR);
  5149. soap->fclosesocket(soap, sk);
  5150. return soap->socket = SOAP_INVALID_SOCKET;
  5151. }
  5152. if (soap->rcvbuf > 0 && setsockopt(sk, SOL_SOCKET, SO_RCVBUF, (char*)&soap->rcvbuf, sizeof(int)))
  5153. {
  5154. soap->errnum = soap_socket_errno(sk);
  5155. #ifdef WITH_IPV6
  5156. freeaddrinfo(ressave);
  5157. #endif
  5158. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR);
  5159. soap->fclosesocket(soap, sk);
  5160. return soap->socket = SOAP_INVALID_SOCKET;
  5161. }
  5162. #ifdef TCP_KEEPIDLE
  5163. if (soap->tcp_keep_idle && setsockopt(sk, IPPROTO_TCP, TCP_KEEPIDLE, (char*)&(soap->tcp_keep_idle), sizeof(int)))
  5164. {
  5165. soap->errnum = soap_socket_errno(sk);
  5166. #ifdef WITH_IPV6
  5167. freeaddrinfo(ressave);
  5168. #endif
  5169. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_KEEPIDLE failed in tcp_connect()", SOAP_TCP_ERROR);
  5170. soap->fclosesocket(soap, sk);
  5171. return soap->socket = SOAP_INVALID_SOCKET;
  5172. }
  5173. #endif
  5174. #ifdef TCP_KEEPINTVL
  5175. if (soap->tcp_keep_intvl && setsockopt(sk, IPPROTO_TCP, TCP_KEEPINTVL, (char*)&(soap->tcp_keep_intvl), sizeof(int)))
  5176. {
  5177. soap->errnum = soap_socket_errno(sk);
  5178. #ifdef WITH_IPV6
  5179. freeaddrinfo(ressave);
  5180. #endif
  5181. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_KEEPINTVL failed in tcp_connect()", SOAP_TCP_ERROR);
  5182. soap->fclosesocket(soap, sk);
  5183. return soap->socket = SOAP_INVALID_SOCKET;
  5184. }
  5185. #endif
  5186. #ifdef TCP_KEEPCNT
  5187. if (soap->tcp_keep_cnt && setsockopt(sk, IPPROTO_TCP, TCP_KEEPCNT, (char*)&(soap->tcp_keep_cnt), sizeof(int)))
  5188. {
  5189. soap->errnum = soap_socket_errno(sk);
  5190. #ifdef WITH_IPV6
  5191. freeaddrinfo(ressave);
  5192. #endif
  5193. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_KEEPCNT failed in tcp_connect()", SOAP_TCP_ERROR);
  5194. soap->fclosesocket(soap, sk);
  5195. return soap->socket = SOAP_INVALID_SOCKET;
  5196. }
  5197. #endif
  5198. #ifdef TCP_NODELAY
  5199. if (!(soap->omode & SOAP_IO_UDP) && setsockopt(sk, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
  5200. {
  5201. soap->errnum = soap_socket_errno(sk);
  5202. #ifdef WITH_IPV6
  5203. freeaddrinfo(ressave);
  5204. #endif
  5205. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR);
  5206. soap->fclosesocket(soap, sk);
  5207. return soap->socket = SOAP_INVALID_SOCKET;
  5208. }
  5209. #endif
  5210. #ifdef WITH_IPV6
  5211. if ((soap->omode & SOAP_IO_UDP) && soap->ipv6_multicast_if)
  5212. {
  5213. struct sockaddr_in6 *in6addr = (struct sockaddr_in6*)res->ai_addr;
  5214. in6addr->sin6_scope_id = soap->ipv6_multicast_if;
  5215. }
  5216. #endif
  5217. #endif
  5218. #ifdef IP_MULTICAST_TTL
  5219. if ((soap->omode & SOAP_IO_UDP))
  5220. {
  5221. if (soap->ipv4_multicast_ttl)
  5222. {
  5223. unsigned char ttl = soap->ipv4_multicast_ttl;
  5224. if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl)))
  5225. {
  5226. soap->errnum = soap_socket_errno(sk);
  5227. #ifdef WITH_IPV6
  5228. freeaddrinfo(ressave);
  5229. #endif
  5230. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR);
  5231. soap->fclosesocket(soap, sk);
  5232. return soap->socket = SOAP_INVALID_SOCKET;
  5233. }
  5234. }
  5235. if ((soap->omode & SOAP_IO_UDP) && soap->ipv4_multicast_if && !soap->ipv6_multicast_if)
  5236. {
  5237. if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
  5238. #ifndef WINDOWS
  5239. {
  5240. soap->errnum = soap_socket_errno(sk);
  5241. #ifdef WITH_IPV6
  5242. freeaddrinfo(ressave);
  5243. #endif
  5244. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
  5245. soap->fclosesocket(soap, sk);
  5246. return soap->socket = SOAP_INVALID_SOCKET;
  5247. }
  5248. #else
  5249. #ifndef IP_MULTICAST_IF
  5250. #define IP_MULTICAST_IF 2
  5251. #endif
  5252. if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
  5253. {
  5254. soap->errnum = soap_socket_errno(sk);
  5255. #ifdef WITH_IPV6
  5256. freeaddrinfo(ressave);
  5257. #endif
  5258. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
  5259. soap->fclosesocket(soap, sk);
  5260. return soap->socket = SOAP_INVALID_SOCKET;
  5261. }
  5262. #endif
  5263. }
  5264. }
  5265. #endif
  5266. #endif
  5267. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Opening socket=%d to host='%s' port=%d\n", (int)sk, host, port));
  5268. #ifndef WITH_IPV6
  5269. soap->peerlen = sizeof(soap->peer.in);
  5270. memset((void*)&soap->peer.in, 0, sizeof(soap->peer.in));
  5271. soap->peer.in.sin_family = AF_INET;
  5272. if (soap->client_port >= 0)
  5273. {
  5274. struct sockaddr_in addr;
  5275. memset((void*)&addr, 0, sizeof(addr));
  5276. addr.sin_family = AF_INET;
  5277. addr.sin_port = htons(soap->client_port);
  5278. if (bind(sk, (struct sockaddr*)&addr, sizeof(addr)))
  5279. {
  5280. soap->errnum = soap_socket_errno(sk);
  5281. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind before connect\n"));
  5282. soap_set_receiver_error(soap, tcp_error(soap), "bind failed in tcp_connect()", SOAP_TCP_ERROR);
  5283. soap->fclosesocket(soap, sk);
  5284. soap->client_port = -1;
  5285. return soap->socket = SOAP_INVALID_SOCKET;
  5286. }
  5287. soap->client_port = -1; /* disable bind before connect, so need to set it again before the next connect */
  5288. }
  5289. #ifndef WIN32
  5290. if (soap->client_interface)
  5291. {
  5292. if (inet_pton(AF_INET, soap->client_interface, &soap->peer.in.sin_addr) != 1)
  5293. {
  5294. soap->errnum = soap_socket_errno(sk);
  5295. soap_set_receiver_error(soap, tcp_error(soap), "inet_pton() failed in tcp_connect()", SOAP_TCP_ERROR);
  5296. soap->fclosesocket(soap, sk);
  5297. soap->client_interface = NULL;
  5298. return soap->socket = SOAP_INVALID_SOCKET;
  5299. }
  5300. soap->client_interface = NULL; /* disable client interface, so need to set it again before the next connect */
  5301. }
  5302. #endif
  5303. soap->errmode = 2;
  5304. if (soap->proxy_host)
  5305. {
  5306. if (soap->fresolve(soap, soap->proxy_host, &soap->peer.in.sin_addr))
  5307. {
  5308. soap_set_receiver_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR);
  5309. soap->fclosesocket(soap, sk);
  5310. return soap->socket = SOAP_INVALID_SOCKET;
  5311. }
  5312. soap->peer.in.sin_port = htons((short)soap->proxy_port);
  5313. }
  5314. else
  5315. {
  5316. if (soap->fresolve(soap, host, &soap->peer.in.sin_addr))
  5317. {
  5318. soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR);
  5319. soap->fclosesocket(soap, sk);
  5320. return soap->socket = SOAP_INVALID_SOCKET;
  5321. }
  5322. soap->peer.in.sin_port = htons((short)port);
  5323. }
  5324. soap->errmode = 0;
  5325. #ifndef WITH_LEAN
  5326. if ((soap->omode & SOAP_IO_UDP))
  5327. return sk;
  5328. #endif
  5329. #else
  5330. if (soap->client_port >= 0)
  5331. {
  5332. struct sockaddr_in6 addr;
  5333. memset((void*)&addr, 0, sizeof(addr));
  5334. addr.sin6_family = AF_INET6;
  5335. addr.sin6_port = htons(soap->client_port);
  5336. if (bind(sk, (struct sockaddr*)&addr, sizeof(addr)))
  5337. {
  5338. soap->errnum = soap_socket_errno(sk);
  5339. freeaddrinfo(ressave);
  5340. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind before connect\n"));
  5341. soap_set_receiver_error(soap, tcp_error(soap), "bind failed in tcp_connect()", SOAP_TCP_ERROR);
  5342. soap->fclosesocket(soap, sk);
  5343. soap->client_port = -1;
  5344. return soap->socket = SOAP_INVALID_SOCKET;
  5345. }
  5346. soap->client_port = -1; /* disable bind before connect, so need to set t again before the next connect */
  5347. }
  5348. if (soap->client_interface)
  5349. {
  5350. if (inet_pton(AF_INET6, soap->client_interface, res->ai_addr) != 1)
  5351. {
  5352. if (inet_pton(AF_INET, soap->client_interface, res->ai_addr) != 1)
  5353. {
  5354. soap->errnum = soap_socket_errno(sk);
  5355. freeaddrinfo(ressave);
  5356. soap_set_receiver_error(soap, tcp_error(soap), "inet_pton() failed in tcp_connect()", SOAP_TCP_ERROR);
  5357. soap->fclosesocket(soap, sk);
  5358. soap->client_interface = NULL;
  5359. return soap->socket = SOAP_INVALID_SOCKET;
  5360. }
  5361. }
  5362. soap->client_interface = NULL; /* disable client interface, so need to set it again before the next connect */
  5363. }
  5364. #ifndef WITH_LEAN
  5365. if ((soap->omode & SOAP_IO_UDP))
  5366. {
  5367. if (soap_memcpy((void*)&soap->peer.storage, sizeof(soap->peer.storage), (const void*)res->ai_addr, res->ai_addrlen))
  5368. {
  5369. soap->error = SOAP_EOM;
  5370. soap->fclosesocket(soap, sk);
  5371. soap->socket = sk = SOAP_INVALID_SOCKET;
  5372. }
  5373. soap->peerlen = res->ai_addrlen;
  5374. freeaddrinfo(ressave);
  5375. return sk;
  5376. }
  5377. #endif
  5378. #endif
  5379. #ifndef WITH_LEAN
  5380. if (soap->connect_timeout)
  5381. SOAP_SOCKNONBLOCK(sk)
  5382. else
  5383. SOAP_SOCKBLOCK(sk)
  5384. retries = 10;
  5385. #endif
  5386. for (;;)
  5387. {
  5388. #ifdef WITH_IPV6
  5389. if (connect(sk, res->ai_addr, (int)res->ai_addrlen))
  5390. #else
  5391. if (connect(sk, &soap->peer.addr, sizeof(soap->peer.in)))
  5392. #endif
  5393. {
  5394. err = soap_socket_errno(sk);
  5395. #ifdef WITH_IPV6
  5396. if (err == SOAP_ECONNREFUSED && res->ai_next)
  5397. {
  5398. soap->fclosesocket(soap, sk);
  5399. res = res->ai_next;
  5400. goto again;
  5401. }
  5402. #endif
  5403. #ifndef WITH_LEAN
  5404. if (err == SOAP_EADDRINUSE)
  5405. {
  5406. soap->fclosesocket(soap, sk);
  5407. if (retries-- > 0)
  5408. goto again;
  5409. }
  5410. else if (soap->connect_timeout && (err == SOAP_EINPROGRESS || err == SOAP_EAGAIN || err == SOAP_EWOULDBLOCK))
  5411. {
  5412. SOAP_SOCKLEN_T k;
  5413. for (;;)
  5414. {
  5415. int r;
  5416. #ifdef WITH_SELF_PIPE
  5417. r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_PIP, soap->connect_timeout);
  5418. if ((r & SOAP_TCP_SELECT_PIP))
  5419. {
  5420. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection closed by self pipe\n"));
  5421. soap->fclosesocket(soap, sk);
  5422. return soap->socket = SOAP_INVALID_SOCKET;
  5423. }
  5424. #else
  5425. r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND, soap->connect_timeout);
  5426. #endif
  5427. if (r > 0)
  5428. break;
  5429. if (!r)
  5430. {
  5431. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
  5432. soap_set_receiver_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR);
  5433. soap->fclosesocket(soap, sk);
  5434. #ifdef WITH_IPV6
  5435. if (res->ai_next)
  5436. {
  5437. res = res->ai_next;
  5438. goto again;
  5439. }
  5440. freeaddrinfo(ressave);
  5441. #endif
  5442. return soap->socket = SOAP_INVALID_SOCKET;
  5443. }
  5444. r = soap->errnum = soap_socket_errno(sk);
  5445. if (r != SOAP_EINTR)
  5446. {
  5447. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
  5448. soap_set_receiver_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
  5449. soap->fclosesocket(soap, sk);
  5450. #ifdef WITH_IPV6
  5451. if (res->ai_next)
  5452. {
  5453. res = res->ai_next;
  5454. goto again;
  5455. }
  5456. freeaddrinfo(ressave);
  5457. #endif
  5458. return soap->socket = SOAP_INVALID_SOCKET;
  5459. }
  5460. }
  5461. k = (SOAP_SOCKLEN_T)sizeof(soap->errnum);
  5462. if (!getsockopt(sk, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
  5463. break;
  5464. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
  5465. if (!soap->errnum)
  5466. soap->errnum = soap_socket_errno(sk);
  5467. soap_set_receiver_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
  5468. soap->fclosesocket(soap, sk);
  5469. #ifdef WITH_IPV6
  5470. if (res->ai_next)
  5471. {
  5472. res = res->ai_next;
  5473. goto again;
  5474. }
  5475. freeaddrinfo(ressave);
  5476. #endif
  5477. return soap->socket = SOAP_INVALID_SOCKET;
  5478. }
  5479. #endif
  5480. #ifdef WITH_IPV6
  5481. if (res->ai_next)
  5482. {
  5483. res = res->ai_next;
  5484. soap->fclosesocket(soap, sk);
  5485. goto again;
  5486. }
  5487. #endif
  5488. if (err && err != SOAP_EINTR)
  5489. {
  5490. soap->errnum = err;
  5491. #ifdef WITH_IPV6
  5492. freeaddrinfo(ressave);
  5493. #endif
  5494. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
  5495. soap_set_receiver_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
  5496. soap->fclosesocket(soap, sk);
  5497. return soap->socket = SOAP_INVALID_SOCKET;
  5498. }
  5499. }
  5500. else
  5501. {
  5502. break;
  5503. }
  5504. }
  5505. #ifdef WITH_IPV6
  5506. soap->peerlen = 0; /* IPv6: already connected so use send() */
  5507. freeaddrinfo(ressave);
  5508. #endif
  5509. soap->imode &= ~SOAP_ENC_SSL;
  5510. soap->omode &= ~SOAP_ENC_SSL;
  5511. if (endpoint && !soap_tag_cmp(endpoint, "https:*"))
  5512. {
  5513. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_SYSTEMSSL)
  5514. #ifdef WITH_OPENSSL
  5515. BIO *bio;
  5516. #endif
  5517. #ifdef WITH_SYSTEMSSL
  5518. gsk_iocallback local_io = { ssl_recv, ssl_send, NULL, NULL, NULL, NULL };
  5519. #endif
  5520. int r;
  5521. if (soap->proxy_host)
  5522. {
  5523. soap_mode m = soap->mode; /* preserve settings */
  5524. soap_mode om = soap->omode; /* make sure we only parse HTTP */
  5525. ULONG64 n = soap->count; /* save the content length */
  5526. const char *userid, *passwd;
  5527. int status = soap->status; /* save the current status/command */
  5528. int keep_alive = soap->keep_alive; /* save the KA status */
  5529. soap->omode &= ~SOAP_ENC; /* mask IO and ENC */
  5530. soap->omode |= SOAP_IO_BUFFER;
  5531. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to %s proxy server %s for destination endpoint %s\n", soap->proxy_http_version, soap->proxy_host, endpoint));
  5532. #ifdef WITH_NTLM
  5533. if (soap->ntlm_challenge && soap_ntlm_handshake(soap, SOAP_CONNECT, endpoint, host, port))
  5534. {
  5535. soap->fclosesocket(soap, sk);
  5536. return soap->socket = SOAP_INVALID_SOCKET;
  5537. }
  5538. #endif
  5539. if (soap_init_send(soap))
  5540. {
  5541. soap->fclosesocket(soap, sk);
  5542. return soap->socket = SOAP_INVALID_SOCKET;
  5543. }
  5544. soap->status = SOAP_CONNECT;
  5545. if (!soap->keep_alive)
  5546. soap->keep_alive = -1; /* must keep alive */
  5547. soap->error = soap->fpost(soap, endpoint, host, port, NULL, NULL, 0);
  5548. if (soap->error
  5549. || soap_end_send_flush(soap))
  5550. {
  5551. soap->fclosesocket(soap, sk);
  5552. return soap->socket = SOAP_INVALID_SOCKET;
  5553. }
  5554. soap->keep_alive = keep_alive;
  5555. soap->omode = om;
  5556. om = soap->imode;
  5557. soap->imode &= ~SOAP_ENC; /* mask IO and ENC */
  5558. userid = soap->userid; /* preserve */
  5559. passwd = soap->passwd; /* preserve */
  5560. soap->error = soap->fparse(soap);
  5561. if (soap->error)
  5562. {
  5563. soap->fclosesocket(soap, sk);
  5564. return soap->socket = SOAP_INVALID_SOCKET;
  5565. }
  5566. soap->status = status; /* restore */
  5567. soap->userid = userid; /* restore */
  5568. soap->passwd = passwd; /* restore */
  5569. soap->imode = om; /* restore */
  5570. soap->count = n; /* restore */
  5571. if (soap_init_send(soap))
  5572. {
  5573. soap->fclosesocket(soap, sk);
  5574. return soap->socket = SOAP_INVALID_SOCKET;
  5575. }
  5576. if (endpoint)
  5577. soap_strcpy(soap->endpoint, sizeof(soap->endpoint), endpoint); /* restore */
  5578. soap->mode = m;
  5579. }
  5580. #ifdef WITH_OPENSSL
  5581. ERR_clear_error();
  5582. soap->ssl_flags |= SOAP_SSL_CLIENT;
  5583. if (!soap->ctx && (soap->error = soap->fsslauth(soap)) != SOAP_OK)
  5584. {
  5585. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL required, but no ctx set\n"));
  5586. soap->fclosesocket(soap, sk);
  5587. soap->error = SOAP_SSL_ERROR;
  5588. return soap->socket = SOAP_INVALID_SOCKET;
  5589. }
  5590. if (!soap->ssl)
  5591. {
  5592. soap->ssl = SSL_new(soap->ctx);
  5593. if (!soap->ssl)
  5594. {
  5595. soap->fclosesocket(soap, sk);
  5596. soap->error = SOAP_SSL_ERROR;
  5597. return soap->socket = SOAP_INVALID_SOCKET;
  5598. }
  5599. }
  5600. else
  5601. {
  5602. SSL_clear(soap->ssl);
  5603. }
  5604. if (soap->session)
  5605. {
  5606. if (!strcmp(soap->session_host, host) && soap->session_port == port)
  5607. SSL_set_session(soap->ssl, soap->session);
  5608. SSL_SESSION_free(soap->session);
  5609. soap->session = NULL;
  5610. }
  5611. #if OPENSSL_VERSION_NUMBER >= 0x1000000aL
  5612. if (!(soap->ssl_flags & SOAP_SSLv3) && !SSL_set_tlsext_host_name(soap->ssl, host))
  5613. {
  5614. soap_set_receiver_error(soap, "SSL/TLS error", "SNI failed", SOAP_SSL_ERROR);
  5615. soap->fclosesocket(soap, sk);
  5616. return soap->socket = SOAP_INVALID_SOCKET;
  5617. }
  5618. #elif (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && defined(SSL_CTRL_SET_TLSEXT_HOSTNAME)
  5619. if (!SSL_ctrl(soap->ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, (void*)host))
  5620. {
  5621. soap_set_receiver_error(soap, "SSL/TLS error", "SNI failed", SOAP_SSL_ERROR);
  5622. soap->fclosesocket(soap, sk);
  5623. return soap->socket = SOAP_INVALID_SOCKET;
  5624. }
  5625. #endif
  5626. bio = BIO_new_socket((int)sk, BIO_NOCLOSE);
  5627. SSL_set_bio(soap->ssl, bio, bio);
  5628. if (soap->connect_timeout || soap->recv_timeout || soap->send_timeout)
  5629. {
  5630. /* Set SSL connect timeout and set SSL sockets to non-blocking */
  5631. int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout;
  5632. if (soap->connect_timeout > 0 && t < soap->connect_timeout)
  5633. t = soap->connect_timeout;
  5634. if (t > 0)
  5635. retries = 10 * t;
  5636. else if (t > -100000)
  5637. retries = 1;
  5638. else
  5639. retries = t/-100000;
  5640. SOAP_SOCKNONBLOCK(sk)
  5641. }
  5642. else
  5643. {
  5644. /* Set sockets to blocking */
  5645. retries = 1;
  5646. SOAP_SOCKBLOCK(sk)
  5647. }
  5648. err = SSL_ERROR_NONE;
  5649. /* Try connecting until success or timeout */
  5650. do
  5651. {
  5652. if ((r = SSL_connect(soap->ssl)) <= 0)
  5653. {
  5654. err = SSL_get_error(soap->ssl, r);
  5655. if (err == SSL_ERROR_WANT_CONNECT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
  5656. {
  5657. int s;
  5658. if (err == SSL_ERROR_WANT_READ)
  5659. s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
  5660. else
  5661. s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
  5662. if (s < 0)
  5663. break;
  5664. if (s == 0 && retries-- <= 0)
  5665. {
  5666. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL/TLS connect timeout\n"));
  5667. soap_set_receiver_error(soap, "Timeout", "SSL_connect() failed in tcp_connect()", SOAP_TCP_ERROR);
  5668. soap->fclosesocket(soap, sk);
  5669. return soap->socket = SOAP_INVALID_SOCKET;
  5670. }
  5671. }
  5672. else
  5673. {
  5674. soap->errnum = soap_socket_errno(sk);
  5675. break;
  5676. }
  5677. }
  5678. } while (!SSL_is_init_finished(soap->ssl));
  5679. if (r <= 0)
  5680. {
  5681. soap_set_sender_error(soap, soap_ssl_error(soap, r, err), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
  5682. soap->fclosesocket(soap, sk);
  5683. return soap->socket = SOAP_INVALID_SOCKET;
  5684. }
  5685. /* Check server credentials when required */
  5686. if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
  5687. {
  5688. if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
  5689. {
  5690. 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);
  5691. soap->fclosesocket(soap, sk);
  5692. return soap->socket = SOAP_INVALID_SOCKET;
  5693. }
  5694. if (!(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK))
  5695. {
  5696. X509_NAME *subj;
  5697. STACK_OF(CONF_VALUE) *val = NULL;
  5698. #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
  5699. GENERAL_NAMES *names = NULL;
  5700. #else
  5701. int ext_count;
  5702. #endif
  5703. int ok = 0;
  5704. X509 *peer = SSL_get_peer_certificate(soap->ssl);
  5705. if (!peer)
  5706. {
  5707. soap_set_sender_error(soap, "SSL/TLS error", "No SSL/TLS certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR);
  5708. soap->fclosesocket(soap, sk);
  5709. return soap->socket = SOAP_INVALID_SOCKET;
  5710. }
  5711. #if OPENSSL_VERSION_NUMBER < 0x0090800fL
  5712. ext_count = X509_get_ext_count(peer);
  5713. if (ext_count > 0)
  5714. {
  5715. int i;
  5716. for (i = 0; i < ext_count; i++)
  5717. {
  5718. X509_EXTENSION *ext = X509_get_ext(peer, i);
  5719. const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
  5720. if (ext_str && !strcmp(ext_str, "subjectAltName"))
  5721. {
  5722. X509V3_EXT_METHOD *meth = (X509V3_EXT_METHOD*)X509V3_EXT_get(ext);
  5723. unsigned char *data;
  5724. if (!meth)
  5725. break;
  5726. data = ext->value->data;
  5727. if (data)
  5728. {
  5729. #if OPENSSL_VERSION_NUMBER > 0x00907000L
  5730. void *ext_data;
  5731. if (meth->it)
  5732. ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it));
  5733. else
  5734. {
  5735. #if OPENSSL_VERSION_NUMBER > 0x0090800fL
  5736. ext_data = meth->d2i(NULL, (const unsigned char **)&data, ext->value->length);
  5737. #else
  5738. ext_data = meth->d2i(NULL, &data, ext->value->length);
  5739. #endif
  5740. }
  5741. if (ext_data)
  5742. val = meth->i2v(meth, ext_data, NULL);
  5743. else
  5744. val = NULL;
  5745. if (meth->it)
  5746. ASN1_item_free((ASN1_VALUE*)ext_data, ASN1_ITEM_ptr(meth->it));
  5747. else
  5748. meth->ext_free(ext_data);
  5749. #else
  5750. void *ext_data = meth->d2i(NULL, &data, ext->value->length);
  5751. if (ext_data)
  5752. val = meth->i2v(meth, ext_data, NULL);
  5753. meth->ext_free(ext_data);
  5754. #endif
  5755. if (val)
  5756. {
  5757. int j;
  5758. for (j = 0; j < sk_CONF_VALUE_num(val); j++)
  5759. {
  5760. CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
  5761. if (nval && (!strcmp(nval->name, "DNS") || !strcmp(nval->name, "IP Address")) && !soap_tag_cmp(host, nval->value))
  5762. {
  5763. ok = 1;
  5764. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate %s %s\n", host, nval->name, nval->value));
  5765. break;
  5766. }
  5767. else
  5768. {
  5769. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s mismatch with certificate %s %s\n", host, nval->name, nval->value));
  5770. }
  5771. }
  5772. sk_CONF_VALUE_pop_free(val, X509V3_conf_free);
  5773. }
  5774. }
  5775. }
  5776. if (ok)
  5777. break;
  5778. }
  5779. }
  5780. #else
  5781. names = (GENERAL_NAMES*)X509_get_ext_d2i(peer, NID_subject_alt_name, NULL, NULL);
  5782. if (names)
  5783. {
  5784. val = i2v_GENERAL_NAMES(NULL, names, val);
  5785. sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
  5786. }
  5787. if (val)
  5788. {
  5789. int j;
  5790. for (j = 0; j < sk_CONF_VALUE_num(val); j++)
  5791. {
  5792. CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
  5793. if (nval && (!strcmp(nval->name, "DNS") || !strcmp(nval->name, "IP Address")) && !soap_tag_cmp(host, nval->value))
  5794. {
  5795. ok = 1;
  5796. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate %s %s\n", host, nval->name, nval->value));
  5797. break;
  5798. }
  5799. else
  5800. {
  5801. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s mismatch with certificate %s %s\n", host, nval->name, nval->value));
  5802. }
  5803. }
  5804. sk_CONF_VALUE_pop_free(val, X509V3_conf_free);
  5805. }
  5806. #endif
  5807. if (!ok && (subj = X509_get_subject_name(peer)) != 0)
  5808. {
  5809. int i = -1;
  5810. do
  5811. {
  5812. ASN1_STRING *name;
  5813. i = X509_NAME_get_index_by_NID(subj, NID_commonName, i);
  5814. if (i == -1)
  5815. break;
  5816. name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i));
  5817. if (name)
  5818. {
  5819. #if OPENSSL_VERSION_NUMBER < 0x10100000L
  5820. const char *tmp = (const char*)ASN1_STRING_data(name);
  5821. #else
  5822. const char *tmp = (const char*)ASN1_STRING_get0_data(name);
  5823. #endif
  5824. if (!soap_tag_cmp(host, tmp))
  5825. {
  5826. ok = 1;
  5827. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate subject %s\n", host, tmp));
  5828. }
  5829. else
  5830. {
  5831. unsigned char *tmp = NULL;
  5832. ASN1_STRING_to_UTF8(&tmp, name);
  5833. if (tmp)
  5834. {
  5835. if (!soap_tag_cmp(host, (const char*)tmp))
  5836. {
  5837. ok = 1;
  5838. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate subject %s\n", host, tmp));
  5839. }
  5840. else if (tmp[0] == '*') /* wildcard domain */
  5841. {
  5842. const char *t = strchr(host, '.');
  5843. if (t && !soap_tag_cmp(t, (const char*)tmp + 1))
  5844. {
  5845. ok = 1;
  5846. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate subject %s\n", host, tmp));
  5847. }
  5848. }
  5849. else
  5850. {
  5851. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s mismatch with certificate %s\n", host, tmp));
  5852. }
  5853. OPENSSL_free(tmp);
  5854. }
  5855. }
  5856. }
  5857. } while (!ok);
  5858. }
  5859. X509_free(peer);
  5860. if (!ok)
  5861. {
  5862. soap_set_sender_error(soap, "SSL/TLS error", "SSL/TLS certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR);
  5863. soap->fclosesocket(soap, sk);
  5864. return soap->socket = SOAP_INVALID_SOCKET;
  5865. }
  5866. }
  5867. }
  5868. #endif
  5869. #ifdef WITH_GNUTLS
  5870. soap->ssl_flags |= SOAP_SSL_CLIENT;
  5871. if (!soap->session && (soap->error = soap->fsslauth(soap)) != SOAP_OK)
  5872. {
  5873. soap->fclosesocket(soap, sk);
  5874. return soap->socket = SOAP_INVALID_SOCKET;
  5875. }
  5876. gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)sk);
  5877. if (soap->connect_timeout || soap->recv_timeout || soap->send_timeout)
  5878. {
  5879. /* Set SSL connect timeout and set SSL sockets to non-blocking */
  5880. int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout;
  5881. if (soap->connect_timeout > 0 && t < soap->connect_timeout)
  5882. t = soap->connect_timeout;
  5883. if (t > 0)
  5884. retries = 10 * t;
  5885. else if (t > -100000)
  5886. retries = 1;
  5887. else
  5888. retries = t/-100000;
  5889. SOAP_SOCKNONBLOCK(sk)
  5890. }
  5891. else
  5892. {
  5893. /* Set sockets to blocking */
  5894. retries = 1;
  5895. SOAP_SOCKBLOCK(sk)
  5896. }
  5897. /* Try connecting until success or timeout */
  5898. while ((r = gnutls_handshake(soap->session)))
  5899. {
  5900. /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */
  5901. if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED)
  5902. {
  5903. int s;
  5904. if (!gnutls_record_get_direction(soap->session))
  5905. s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
  5906. else
  5907. s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
  5908. if (s < 0)
  5909. break;
  5910. if (s == 0 && retries-- <= 0)
  5911. {
  5912. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL/TLS connect timeout\n"));
  5913. soap_set_receiver_error(soap, "Timeout", "SSL_connect() failed in tcp_connect()", SOAP_TCP_ERROR);
  5914. soap->fclosesocket(soap, sk);
  5915. return soap->socket = SOAP_INVALID_SOCKET;
  5916. }
  5917. }
  5918. else
  5919. {
  5920. soap->errnum = soap_socket_errno(sk);
  5921. break;
  5922. }
  5923. }
  5924. if (r)
  5925. {
  5926. soap_set_sender_error(soap, soap_ssl_error(soap, r, 0), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
  5927. soap->fclosesocket(soap, sk);
  5928. return soap->socket = SOAP_INVALID_SOCKET;
  5929. }
  5930. if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
  5931. {
  5932. const char *s = ssl_verify(soap, host);
  5933. if (s)
  5934. {
  5935. soap->fclosesocket(soap, sk);
  5936. soap->error = soap_set_sender_error(soap, "SSL/TLS verify error", s, SOAP_SSL_ERROR);
  5937. return soap->socket = SOAP_INVALID_SOCKET;
  5938. }
  5939. }
  5940. #endif
  5941. #ifdef WITH_SYSTEMSSL
  5942. soap->ssl_flags |= SOAP_SSL_CLIENT;
  5943. if (!soap->ctx && (soap->error = soap->fsslauth(soap)) != SOAP_OK)
  5944. {
  5945. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL required, but no ctx set\n"));
  5946. soap->fclosesocket(soap, sk);
  5947. soap->error = SOAP_SSL_ERROR;
  5948. return soap->socket = SOAP_INVALID_SOCKET;
  5949. }
  5950. if (soap->connect_timeout || soap->recv_timeout || soap->send_timeout)
  5951. {
  5952. /* Set SSL connect timeout and set SSL sockets to non-blocking */
  5953. int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout;
  5954. if (soap->connect_timeout > 0 && t < soap->connect_timeout)
  5955. t = soap->connect_timeout;
  5956. if (t > 0)
  5957. retries = 10 * t;
  5958. else if (t > -100000)
  5959. retries = 1;
  5960. else
  5961. retries = t/-100000;
  5962. SOAP_SOCKNONBLOCK(sk)
  5963. }
  5964. else
  5965. {
  5966. /* Set sockets to blocking */
  5967. retries = 1;
  5968. SOAP_SOCKBLOCK(sk)
  5969. }
  5970. r = gsk_secure_socket_open(soap->ctx, &soap->ssl);
  5971. if (r == GSK_OK)
  5972. r = gsk_attribute_set_numeric_value(soap->ssl, GSK_FD, sk);
  5973. if (r == GSK_OK)
  5974. r = gsk_attribute_set_buffer(soap->ssl, GSK_KEYRING_LABEL, soap->cafile, 0); /* Certificate label */
  5975. if (r == GSK_OK)
  5976. r = gsk_attribute_set_enum(soap->ssl, GSK_SESSION_TYPE, GSK_CLIENT_SESSION);
  5977. if (r == GSK_OK)
  5978. r = gsk_attribute_set_buffer(soap->ssl, GSK_V3_CIPHER_SPECS_EXPANDED, "0035002F000A", 0);
  5979. if (r == GSK_OK)
  5980. r = gsk_attribute_set_enum(soap->ssl, GSK_V3_CIPHERS, GSK_V3_CIPHERS_CHAR4);
  5981. if (r == GSK_OK)
  5982. r = gsk_attribute_set_callback(soap->ssl, GSK_IO_CALLBACK, &local_io);
  5983. if (r != GSK_OK)
  5984. {
  5985. soap_set_receiver_error(soap, gsk_strerror(r), "SYSTEM SSL error in tcp_connect()", SOAP_SSL_ERROR);
  5986. return soap->socket = SOAP_INVALID_SOCKET;
  5987. }
  5988. /* Try connecting until success or timeout */
  5989. while ((r = gsk_secure_socket_init(soap->ssl)) != GSK_OK)
  5990. {
  5991. if (r == GSK_WOULD_BLOCK_READ || r == GSK_WOULD_BLOCK_WRITE)
  5992. {
  5993. int s;
  5994. if (r == GSK_WOULD_BLOCK_READ)
  5995. s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
  5996. else
  5997. s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
  5998. if (s < 0)
  5999. break;
  6000. if (s == 0 && retries-- <= 0)
  6001. {
  6002. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL/TLS connect timeout\n"));
  6003. soap_set_receiver_error(soap, "Timeout", "SSL_connect() failed in tcp_connect()", SOAP_TCP_ERROR);
  6004. soap->fclosesocket(soap, sk);
  6005. return soap->socket = SOAP_INVALID_SOCKET;
  6006. }
  6007. }
  6008. else
  6009. {
  6010. soap->errnum = soap_socket_errno(sk);
  6011. break;
  6012. }
  6013. }
  6014. if (r != GSK_OK)
  6015. {
  6016. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL_connect/select error in tcp_connect\n"));
  6017. soap_set_receiver_error(soap, gsk_strerror(r), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
  6018. soap->fclosesocket(soap, sk);
  6019. return soap->socket = SOAP_INVALID_SOCKET;
  6020. }
  6021. #endif
  6022. soap->imode |= SOAP_ENC_SSL;
  6023. soap->omode |= SOAP_ENC_SSL;
  6024. #else
  6025. soap->fclosesocket(soap, sk);
  6026. soap->error = SOAP_SSL_ERROR;
  6027. return soap->socket = SOAP_INVALID_SOCKET;
  6028. #endif
  6029. }
  6030. if (soap->recv_timeout || soap->send_timeout)
  6031. SOAP_SOCKNONBLOCK(sk)
  6032. else
  6033. SOAP_SOCKBLOCK(sk)
  6034. return sk;
  6035. }
  6036. #endif
  6037. /******************************************************************************/
  6038. #ifndef WITH_NOIO
  6039. static int
  6040. tcp_select(struct soap *soap, SOAP_SOCKET sk, int flags, int timeout)
  6041. {
  6042. int r;
  6043. struct timeval tv;
  6044. fd_set fd[3], *rfd, *sfd, *efd;
  6045. int retries = 0;
  6046. int eintr = SOAP_MAXEINTR;
  6047. soap->errnum = 0;
  6048. if (!soap_valid_socket(sk))
  6049. {
  6050. soap->error = SOAP_EOF;
  6051. return -1;
  6052. }
  6053. #ifndef WIN32
  6054. #if !defined(FD_SETSIZE) || defined(__QNX__) || defined(QNX)
  6055. /* no FD_SETSIZE or select() is not MT safe on some QNX: always poll */
  6056. if (1)
  6057. #else
  6058. /* if fd max set size exceeded, use poll() when available */
  6059. if ((int)sk >= (int)FD_SETSIZE)
  6060. #endif
  6061. #ifdef HAVE_POLL
  6062. {
  6063. #ifdef WITH_SELF_PIPE
  6064. struct pollfd pollfd[2];
  6065. pollfd[1].fd = soap->pipe_fd[0];
  6066. pollfd[1].events = POLLIN;
  6067. #else
  6068. struct pollfd pollfd[1];
  6069. #endif
  6070. pollfd[0].fd = (int)sk;
  6071. pollfd[0].events = 0;
  6072. if ((flags & SOAP_TCP_SELECT_RCV))
  6073. pollfd[0].events |= POLLIN;
  6074. if ((flags & SOAP_TCP_SELECT_SND))
  6075. pollfd[0].events |= POLLOUT;
  6076. if ((flags & SOAP_TCP_SELECT_ERR))
  6077. pollfd[0].events |= POLLERR;
  6078. if (timeout <= 0)
  6079. timeout /= -1000; /* -usec -> ms */
  6080. else
  6081. {
  6082. retries = timeout - 1;
  6083. timeout = 1000;
  6084. }
  6085. do
  6086. {
  6087. #ifdef WITH_SELF_PIPE
  6088. r = poll(pollfd, 2, timeout);
  6089. #else
  6090. r = poll(pollfd, 1, timeout);
  6091. #endif
  6092. if (r < 0 && (soap->errnum = soap_socket_errno(sk)) == SOAP_EINTR && eintr > 0)
  6093. {
  6094. eintr--;
  6095. r = 0;
  6096. }
  6097. else if (retries-- <= 0)
  6098. {
  6099. break;
  6100. }
  6101. } while (r == 0);
  6102. if (r > 0)
  6103. {
  6104. r = 0;
  6105. if ((flags & SOAP_TCP_SELECT_RCV) && (pollfd[0].revents & POLLIN))
  6106. r |= SOAP_TCP_SELECT_RCV;
  6107. if ((flags & SOAP_TCP_SELECT_SND) && (pollfd[0].revents & POLLOUT))
  6108. r |= SOAP_TCP_SELECT_SND;
  6109. if ((flags & SOAP_TCP_SELECT_ERR) && (pollfd[0].revents & POLLERR))
  6110. r |= SOAP_TCP_SELECT_ERR;
  6111. #ifdef WITH_SELF_PIPE
  6112. if ((flags & SOAP_TCP_SELECT_PIP) && (pollfd[1].revents & POLLIN))
  6113. {
  6114. char ch;
  6115. for (;;)
  6116. {
  6117. if (read(soap->pipe_fd[0], &ch, 1) == -1)
  6118. {
  6119. if (soap_socket_errno(soap->pipe_fd[0]) == SOAP_EAGAIN)
  6120. break;
  6121. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Self pipe read error\n"));
  6122. return -1;
  6123. }
  6124. }
  6125. r |= SOAP_TCP_SELECT_PIP;
  6126. }
  6127. #endif
  6128. }
  6129. else if (r == 0)
  6130. {
  6131. soap->errnum = 0;
  6132. }
  6133. return r;
  6134. }
  6135. #else
  6136. {
  6137. soap->error = SOAP_FD_EXCEEDED;
  6138. return -1;
  6139. }
  6140. #endif
  6141. #endif
  6142. if (timeout > 0)
  6143. retries = timeout - 1;
  6144. do
  6145. {
  6146. rfd = sfd = efd = NULL;
  6147. #ifdef WITH_SELF_PIPE
  6148. if ((flags & SOAP_TCP_SELECT_PIP) || (flags & SOAP_TCP_SELECT_RCV))
  6149. {
  6150. rfd = &fd[0];
  6151. FD_ZERO(rfd);
  6152. if ((flags & SOAP_TCP_SELECT_PIP))
  6153. FD_SET(soap->pipe_fd[0], rfd);
  6154. if ((flags & SOAP_TCP_SELECT_RCV))
  6155. FD_SET(sk, rfd);
  6156. }
  6157. #else
  6158. if ((flags & SOAP_TCP_SELECT_RCV))
  6159. {
  6160. rfd = &fd[0];
  6161. FD_ZERO(rfd);
  6162. FD_SET(sk, rfd);
  6163. }
  6164. #endif
  6165. if ((flags & SOAP_TCP_SELECT_SND))
  6166. {
  6167. sfd = &fd[1];
  6168. FD_ZERO(sfd);
  6169. FD_SET(sk, sfd);
  6170. }
  6171. if ((flags & SOAP_TCP_SELECT_ERR))
  6172. {
  6173. efd = &fd[2];
  6174. FD_ZERO(efd);
  6175. FD_SET(sk, efd);
  6176. }
  6177. if (timeout <= 0)
  6178. {
  6179. tv.tv_sec = -timeout / 1000000;
  6180. tv.tv_usec = -timeout % 1000000;
  6181. }
  6182. else
  6183. {
  6184. tv.tv_sec = 1;
  6185. tv.tv_usec = 0;
  6186. }
  6187. #ifdef WITH_SELF_PIPE
  6188. r = select((int)(sk > soap->pipe_fd[0] ? sk : soap->pipe_fd[0]) + 1, rfd, sfd, efd, &tv);
  6189. #else
  6190. r = select((int)sk + 1, rfd, sfd, efd, &tv);
  6191. #endif
  6192. if (r < 0 && (soap->errnum = soap_socket_errno(sk)) == SOAP_EINTR && eintr > 0)
  6193. {
  6194. eintr--;
  6195. r = 0;
  6196. }
  6197. else if (retries-- <= 0)
  6198. {
  6199. break;
  6200. }
  6201. } while (r == 0);
  6202. if (r > 0)
  6203. {
  6204. r = 0;
  6205. if ((flags & SOAP_TCP_SELECT_RCV) && FD_ISSET(sk, rfd))
  6206. r |= SOAP_TCP_SELECT_RCV;
  6207. if ((flags & SOAP_TCP_SELECT_SND) && FD_ISSET(sk, sfd))
  6208. r |= SOAP_TCP_SELECT_SND;
  6209. if ((flags & SOAP_TCP_SELECT_ERR) && FD_ISSET(sk, efd))
  6210. r |= SOAP_TCP_SELECT_ERR;
  6211. #ifdef WITH_SELF_PIPE
  6212. if ((flags & SOAP_TCP_SELECT_PIP) && FD_ISSET(soap->pipe_fd[0], rfd))
  6213. {
  6214. char ch;
  6215. for (;;)
  6216. {
  6217. if (read(soap->pipe_fd[0], &ch, 1) == -1)
  6218. {
  6219. if (soap_socket_errno(soap->pipe_fd[0]) == SOAP_EAGAIN)
  6220. break;
  6221. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Self pipe read error\n"));
  6222. return -1;
  6223. }
  6224. }
  6225. r |= SOAP_TCP_SELECT_PIP;
  6226. }
  6227. #endif
  6228. }
  6229. else if (r == 0)
  6230. {
  6231. soap->errnum = 0;
  6232. }
  6233. return r;
  6234. }
  6235. #endif
  6236. /******************************************************************************/
  6237. #ifndef WITH_NOIO
  6238. static SOAP_SOCKET
  6239. tcp_accept(struct soap *soap, SOAP_SOCKET sk, struct sockaddr *addr, int *len)
  6240. {
  6241. SOAP_SOCKET s;
  6242. (void)soap;
  6243. s = accept(sk, addr, (SOAP_SOCKLEN_T*)len); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
  6244. #ifdef WITH_SOCKET_CLOSE_ON_EXIT
  6245. #ifdef WIN32
  6246. #ifndef UNDER_CE
  6247. SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, 0);
  6248. #endif
  6249. #else
  6250. fcntl(s, F_SETFD, FD_CLOEXEC);
  6251. #endif
  6252. #endif
  6253. return s;
  6254. }
  6255. #endif
  6256. /******************************************************************************/
  6257. #ifndef WITH_NOIO
  6258. static int
  6259. tcp_disconnect(struct soap *soap)
  6260. {
  6261. #ifdef WITH_OPENSSL
  6262. if (soap->ssl)
  6263. {
  6264. int r;
  6265. if (soap->session)
  6266. {
  6267. SSL_SESSION_free(soap->session);
  6268. soap->session = NULL;
  6269. }
  6270. if (*soap->host)
  6271. {
  6272. soap->session = SSL_get1_session(soap->ssl);
  6273. if (soap->session)
  6274. {
  6275. soap_strcpy(soap->session_host, sizeof(soap->session_host), soap->host);
  6276. soap->session_port = soap->port;
  6277. }
  6278. }
  6279. r = SSL_shutdown(soap->ssl);
  6280. /* SSL shutdown does not work when reads are pending, non-blocking */
  6281. if (r == 0)
  6282. {
  6283. while (SSL_want_read(soap->ssl))
  6284. {
  6285. if (SSL_read(soap->ssl, NULL, 0)
  6286. || soap_socket_errno(soap->socket) != SOAP_EAGAIN)
  6287. {
  6288. r = SSL_shutdown(soap->ssl);
  6289. break;
  6290. }
  6291. }
  6292. }
  6293. if (r == 0)
  6294. {
  6295. if (soap_valid_socket(soap->socket))
  6296. {
  6297. if (!soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR))
  6298. {
  6299. #if !defined(WITH_LEAN) && !defined(WIN32)
  6300. /*
  6301. wait up to 5 seconds for close_notify to be sent by peer (if peer not
  6302. present, this avoids calling SSL_shutdown() which has a lengthy return
  6303. timeout)
  6304. */
  6305. r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, 5);
  6306. if (r <= 0)
  6307. {
  6308. soap->errnum = 0;
  6309. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection lost...\n"));
  6310. soap->fclosesocket(soap, soap->socket);
  6311. soap->socket = SOAP_INVALID_SOCKET;
  6312. ERR_clear_error();
  6313. SSL_free(soap->ssl);
  6314. soap->ssl = NULL;
  6315. return SOAP_OK;
  6316. }
  6317. #else
  6318. r = SSL_shutdown(soap->ssl);
  6319. if (r <= 0)
  6320. {
  6321. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r)));
  6322. if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
  6323. {
  6324. soap->fclosesocket(soap, soap->socket);
  6325. soap->socket = SOAP_INVALID_SOCKET;
  6326. }
  6327. }
  6328. #endif
  6329. }
  6330. }
  6331. }
  6332. SSL_free(soap->ssl);
  6333. soap->ssl = NULL;
  6334. ERR_clear_error();
  6335. }
  6336. #endif
  6337. #ifdef WITH_GNUTLS
  6338. if (soap->session)
  6339. {
  6340. gnutls_bye(soap->session, GNUTLS_SHUT_RDWR);
  6341. gnutls_deinit(soap->session);
  6342. soap->session = NULL;
  6343. }
  6344. #endif
  6345. #ifdef WITH_SYSTEMSSL
  6346. if (soap->ssl)
  6347. {
  6348. gsk_secure_socket_shutdown(soap->ssl);
  6349. gsk_secure_socket_close(&soap->ssl);
  6350. }
  6351. #endif
  6352. if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
  6353. {
  6354. soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_RDWR);
  6355. soap->fclosesocket(soap, soap->socket);
  6356. soap->socket = SOAP_INVALID_SOCKET;
  6357. }
  6358. return SOAP_OK;
  6359. }
  6360. #endif
  6361. /******************************************************************************/
  6362. #ifndef WITH_NOIO
  6363. static int
  6364. tcp_closesocket(struct soap *soap, SOAP_SOCKET sk)
  6365. {
  6366. (void)soap;
  6367. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket=%d\n", (int)sk));
  6368. return soap_closesocket(sk);
  6369. }
  6370. #endif
  6371. /******************************************************************************/
  6372. #ifndef WITH_NOIO
  6373. static int
  6374. tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET sk, int how)
  6375. {
  6376. (void)soap;
  6377. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket=%d how=%d\n", (int)sk, how));
  6378. return shutdown(sk, how);
  6379. }
  6380. #endif
  6381. /******************************************************************************/
  6382. #ifndef WITH_NOIO
  6383. SOAP_FMAC1
  6384. SOAP_SOCKET
  6385. SOAP_FMAC2
  6386. soap_bind(struct soap *soap, const char *host, int port, int backlog)
  6387. {
  6388. #if defined(WITH_IPV6)
  6389. struct addrinfo *addrinfo = NULL;
  6390. struct addrinfo hints;
  6391. struct addrinfo res;
  6392. int err;
  6393. int set = 1;
  6394. int unset = 0;
  6395. #elif !defined(WITH_LEAN)
  6396. int set = 1;
  6397. #endif
  6398. if (soap_valid_socket(soap->master))
  6399. {
  6400. soap->fclosesocket(soap, soap->master);
  6401. soap->master = SOAP_INVALID_SOCKET;
  6402. }
  6403. soap->socket = SOAP_INVALID_SOCKET;
  6404. soap->errnum = 0;
  6405. soap->errmode = 1;
  6406. if (tcp_init(soap))
  6407. {
  6408. soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR);
  6409. return SOAP_INVALID_SOCKET;
  6410. }
  6411. #ifdef WITH_IPV6
  6412. memset((void*)&hints, 0, sizeof(hints));
  6413. hints.ai_family = soap->bind_inet6 ? AF_INET6 : PF_UNSPEC;
  6414. #ifndef WITH_LEAN
  6415. if ((soap->omode & SOAP_IO_UDP))
  6416. hints.ai_socktype = SOCK_DGRAM;
  6417. else
  6418. #endif
  6419. hints.ai_socktype = SOCK_STREAM;
  6420. hints.ai_flags = AI_PASSIVE;
  6421. soap->errmode = 2;
  6422. err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo);
  6423. if (err || !addrinfo)
  6424. {
  6425. soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR);
  6426. if (addrinfo)
  6427. freeaddrinfo(addrinfo);
  6428. return SOAP_INVALID_SOCKET;
  6429. }
  6430. res = *addrinfo;
  6431. if (soap_memcpy((void*)&soap->peer.storage, sizeof(soap->peer.storage), (const void*)addrinfo->ai_addr, addrinfo->ai_addrlen))
  6432. {
  6433. freeaddrinfo(addrinfo);
  6434. soap->error = SOAP_EOM;
  6435. return SOAP_INVALID_SOCKET;
  6436. }
  6437. soap->peerlen = addrinfo->ai_addrlen;
  6438. res.ai_addr = &soap->peer.addr;
  6439. res.ai_addrlen = soap->peerlen;
  6440. freeaddrinfo(addrinfo);
  6441. soap->master = (int)socket(res.ai_family, res.ai_socktype, res.ai_protocol);
  6442. #else
  6443. #ifndef WITH_LEAN
  6444. if ((soap->omode & SOAP_IO_UDP))
  6445. soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0);
  6446. else
  6447. #endif
  6448. soap->master = (int)socket(AF_INET, SOCK_STREAM, 0);
  6449. #endif
  6450. soap->errmode = 0;
  6451. if (!soap_valid_socket(soap->master))
  6452. {
  6453. soap->errnum = soap_socket_errno(soap->master);
  6454. soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR);
  6455. return SOAP_INVALID_SOCKET;
  6456. }
  6457. soap->port = port;
  6458. #ifndef WITH_LEAN
  6459. if ((soap->omode & SOAP_IO_UDP))
  6460. soap->socket = soap->master;
  6461. #endif
  6462. #ifdef WITH_SOCKET_CLOSE_ON_EXIT
  6463. #ifdef WIN32
  6464. #ifndef UNDER_CE
  6465. SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0);
  6466. #endif
  6467. #else
  6468. fcntl(soap->master, F_SETFD, 1);
  6469. #endif
  6470. #endif
  6471. #ifndef WITH_LEAN
  6472. if (soap->bind_flags && setsockopt(soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int)))
  6473. {
  6474. soap->errnum = soap_socket_errno(soap->master);
  6475. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR);
  6476. return SOAP_INVALID_SOCKET;
  6477. }
  6478. #ifndef UNDER_CE
  6479. if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && (!((soap->imode | soap->omode) & SOAP_IO_UDP)) && setsockopt(soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
  6480. {
  6481. soap->errnum = soap_socket_errno(soap->master);
  6482. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR);
  6483. return SOAP_INVALID_SOCKET;
  6484. }
  6485. if (soap->sndbuf > 0 && setsockopt(soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&soap->sndbuf, sizeof(int)))
  6486. {
  6487. soap->errnum = soap_socket_errno(soap->master);
  6488. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR);
  6489. return SOAP_INVALID_SOCKET;
  6490. }
  6491. if (soap->rcvbuf > 0 && setsockopt(soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&soap->rcvbuf, sizeof(int)))
  6492. {
  6493. soap->errnum = soap_socket_errno(soap->master);
  6494. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR);
  6495. return SOAP_INVALID_SOCKET;
  6496. }
  6497. #ifdef TCP_NODELAY
  6498. if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
  6499. {
  6500. soap->errnum = soap_socket_errno(soap->master);
  6501. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR);
  6502. return SOAP_INVALID_SOCKET;
  6503. }
  6504. #endif
  6505. #ifdef TCP_FASTOPEN
  6506. if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->master, IPPROTO_TCP, TCP_FASTOPEN, (char*)&set, sizeof(int)))
  6507. {
  6508. /* silently ignore */
  6509. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "setsockopt TCP_FASTOPEN failed in soap_bind()\n"));
  6510. }
  6511. #endif
  6512. #endif
  6513. #endif
  6514. #ifdef WITH_IPV6
  6515. if (res.ai_family == AF_INET6 && setsockopt(soap->master, IPPROTO_IPV6, IPV6_V6ONLY, soap->bind_v6only ? (char*)&set : (char*)&unset, sizeof(int)))
  6516. {
  6517. soap->errnum = soap_socket_errno(soap->master);
  6518. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR);
  6519. return SOAP_INVALID_SOCKET;
  6520. }
  6521. soap->errmode = 0;
  6522. if (bind(soap->master, res.ai_addr, (int)res.ai_addrlen))
  6523. {
  6524. soap->errnum = soap_socket_errno(soap->master);
  6525. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host, bind failed\n"));
  6526. soap_closesock(soap);
  6527. soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
  6528. return SOAP_INVALID_SOCKET;
  6529. }
  6530. #else
  6531. soap->peerlen = sizeof(soap->peer.in);
  6532. memset((void*)&soap->peer.in, 0, sizeof(soap->peer.in));
  6533. soap->peer.in.sin_family = AF_INET;
  6534. soap->errmode = 2;
  6535. if (host)
  6536. {
  6537. if (soap->fresolve(soap, host, &soap->peer.in.sin_addr))
  6538. {
  6539. soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR);
  6540. return SOAP_INVALID_SOCKET;
  6541. }
  6542. }
  6543. else
  6544. soap->peer.in.sin_addr.s_addr = htonl(INADDR_ANY);
  6545. soap->peer.in.sin_port = htons((short)port);
  6546. soap->errmode = 0;
  6547. if (bind(soap->master, &soap->peer.addr, (int)soap->peerlen))
  6548. {
  6549. soap->errnum = soap_socket_errno(soap->master);
  6550. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host, bind failed\n"));
  6551. soap_closesock(soap);
  6552. soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
  6553. return SOAP_INVALID_SOCKET;
  6554. }
  6555. #endif
  6556. if (!(soap->omode & SOAP_IO_UDP) && listen(soap->master, backlog))
  6557. {
  6558. soap->errnum = soap_socket_errno(soap->master);
  6559. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host, listen failed\n"));
  6560. soap_closesock(soap);
  6561. soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR);
  6562. return SOAP_INVALID_SOCKET;
  6563. }
  6564. return soap->master;
  6565. }
  6566. #endif
  6567. /******************************************************************************/
  6568. #ifndef WITH_NOIO
  6569. SOAP_FMAC1
  6570. int
  6571. SOAP_FMAC2
  6572. soap_poll(struct soap *soap)
  6573. {
  6574. #ifndef WITH_LEAN
  6575. int r;
  6576. if (soap_valid_socket(soap->socket))
  6577. {
  6578. r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ALL, 0);
  6579. if (r > 0 && (r & SOAP_TCP_SELECT_ERR))
  6580. r = -1;
  6581. }
  6582. else if (soap_valid_socket(soap->master))
  6583. {
  6584. r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, 0);
  6585. }
  6586. else
  6587. {
  6588. return SOAP_OK; /* OK when no socket! */
  6589. }
  6590. if (r > 0)
  6591. {
  6592. int t;
  6593. #ifdef WITH_OPENSSL
  6594. if ((soap->imode & SOAP_ENC_SSL))
  6595. {
  6596. if (soap_valid_socket(soap->socket)
  6597. && (r & SOAP_TCP_SELECT_SND)
  6598. && (!(r & SOAP_TCP_SELECT_RCV)
  6599. || SSL_peek(soap->ssl, (char*)&t, 1) > 0))
  6600. return SOAP_OK;
  6601. }
  6602. else
  6603. #endif
  6604. {
  6605. if (soap_valid_socket(soap->socket)
  6606. && (r & SOAP_TCP_SELECT_SND)
  6607. && (!(r & SOAP_TCP_SELECT_RCV)
  6608. || recv(soap->socket, (char*)&t, 1, MSG_PEEK) > 0))
  6609. return SOAP_OK;
  6610. }
  6611. }
  6612. else if (r < 0)
  6613. {
  6614. if ((soap_valid_socket(soap->master) && soap_socket_errno(soap->master) != SOAP_EINTR)
  6615. || (soap_valid_socket(soap->socket) && soap_socket_errno(soap->socket) != SOAP_EINTR))
  6616. return soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR);
  6617. }
  6618. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_poll: other end down on socket=%d select=%d\n", (int)soap->socket, r));
  6619. return SOAP_EOF;
  6620. #else
  6621. (void)soap;
  6622. return SOAP_OK;
  6623. #endif
  6624. }
  6625. #endif
  6626. /******************************************************************************/
  6627. #ifndef WITH_NOIO
  6628. SOAP_FMAC1
  6629. int
  6630. SOAP_FMAC2
  6631. soap_ready(struct soap *soap)
  6632. {
  6633. #ifndef WITH_LEAN
  6634. int r;
  6635. if (!soap_valid_socket(soap->socket))
  6636. return SOAP_OK; /* OK when no socket! */
  6637. r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, 0);
  6638. if (r > 0 && (r & SOAP_TCP_SELECT_ERR))
  6639. r = -1;
  6640. if (r < 0 && soap_socket_errno(soap->socket) != SOAP_EINTR)
  6641. return soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_ready()", SOAP_TCP_ERROR);
  6642. if (r > 0)
  6643. {
  6644. char t;
  6645. #ifdef WITH_OPENSSL
  6646. if ((soap->imode & SOAP_ENC_SSL))
  6647. {
  6648. if (SSL_peek(soap->ssl, &t, 1) > 0)
  6649. return SOAP_OK;
  6650. }
  6651. else
  6652. #endif
  6653. {
  6654. if (recv(soap->socket, &t, 1, MSG_PEEK) > 0)
  6655. return SOAP_OK;
  6656. }
  6657. }
  6658. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_ready: other end not ready to send on socket=%d select=%d\n", (int)soap->socket, r));
  6659. return SOAP_EOF;
  6660. #else
  6661. (void)soap;
  6662. return SOAP_OK;
  6663. #endif
  6664. }
  6665. #endif
  6666. /******************************************************************************/
  6667. #ifndef WITH_NOIO
  6668. SOAP_FMAC1
  6669. SOAP_SOCKET
  6670. SOAP_FMAC2
  6671. soap_accept(struct soap *soap)
  6672. {
  6673. int n = (int)sizeof(soap->peer);
  6674. int err;
  6675. #ifndef WITH_LEAN
  6676. int set = 1;
  6677. #endif
  6678. soap->error = SOAP_OK;
  6679. memset((void*)&soap->peer, 0, sizeof(soap->peer));
  6680. soap->socket = SOAP_INVALID_SOCKET;
  6681. soap->errmode = 0;
  6682. soap->errnum = 0;
  6683. soap->keep_alive = 0;
  6684. if (!soap_valid_socket(soap->master))
  6685. {
  6686. soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR);
  6687. return SOAP_INVALID_SOCKET;
  6688. }
  6689. #ifndef WITH_LEAN
  6690. if ((soap->omode & SOAP_IO_UDP))
  6691. return soap->socket = soap->master;
  6692. #endif
  6693. for (;;)
  6694. {
  6695. if (soap->accept_timeout)
  6696. {
  6697. for (;;)
  6698. {
  6699. int r;
  6700. r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_ALL, soap->accept_timeout);
  6701. if (r > 0)
  6702. break;
  6703. if (!r)
  6704. {
  6705. soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR);
  6706. return SOAP_INVALID_SOCKET;
  6707. }
  6708. if (r < 0)
  6709. {
  6710. r = soap->errnum;
  6711. if (r != SOAP_EINTR)
  6712. {
  6713. soap_closesock(soap);
  6714. soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
  6715. return SOAP_INVALID_SOCKET;
  6716. }
  6717. }
  6718. }
  6719. }
  6720. n = (int)sizeof(soap->peer);
  6721. soap->socket = soap->faccept(soap, soap->master, &soap->peer.addr, &n);
  6722. soap->peerlen = (size_t)n;
  6723. if (soap_valid_socket(soap->socket))
  6724. {
  6725. #ifdef WITH_IPV6
  6726. char port[16];
  6727. struct addrinfo *res = NULL;
  6728. struct addrinfo hints;
  6729. memset(&hints, 0, sizeof(struct addrinfo));
  6730. hints.ai_family = PF_UNSPEC;
  6731. hints.ai_socktype = SOCK_STREAM;
  6732. hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
  6733. getnameinfo(&soap->peer.addr, n, soap->host, sizeof(soap->host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
  6734. soap->ip = 0;
  6735. soap->ip6[0] = 0;
  6736. soap->ip6[1] = 0;
  6737. soap->ip6[2] = 0;
  6738. soap->ip6[3] = 0;
  6739. if (getaddrinfo(soap->host, NULL, &hints, &res) == 0 && res)
  6740. {
  6741. struct sockaddr_storage result;
  6742. soap_memcpy(&result, sizeof(result), res->ai_addr, res->ai_addrlen);
  6743. freeaddrinfo(res);
  6744. if (result.ss_family == AF_INET6)
  6745. {
  6746. struct sockaddr_in6 *addr = (struct sockaddr_in6*)&result;
  6747. struct in6_addr *inaddr = &addr->sin6_addr;
  6748. int i;
  6749. for (i = 0; i < 16; i++)
  6750. soap->ip6[i/4] = (soap->ip6[i/4] << 8) + inaddr->s6_addr[i];
  6751. }
  6752. else if (result.ss_family == AF_INET)
  6753. {
  6754. struct sockaddr_in *addr = (struct sockaddr_in*)&result;
  6755. soap->ip = ntohl(addr->sin_addr.s_addr);
  6756. soap->ip6[2] = 0xFFFF;
  6757. soap->ip6[3] = soap->ip;
  6758. }
  6759. }
  6760. soap->port = soap_strtol(port, NULL, 10);
  6761. #else
  6762. soap->ip = ntohl(soap->peer.in.sin_addr.s_addr);
  6763. soap->ip6[0] = 0;
  6764. soap->ip6[1] = 0;
  6765. soap->ip6[2] = 0xFFFF;
  6766. soap->ip6[3] = soap->ip;
  6767. (SOAP_SNPRINTF(soap->host, sizeof(soap->host), 80), "%u.%u.%u.%u", (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF);
  6768. soap->port = (int)ntohs(soap->peer.in.sin_port); /* does not return port number on some systems */
  6769. #endif
  6770. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Accept socket=%d at port=%d from IP='%s'\n", (int)soap->socket, soap->port, soap->host));
  6771. #ifndef WITH_LEAN
  6772. if ((soap->accept_flags & SO_LINGER))
  6773. {
  6774. struct linger linger;
  6775. memset((void*)&linger, 0, sizeof(linger));
  6776. linger.l_onoff = 1;
  6777. linger.l_linger = soap->linger_time;
  6778. if (setsockopt(soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
  6779. {
  6780. soap->errnum = soap_socket_errno(soap->socket);
  6781. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR);
  6782. soap_closesock(soap);
  6783. return SOAP_INVALID_SOCKET;
  6784. }
  6785. }
  6786. if ((soap->accept_flags & ~SO_LINGER) && setsockopt(soap->socket, SOL_SOCKET, soap->accept_flags & ~SO_LINGER, (char*)&set, sizeof(int)))
  6787. {
  6788. soap->errnum = soap_socket_errno(soap->socket);
  6789. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR);
  6790. soap_closesock(soap);
  6791. return SOAP_INVALID_SOCKET;
  6792. }
  6793. #ifndef UNDER_CE
  6794. if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
  6795. {
  6796. soap->errnum = soap_socket_errno(soap->socket);
  6797. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR);
  6798. soap_closesock(soap);
  6799. return SOAP_INVALID_SOCKET;
  6800. }
  6801. if (soap->sndbuf > 0 && setsockopt(soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&soap->sndbuf, sizeof(int)))
  6802. {
  6803. soap->errnum = soap_socket_errno(soap->socket);
  6804. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR);
  6805. soap_closesock(soap);
  6806. return SOAP_INVALID_SOCKET;
  6807. }
  6808. if (soap->rcvbuf > 0 && setsockopt(soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&soap->rcvbuf, sizeof(int)))
  6809. {
  6810. soap->errnum = soap_socket_errno(soap->socket);
  6811. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR);
  6812. soap_closesock(soap);
  6813. return SOAP_INVALID_SOCKET;
  6814. }
  6815. #ifdef TCP_NODELAY
  6816. if (setsockopt(soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
  6817. {
  6818. soap->errnum = soap_socket_errno(soap->socket);
  6819. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR);
  6820. soap_closesock(soap);
  6821. return SOAP_INVALID_SOCKET;
  6822. }
  6823. #endif
  6824. #endif
  6825. #endif
  6826. soap->keep_alive = -(((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
  6827. if (soap->send_timeout || soap->recv_timeout)
  6828. SOAP_SOCKNONBLOCK(soap->socket)
  6829. else
  6830. SOAP_SOCKBLOCK(soap->socket)
  6831. return soap->socket;
  6832. }
  6833. err = soap_socket_errno(soap->socket);
  6834. if (err != 0 && err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
  6835. {
  6836. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host));
  6837. soap->errnum = err;
  6838. soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
  6839. soap_closesock(soap);
  6840. return SOAP_INVALID_SOCKET;
  6841. }
  6842. }
  6843. }
  6844. #endif
  6845. /******************************************************************************/
  6846. SOAP_FMAC1
  6847. int
  6848. SOAP_FMAC2
  6849. soap_closesock(struct soap *soap)
  6850. {
  6851. int status = soap->error;
  6852. int err = SOAP_OK;
  6853. soap->part = SOAP_END;
  6854. #ifndef WITH_LEANER
  6855. if (status && status < 200) /* attachment state is not to be trusted */
  6856. {
  6857. soap->mime.first = NULL;
  6858. soap->mime.last = NULL;
  6859. soap->dime.first = NULL;
  6860. soap->dime.last = NULL;
  6861. }
  6862. #endif
  6863. if (soap->fdisconnect)
  6864. err = soap->fdisconnect(soap);
  6865. if (err || status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive)
  6866. {
  6867. soap->keep_alive = 0;
  6868. if (soap->fclose && (soap->error = soap->fclose(soap)) != SOAP_OK)
  6869. return soap->error;
  6870. if (err)
  6871. return soap->error = err;
  6872. }
  6873. #ifdef WITH_ZLIB
  6874. if (!(soap->mode & SOAP_MIME_POSTCHECK))
  6875. {
  6876. if (soap->zlib_state == SOAP_ZLIB_DEFLATE)
  6877. deflateEnd(soap->d_stream);
  6878. else if (soap->zlib_state == SOAP_ZLIB_INFLATE)
  6879. inflateEnd(soap->d_stream);
  6880. soap->zlib_state = SOAP_ZLIB_NONE;
  6881. }
  6882. #endif
  6883. return soap->error = status;
  6884. }
  6885. /******************************************************************************/
  6886. SOAP_FMAC1
  6887. int
  6888. SOAP_FMAC2
  6889. soap_force_closesock(struct soap *soap)
  6890. {
  6891. soap->keep_alive = 0;
  6892. if (soap_valid_socket(soap->socket) && soap->fclosesocket)
  6893. {
  6894. soap->fclosesocket(soap, soap->socket);
  6895. soap->socket = SOAP_INVALID_SOCKET;
  6896. }
  6897. return soap->error;
  6898. }
  6899. /******************************************************************************/
  6900. #ifdef WITH_SELF_PIPE
  6901. SOAP_FMAC1
  6902. void
  6903. SOAP_FMAC2
  6904. soap_close_connection(struct soap *soap)
  6905. {
  6906. if (soap_valid_socket(soap->socket))
  6907. write(soap->pipe_fd[1], "1", 1);
  6908. }
  6909. #endif
  6910. /******************************************************************************/
  6911. #ifndef WITH_NOIO
  6912. SOAP_FMAC1
  6913. void
  6914. SOAP_FMAC2
  6915. soap_cleanup(struct soap *soap)
  6916. {
  6917. soap_done(soap);
  6918. #ifdef WIN32
  6919. if (!tcp_done)
  6920. return;
  6921. tcp_done = 0;
  6922. WSACleanup();
  6923. #endif
  6924. }
  6925. #endif
  6926. /******************************************************************************/
  6927. SOAP_FMAC1
  6928. void
  6929. SOAP_FMAC2
  6930. soap_done(struct soap *soap)
  6931. {
  6932. #ifdef SOAP_DEBUG
  6933. int i;
  6934. #endif
  6935. if (soap_check_state(soap))
  6936. return;
  6937. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context%s\n", soap->state == SOAP_COPY ? " copy" : ""));
  6938. soap_free_temp(soap);
  6939. while (soap->clist)
  6940. {
  6941. struct soap_clist *p = soap->clist->next;
  6942. SOAP_FREE(soap, soap->clist);
  6943. soap->clist = p;
  6944. }
  6945. if (soap->state == SOAP_INIT)
  6946. soap->omode &= ~SOAP_IO_UDP; /* to force close the socket */
  6947. soap->keep_alive = 0; /* to force close the socket */
  6948. if (soap->master == soap->socket) /* do not close twice */
  6949. soap->master = SOAP_INVALID_SOCKET;
  6950. soap_closesock(soap);
  6951. #ifdef WITH_COOKIES
  6952. soap_free_cookies(soap);
  6953. #endif
  6954. while (soap->plugins)
  6955. {
  6956. struct soap_plugin *p = soap->plugins->next;
  6957. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id));
  6958. if (soap->plugins->fcopy || soap->state == SOAP_INIT)
  6959. soap->plugins->fdelete(soap, soap->plugins);
  6960. SOAP_FREE(soap, soap->plugins);
  6961. soap->plugins = p;
  6962. }
  6963. soap->fplugin = fplugin;
  6964. #ifndef WITH_NOHTTP
  6965. soap->fpost = http_post;
  6966. soap->fget = http_get;
  6967. soap->fput = http_put;
  6968. soap->fpatch = http_patch;
  6969. soap->fdel = http_del;
  6970. soap->fopt = http_200;
  6971. soap->fhead = http_200;
  6972. soap->fform = NULL;
  6973. soap->fposthdr = http_post_header;
  6974. soap->fresponse = http_response;
  6975. soap->fparse = http_parse;
  6976. soap->fparsehdr = http_parse_header;
  6977. #endif
  6978. soap->fheader = NULL;
  6979. #ifndef WITH_NOIO
  6980. #ifndef WITH_IPV6
  6981. soap->fresolve = tcp_gethost;
  6982. #else
  6983. soap->fresolve = NULL;
  6984. #endif
  6985. soap->faccept = tcp_accept;
  6986. soap->fopen = tcp_connect;
  6987. soap->fclose = tcp_disconnect;
  6988. soap->fclosesocket = tcp_closesocket;
  6989. soap->fshutdownsocket = tcp_shutdownsocket;
  6990. soap->fsend = fsend;
  6991. soap->frecv = frecv;
  6992. soap->fpoll = soap_poll;
  6993. #else
  6994. soap->fopen = NULL;
  6995. soap->fclose = NULL;
  6996. soap->fpoll = NULL;
  6997. #endif
  6998. #ifndef WITH_LEANER
  6999. soap->fsvalidate = NULL;
  7000. soap->fwvalidate = NULL;
  7001. soap->feltbegin = NULL;
  7002. soap->feltendin = NULL;
  7003. soap->feltbegout = NULL;
  7004. soap->feltendout = NULL;
  7005. soap->fprepareinitsend = NULL;
  7006. soap->fprepareinitrecv = NULL;
  7007. soap->fpreparesend = NULL;
  7008. soap->fpreparerecv = NULL;
  7009. soap->fpreparefinalsend = NULL;
  7010. soap->fpreparefinalrecv = NULL;
  7011. soap->ffiltersend = NULL;
  7012. soap->ffilterrecv = NULL;
  7013. #endif
  7014. soap->fseterror = NULL;
  7015. soap->fignore = NULL;
  7016. soap->fserveloop = NULL;
  7017. #ifdef WITH_OPENSSL
  7018. if (soap->session)
  7019. {
  7020. SSL_SESSION_free(soap->session);
  7021. soap->session = NULL;
  7022. }
  7023. #endif
  7024. if (soap->state == SOAP_INIT)
  7025. {
  7026. if (soap_valid_socket(soap->master))
  7027. {
  7028. soap->fclosesocket(soap, soap->master);
  7029. soap->master = SOAP_INVALID_SOCKET;
  7030. }
  7031. }
  7032. #ifdef WITH_OPENSSL
  7033. if (soap->ssl)
  7034. {
  7035. SSL_free(soap->ssl);
  7036. soap->ssl = NULL;
  7037. }
  7038. if (soap->state == SOAP_INIT)
  7039. {
  7040. if (soap->ctx)
  7041. {
  7042. SSL_CTX_free(soap->ctx);
  7043. soap->ctx = NULL;
  7044. }
  7045. }
  7046. ERR_clear_error();
  7047. # if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
  7048. /* OpenSSL libraries handle thread init and deinit */
  7049. # elif OPENSSL_VERSION_NUMBER >= 0x10000000L
  7050. ERR_remove_thread_state(NULL);
  7051. # else
  7052. ERR_remove_state(0);
  7053. # endif
  7054. #endif
  7055. #ifdef WITH_GNUTLS
  7056. if (soap->state == SOAP_INIT)
  7057. {
  7058. if (soap->xcred)
  7059. {
  7060. gnutls_certificate_free_credentials(soap->xcred);
  7061. soap->xcred = NULL;
  7062. }
  7063. if (soap->acred)
  7064. {
  7065. gnutls_anon_free_client_credentials(soap->acred);
  7066. soap->acred = NULL;
  7067. }
  7068. if (soap->cache)
  7069. {
  7070. gnutls_priority_deinit(soap->cache);
  7071. soap->cache = NULL;
  7072. }
  7073. if (soap->dh_params)
  7074. {
  7075. gnutls_dh_params_deinit(soap->dh_params);
  7076. soap->dh_params = NULL;
  7077. }
  7078. # if GNUTLS_VERSION_NUMBER < 0x030300
  7079. if (soap->rsa_params)
  7080. {
  7081. gnutls_rsa_params_deinit(soap->rsa_params);
  7082. soap->rsa_params = NULL;
  7083. }
  7084. #endif
  7085. }
  7086. if (soap->session)
  7087. {
  7088. gnutls_deinit(soap->session);
  7089. soap->session = NULL;
  7090. }
  7091. #endif
  7092. #ifdef WITH_SYSTEMSSL
  7093. if (soap->ssl)
  7094. gsk_secure_socket_close(&soap->ssl);
  7095. if (soap->state == SOAP_INIT)
  7096. if (soap->ctx)
  7097. gsk_environment_close(&soap->ctx);
  7098. #endif
  7099. #ifdef WITH_C_LOCALE
  7100. SOAP_FREELOCALE(soap);
  7101. #endif
  7102. #ifdef WITH_ZLIB
  7103. if (soap->d_stream)
  7104. {
  7105. SOAP_FREE(soap, soap->d_stream);
  7106. soap->d_stream = NULL;
  7107. }
  7108. if (soap->z_buf)
  7109. {
  7110. SOAP_FREE(soap, soap->z_buf);
  7111. soap->z_buf = NULL;
  7112. }
  7113. #endif
  7114. #ifdef SOAP_DEBUG
  7115. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n"));
  7116. for (i = 0; i < SOAP_MAXLOGS; i++)
  7117. {
  7118. soap_close_logfile(soap, i);
  7119. if (soap->logfile[i])
  7120. {
  7121. SOAP_FREE_UNMANAGED(soap->logfile[i]);
  7122. soap->logfile[i] = NULL;
  7123. }
  7124. }
  7125. #endif
  7126. #ifdef WITH_SELF_PIPE
  7127. close(soap->pipe_fd[0]);
  7128. close(soap->pipe_fd[1]);
  7129. #endif
  7130. #ifdef SOAP_MEM_DEBUG
  7131. soap_free_mht(soap);
  7132. #endif
  7133. soap->state = SOAP_NONE;
  7134. }
  7135. /******************************************************************************\
  7136. *
  7137. * HTTP
  7138. *
  7139. \******************************************************************************/
  7140. #ifndef WITH_NOHTTP
  7141. static int
  7142. http_parse(struct soap *soap)
  7143. {
  7144. char header[SOAP_HDRLEN], *s;
  7145. int err = SOAP_OK;
  7146. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n"));
  7147. soap->fform = NULL;
  7148. *soap->endpoint = '\0';
  7149. soap->bearer = NULL;
  7150. #ifdef WITH_NTLM
  7151. if (!soap->ntlm_challenge)
  7152. #endif
  7153. {
  7154. soap->userid = NULL;
  7155. soap->passwd = NULL;
  7156. soap->authrealm = NULL;
  7157. }
  7158. #ifdef WITH_NTLM
  7159. soap->ntlm_challenge = NULL;
  7160. #endif
  7161. soap->proxy_from = NULL;
  7162. soap->cors_origin = NULL;
  7163. soap->cors_method = NULL;
  7164. soap->cors_header = NULL;
  7165. do
  7166. {
  7167. soap->length = 0;
  7168. soap->http_content = NULL;
  7169. soap->action = NULL;
  7170. soap->status = 0;
  7171. soap->body = 1;
  7172. if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
  7173. {
  7174. if (soap->error == SOAP_EOF)
  7175. return SOAP_EOF;
  7176. return soap->error = 414;
  7177. }
  7178. s = strchr(soap->msgbuf, ' ');
  7179. if (s)
  7180. {
  7181. soap->status = (unsigned short)soap_strtoul(s, &s, 10);
  7182. if (!soap_coblank((soap_wchar)*s))
  7183. soap->status = 0;
  7184. }
  7185. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf));
  7186. for (;;)
  7187. {
  7188. if (soap_getline(soap, header, SOAP_HDRLEN))
  7189. {
  7190. if (soap->error == SOAP_EOF)
  7191. {
  7192. soap->error = SOAP_OK;
  7193. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "EOF in HTTP header, try to continue anyway\n"));
  7194. break;
  7195. }
  7196. return soap->error;
  7197. }
  7198. if (!*header)
  7199. break;
  7200. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header));
  7201. s = strchr(header, ':');
  7202. if (s)
  7203. {
  7204. char *t;
  7205. *s = '\0';
  7206. do
  7207. {
  7208. s++;
  7209. } while (*s && *s <= 32);
  7210. if (*s == '"')
  7211. s++;
  7212. t = s + strlen(s) - 1;
  7213. while (t > s && *t <= 32)
  7214. t--;
  7215. if (t >= s && *t == '"')
  7216. t--;
  7217. t[1] = '\0';
  7218. soap->error = soap->fparsehdr(soap, header, s);
  7219. if (soap->error)
  7220. {
  7221. if (soap->error < SOAP_STOP)
  7222. return soap->error;
  7223. err = soap->error;
  7224. soap->error = SOAP_OK;
  7225. }
  7226. }
  7227. }
  7228. } while (soap->status == 100);
  7229. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Finished HTTP header parsing, status = %d\n", soap->status));
  7230. s = strstr(soap->msgbuf, "HTTP/");
  7231. if (s && s[5] == '1' && s[6] == '.' && s[7] == '0')
  7232. {
  7233. soap->keep_alive = 0; /* HTTP 1.0 does not support keep-alive */
  7234. if (soap->status == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* soap->status == 0 for HTTP request */
  7235. soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; /* HTTP 1.0 does not support chunked transfers */
  7236. }
  7237. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive));
  7238. if (soap->status == 0)
  7239. {
  7240. size_t l = 0;
  7241. if (s)
  7242. {
  7243. if (!strncmp(soap->msgbuf, "POST ", l = 5))
  7244. soap->status = SOAP_POST;
  7245. else if (!strncmp(soap->msgbuf, "GET ", l = 4))
  7246. soap->status = SOAP_GET;
  7247. else if (!strncmp(soap->msgbuf, "PUT ", l = 4))
  7248. soap->status = SOAP_PUT;
  7249. else if (!strncmp(soap->msgbuf, "PATCH ", l = 4))
  7250. soap->status = SOAP_PATCH;
  7251. else if (!strncmp(soap->msgbuf, "DELETE ", l = 7))
  7252. soap->status = SOAP_DEL;
  7253. else if (!strncmp(soap->msgbuf, "HEAD ", l = 5))
  7254. soap->status = SOAP_HEAD;
  7255. else if (!strncmp(soap->msgbuf, "OPTIONS ", l = 8))
  7256. soap->status = SOAP_OPTIONS;
  7257. }
  7258. if (s && soap->status)
  7259. {
  7260. size_t m, n, k;
  7261. int r;
  7262. while (soap->msgbuf[l] && soap_coblank((soap_wchar)soap->msgbuf[l]))
  7263. l++;
  7264. m = strlen(soap->endpoint);
  7265. n = m + (s - soap->msgbuf) - l - 1;
  7266. if (n >= sizeof(soap->endpoint))
  7267. n = sizeof(soap->endpoint) - 1;
  7268. if (m > n)
  7269. m = n;
  7270. k = n - m + 1;
  7271. if (k >= sizeof(soap->path))
  7272. k = sizeof(soap->path) - 1;
  7273. while (k > 0 && soap_coblank((soap_wchar)soap->msgbuf[l + k - 1]))
  7274. k--;
  7275. if (soap_strncpy(soap->path, sizeof(soap->path), soap->msgbuf + l, k))
  7276. return soap->error = 414;
  7277. if (*soap->path && *soap->path != '/')
  7278. r = soap_strncpy(soap->endpoint, sizeof(soap->endpoint), soap->path, k);
  7279. else
  7280. r = soap_strncat(soap->endpoint, sizeof(soap->endpoint), soap->path, k);
  7281. if (r)
  7282. return soap->error = 414;
  7283. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Target endpoint='%s' path='%s'\n", soap->endpoint, soap->path));
  7284. if (err)
  7285. return soap->error = err;
  7286. }
  7287. else if (err)
  7288. {
  7289. return soap->error = err;
  7290. }
  7291. else if (s)
  7292. {
  7293. return soap->error = 405;
  7294. }
  7295. return SOAP_OK;
  7296. }
  7297. if ((soap->status >= 200 && soap->status <= 299) /* OK, Accepted, etc */
  7298. || soap->status == 400 /* Bad Request */
  7299. || soap->status == 500) /* Internal Server Error */
  7300. return soap->error = SOAP_OK;
  7301. return soap->error = soap->status;
  7302. }
  7303. #endif
  7304. /******************************************************************************/
  7305. #ifndef WITH_NOHTTP
  7306. static int
  7307. http_parse_header(struct soap *soap, const char *key, const char *val)
  7308. {
  7309. if (!soap_tag_cmp(key, "Host"))
  7310. {
  7311. #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
  7312. if ((soap->imode & SOAP_ENC_SSL))
  7313. soap_strcpy(soap->endpoint, sizeof(soap->endpoint), "https://");
  7314. else
  7315. #endif
  7316. soap_strcpy(soap->endpoint, sizeof(soap->endpoint), "http://");
  7317. if (soap_strncat(soap->endpoint, sizeof(soap->endpoint), val, sizeof(soap->endpoint) - 9))
  7318. return soap->error = SOAP_HDR;
  7319. }
  7320. #ifndef WITH_LEANER
  7321. else if (!soap_tag_cmp(key, "Content-Type"))
  7322. {
  7323. const char *action;
  7324. soap->http_content = soap_strdup(soap, val);
  7325. if (soap_http_header_attribute(soap, val, "application/dime"))
  7326. soap->imode |= SOAP_ENC_DIME;
  7327. else if (soap_http_header_attribute(soap, val, "multipart/related")
  7328. || soap_http_header_attribute(soap, val, "multipart/form-data"))
  7329. {
  7330. const char *type;
  7331. soap->mime.boundary = soap_strdup(soap, soap_http_header_attribute(soap, val, "boundary"));
  7332. soap->mime.start = soap_strdup(soap, soap_http_header_attribute(soap, val, "start"));
  7333. soap->imode |= SOAP_ENC_MIME;
  7334. type = soap_http_header_attribute(soap, val, "type");
  7335. if (type && !strcmp(type, "application/xop+xml"))
  7336. soap->imode |= SOAP_ENC_MTOM;
  7337. }
  7338. action = soap_http_header_attribute(soap, val, "action");
  7339. if (action)
  7340. {
  7341. if (*action == '"')
  7342. {
  7343. soap->action = soap_strdup(soap, action + 1);
  7344. if (soap->action && *soap->action)
  7345. soap->action[strlen(soap->action) - 1] = '\0';
  7346. }
  7347. else
  7348. soap->action = soap_strdup(soap, action);
  7349. }
  7350. }
  7351. #endif
  7352. else if (!soap_tag_cmp(key, "Content-Length"))
  7353. {
  7354. soap->length = soap_strtoull(val, NULL, 10);
  7355. if (soap->length == 0)
  7356. soap->body = 0;
  7357. }
  7358. else if (!soap_tag_cmp(key, "Content-Encoding"))
  7359. {
  7360. if (!soap_tag_cmp(val, "deflate"))
  7361. #ifdef WITH_ZLIB
  7362. soap->zlib_in = SOAP_ZLIB_DEFLATE;
  7363. #else
  7364. return SOAP_ZLIB_ERROR;
  7365. #endif
  7366. else if (!soap_tag_cmp(val, "gzip"))
  7367. #ifdef WITH_GZIP
  7368. soap->zlib_in = SOAP_ZLIB_GZIP;
  7369. #else
  7370. return SOAP_ZLIB_ERROR;
  7371. #endif
  7372. }
  7373. #ifdef WITH_ZLIB
  7374. else if (!soap_tag_cmp(key, "Accept-Encoding"))
  7375. {
  7376. #ifdef WITH_GZIP
  7377. if (strchr(val, '*') || soap_http_header_attribute(soap, val, "gzip"))
  7378. soap->zlib_out = SOAP_ZLIB_GZIP;
  7379. else
  7380. #endif
  7381. if (strchr(val, '*') || soap_http_header_attribute(soap, val, "deflate"))
  7382. soap->zlib_out = SOAP_ZLIB_DEFLATE;
  7383. else
  7384. soap->zlib_out = SOAP_ZLIB_NONE;
  7385. }
  7386. #endif
  7387. else if (!soap_tag_cmp(key, "Transfer-Encoding"))
  7388. {
  7389. soap->imode &= ~SOAP_IO;
  7390. if (!soap_tag_cmp(val, "chunked"))
  7391. soap->imode |= SOAP_IO_CHUNK;
  7392. }
  7393. else if (!soap_tag_cmp(key, "Connection"))
  7394. {
  7395. if (!soap_tag_cmp(val, "close"))
  7396. soap->keep_alive = 0;
  7397. }
  7398. #if !defined(WITH_LEAN) || defined(WITH_NTLM)
  7399. else if (!soap_tag_cmp(key, "Authorization") || !soap_tag_cmp(key, "Proxy-Authorization"))
  7400. {
  7401. #ifdef WITH_NTLM
  7402. if (!soap_tag_cmp(val, "NTLM*"))
  7403. {
  7404. soap->ntlm_challenge = soap_strdup(soap, val + 4);
  7405. }
  7406. else
  7407. #endif
  7408. if (!soap_tag_cmp(val, "Bearer *"))
  7409. {
  7410. soap->bearer = soap_strdup(soap, val + 7);
  7411. }
  7412. else if (!soap_tag_cmp(val, "Basic *"))
  7413. {
  7414. int n;
  7415. char *s;
  7416. soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n);
  7417. soap->tmpbuf[n] = '\0';
  7418. s = strchr(soap->tmpbuf, ':');
  7419. if (s)
  7420. {
  7421. *s = '\0';
  7422. soap->userid = soap_strdup(soap, soap->tmpbuf);
  7423. soap->passwd = soap_strdup(soap, s + 1);
  7424. }
  7425. }
  7426. }
  7427. else if (!soap_tag_cmp(key, "WWW-Authenticate") || !soap_tag_cmp(key, "Proxy-Authenticate"))
  7428. {
  7429. #ifdef WITH_NTLM
  7430. if (!soap_tag_cmp(val, "NTLM*"))
  7431. soap->ntlm_challenge = soap_strdup(soap, val + 4);
  7432. else
  7433. #endif
  7434. soap->authrealm = soap_strdup(soap, soap_http_header_attribute(soap, val + 6, "realm"));
  7435. }
  7436. else if (!soap_tag_cmp(key, "Expect"))
  7437. {
  7438. if (!soap_tag_cmp(val, "100-continue"))
  7439. {
  7440. if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL)) != SOAP_OK
  7441. || (soap->error = soap->fposthdr(soap, NULL, NULL)) != SOAP_OK)
  7442. return soap->error;
  7443. }
  7444. }
  7445. #endif
  7446. else if (!soap_tag_cmp(key, "SOAPAction"))
  7447. {
  7448. if (*val == '"')
  7449. {
  7450. soap->action = soap_strdup(soap, val + 1);
  7451. if (*soap->action)
  7452. soap->action[strlen(soap->action) - 1] = '\0';
  7453. }
  7454. else
  7455. soap->action = soap_strdup(soap, val);
  7456. }
  7457. else if (!soap_tag_cmp(key, "Location"))
  7458. {
  7459. soap_strcpy(soap->endpoint, sizeof(soap->endpoint), val);
  7460. }
  7461. else if (!soap_tag_cmp(key, "X-Forwarded-For"))
  7462. {
  7463. soap->proxy_from = soap_strdup(soap, val);
  7464. }
  7465. else if (!soap_tag_cmp(key, "Origin"))
  7466. {
  7467. soap->origin = soap_strdup(soap, val);
  7468. soap->cors_origin = soap->cors_allow;
  7469. }
  7470. else if (!soap_tag_cmp(key, "Access-Control-Request-Method"))
  7471. {
  7472. soap->cors_method = soap_strdup(soap, val);
  7473. }
  7474. else if (!soap_tag_cmp(key, "Access-Control-Request-Headers"))
  7475. {
  7476. soap->cors_header = soap_strdup(soap, val);
  7477. }
  7478. #ifdef WITH_COOKIES
  7479. else if (!soap_tag_cmp(key, "Cookie")
  7480. || !soap_tag_cmp(key, "Cookie2")
  7481. || !soap_tag_cmp(key, "Set-Cookie")
  7482. || !soap_tag_cmp(key, "Set-Cookie2"))
  7483. {
  7484. soap_getcookies(soap, val);
  7485. }
  7486. #endif
  7487. return SOAP_OK;
  7488. }
  7489. #endif
  7490. /******************************************************************************/
  7491. #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
  7492. SOAP_FMAC1
  7493. const char*
  7494. SOAP_FMAC2
  7495. soap_http_header_attribute(struct soap *soap, const char *line, const char *key)
  7496. {
  7497. const char *s = line;
  7498. if (s)
  7499. {
  7500. while (*s)
  7501. {
  7502. short flag;
  7503. s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s);
  7504. flag = soap_tag_cmp(soap->tmpbuf, key);
  7505. s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s);
  7506. if (!flag)
  7507. return soap->tmpbuf;
  7508. }
  7509. }
  7510. return NULL;
  7511. }
  7512. #endif
  7513. /******************************************************************************/
  7514. #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
  7515. SOAP_FMAC1
  7516. const char*
  7517. SOAP_FMAC2
  7518. soap_decode_key(char *buf, size_t len, const char *val)
  7519. {
  7520. return soap_decode(buf, len, val, "=,;");
  7521. }
  7522. #endif
  7523. /******************************************************************************/
  7524. #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
  7525. SOAP_FMAC1
  7526. const char*
  7527. SOAP_FMAC2
  7528. soap_decode_val(char *buf, size_t len, const char *val)
  7529. {
  7530. if (*val != '=')
  7531. {
  7532. *buf = '\0';
  7533. return val;
  7534. }
  7535. return soap_decode(buf, len, val + 1, ",;");
  7536. }
  7537. #endif
  7538. /******************************************************************************/
  7539. #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
  7540. static const char *
  7541. soap_decode(char *buf, size_t len, const char *val, const char *sep)
  7542. {
  7543. const char *s;
  7544. char *t = buf;
  7545. size_t i = len;
  7546. for (s = val; *s; s++)
  7547. if (*s != ' ' && *s != '\t' && !strchr(sep, *s))
  7548. break;
  7549. if (len > 0)
  7550. {
  7551. if (*s == '"')
  7552. {
  7553. s++;
  7554. while (*s && *s != '"' && --i)
  7555. *t++ = *s++;
  7556. }
  7557. else
  7558. {
  7559. while (*s && !strchr(sep, *s) && --i)
  7560. {
  7561. if (*s == '%' && s[1] && s[2])
  7562. {
  7563. *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4)
  7564. + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0');
  7565. s += 3;
  7566. }
  7567. else
  7568. *t++ = *s++;
  7569. }
  7570. }
  7571. buf[len - 1] = '\0'; /* appease static checkers that get confused */
  7572. }
  7573. *t = '\0';
  7574. while (*s && !strchr(sep, *s))
  7575. s++;
  7576. return s;
  7577. }
  7578. #endif
  7579. /******************************************************************************/
  7580. #ifndef WITH_NOHTTP
  7581. static const char*
  7582. http_error(struct soap *soap, int status)
  7583. {
  7584. const char *msg = SOAP_STR_EOS;
  7585. (void)soap;
  7586. (void)status;
  7587. #ifndef WITH_LEAN
  7588. msg = soap_code_str(h_http_error_codes, status);
  7589. if (!msg)
  7590. msg = SOAP_STR_EOS;
  7591. #endif
  7592. return msg;
  7593. }
  7594. #endif
  7595. /******************************************************************************/
  7596. #ifndef WITH_NOHTTP
  7597. static int
  7598. http_get(struct soap *soap)
  7599. {
  7600. (void)soap;
  7601. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP GET request\n"));
  7602. return SOAP_GET_METHOD;
  7603. }
  7604. #endif
  7605. /******************************************************************************/
  7606. #ifndef WITH_NOHTTP
  7607. static int
  7608. http_put(struct soap *soap)
  7609. {
  7610. (void)soap;
  7611. return SOAP_PUT_METHOD;
  7612. }
  7613. #endif
  7614. /******************************************************************************/
  7615. #ifndef WITH_NOHTTP
  7616. static int
  7617. http_patch(struct soap *soap)
  7618. {
  7619. (void)soap;
  7620. return SOAP_PATCH_METHOD;
  7621. }
  7622. #endif
  7623. /******************************************************************************/
  7624. #ifndef WITH_NOHTTP
  7625. static int
  7626. http_del(struct soap *soap)
  7627. {
  7628. (void)soap;
  7629. return SOAP_DEL_METHOD;
  7630. }
  7631. #endif
  7632. /******************************************************************************/
  7633. #ifndef WITH_NOHTTP
  7634. static int
  7635. http_200(struct soap *soap)
  7636. {
  7637. if (soap->origin && soap->cors_method) /* CORS Origin and Access-Control-Request-Method headers */
  7638. {
  7639. soap->cors_origin = soap->cors_allow; /* modify this code or hook your own soap->fopt() callback with logic */
  7640. soap->cors_methods = "GET, PUT, PATCH, POST, HEAD, OPTIONS";
  7641. soap->cors_headers = soap->cors_header;
  7642. }
  7643. return soap_send_empty_response(soap, 200);
  7644. }
  7645. #endif
  7646. /******************************************************************************/
  7647. #ifndef WITH_NOHTTP
  7648. static int
  7649. http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, ULONG64 count)
  7650. {
  7651. const char *s;
  7652. int err;
  7653. size_t l;
  7654. switch (soap->status)
  7655. {
  7656. case SOAP_GET:
  7657. s = "GET";
  7658. break;
  7659. case SOAP_PUT:
  7660. s = "PUT";
  7661. break;
  7662. case SOAP_PATCH:
  7663. s = "PATCH";
  7664. break;
  7665. case SOAP_DEL:
  7666. s = "DELETE";
  7667. break;
  7668. case SOAP_CONNECT:
  7669. s = "CONNECT";
  7670. break;
  7671. case SOAP_HEAD:
  7672. s = "HEAD";
  7673. break;
  7674. case SOAP_OPTIONS:
  7675. s = "OPTIONS";
  7676. break;
  7677. default:
  7678. s = "POST";
  7679. }
  7680. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP %s to %s\n", s, endpoint ? endpoint : "(null)"));
  7681. if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && soap_tag_cmp(endpoint, "httpg:*")))
  7682. return SOAP_OK;
  7683. /* set l to prevent overruns ('host' and 'soap->host' are substrings of 'endpoint') */
  7684. l = strlen(endpoint) + strlen(soap->http_version) + 80;
  7685. if (l > sizeof(soap->tmpbuf))
  7686. return soap->error = SOAP_EOM;
  7687. if (soap->status == SOAP_CONNECT)
  7688. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "%s %s:%d HTTP/%s", s, soap->host, soap->port, soap->http_version);
  7689. else if (soap->proxy_host && endpoint)
  7690. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "%s %s HTTP/%s", s, endpoint, soap->http_version);
  7691. else
  7692. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version);
  7693. err = soap->fposthdr(soap, soap->tmpbuf, NULL);
  7694. if (err)
  7695. return err;
  7696. #ifdef WITH_OPENSSL
  7697. if ((soap->ssl && port != 443) || (!soap->ssl && port != 80))
  7698. #else
  7699. if (port != 80)
  7700. #endif
  7701. {
  7702. #ifdef WITH_IPV6
  7703. if (*host != '[' && strchr(host, ':'))
  7704. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "[%s]:%d", host, port); /* RFC 2732 */
  7705. else
  7706. #endif
  7707. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "%s:%d", host, port);
  7708. }
  7709. else
  7710. {
  7711. #ifdef WITH_IPV6
  7712. if (*host != '[' && strchr(host, ':'))
  7713. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "[%s]", host); /* RFC 2732 */
  7714. else
  7715. #endif
  7716. soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), host);
  7717. }
  7718. err = soap->fposthdr(soap, "Host", soap->tmpbuf);
  7719. if (err)
  7720. return err;
  7721. err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.8");
  7722. if (err)
  7723. return err;
  7724. if (soap->origin)
  7725. {
  7726. err = soap->fposthdr(soap, "Origin", soap->origin);
  7727. if (err)
  7728. return err;
  7729. if (soap->status == SOAP_OPTIONS)
  7730. {
  7731. err = soap->fposthdr(soap, "Access-Control-Request-Method", soap->cors_method ? soap->cors_method : "POST");
  7732. if (err)
  7733. return err;
  7734. if (soap->cors_header)
  7735. {
  7736. err = soap->fposthdr(soap, "Access-Control-Request-Headers", soap->cors_header);
  7737. if (err)
  7738. return err;
  7739. }
  7740. }
  7741. }
  7742. err = soap_puthttphdr(soap, SOAP_OK, count);
  7743. if (err)
  7744. return err;
  7745. #ifndef WITH_LEANER
  7746. if ((soap->imode & SOAP_ENC_MTOM))
  7747. {
  7748. err = soap->fposthdr(soap, "Accept", "multipart/related,application/xop+xml,*/*;q=0.8");
  7749. if (err)
  7750. return err;
  7751. }
  7752. #endif
  7753. #ifdef WITH_ZLIB
  7754. #ifdef WITH_GZIP
  7755. err = soap->fposthdr(soap, "Accept-Encoding", "gzip,deflate");
  7756. #else
  7757. err = soap->fposthdr(soap, "Accept-Encoding", "deflate");
  7758. #endif
  7759. if (err)
  7760. return err;
  7761. #endif
  7762. #if !defined(WITH_LEAN) || defined(WITH_NTLM)
  7763. if (soap->bearer)
  7764. {
  7765. l = strlen(soap->bearer);
  7766. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l + 1), "Bearer %s", soap->bearer);
  7767. err = soap->fposthdr(soap, "Authorization", soap->tmpbuf);
  7768. if (err)
  7769. return err;
  7770. }
  7771. #ifdef WITH_NTLM
  7772. if (soap->ntlm_challenge)
  7773. {
  7774. l = strlen(soap->ntlm_challenge);
  7775. if (l)
  7776. {
  7777. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l + 5), "NTLM %s", soap->ntlm_challenge);
  7778. if (soap->proxy_host)
  7779. {
  7780. err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf);
  7781. if (err)
  7782. return err;
  7783. }
  7784. else
  7785. {
  7786. err = soap->fposthdr(soap, "Authorization", soap->tmpbuf);
  7787. if (err)
  7788. return err;
  7789. }
  7790. }
  7791. }
  7792. else
  7793. {
  7794. #endif
  7795. if (soap->userid && soap->passwd)
  7796. {
  7797. soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "Basic ");
  7798. (SOAP_SNPRINTF(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262, strlen(soap->userid) + strlen(soap->passwd) + 1), "%s:%s", soap->userid, soap->passwd);
  7799. soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
  7800. err = soap->fposthdr(soap, "Authorization", soap->tmpbuf);
  7801. if (err)
  7802. return err;
  7803. }
  7804. if (soap->proxy_userid && soap->proxy_passwd)
  7805. {
  7806. soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "Basic ");
  7807. (SOAP_SNPRINTF(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262, strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) + 1), "%s:%s", soap->proxy_userid, soap->proxy_passwd);
  7808. soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
  7809. err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf);
  7810. if (err)
  7811. return err;
  7812. }
  7813. #ifdef WITH_NTLM
  7814. }
  7815. #endif
  7816. #endif
  7817. #ifdef WITH_COOKIES
  7818. #ifdef WITH_OPENSSL
  7819. if (soap_putcookies(soap, host, path, soap->ssl != NULL))
  7820. return soap->error;
  7821. #else
  7822. if (soap_putcookies(soap, host, path, 0))
  7823. return soap->error;
  7824. #endif
  7825. #endif
  7826. if (action && soap->status != SOAP_GET && soap->status != SOAP_DEL)
  7827. {
  7828. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(action) + 2), "\"%s\"", action);
  7829. err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf);
  7830. if (err)
  7831. return err;
  7832. }
  7833. return soap->fposthdr(soap, NULL, NULL);
  7834. }
  7835. #endif
  7836. /******************************************************************************/
  7837. #ifndef WITH_NOHTTP
  7838. static int
  7839. http_send_header(struct soap *soap, const char *s)
  7840. {
  7841. const char *t;
  7842. do
  7843. {
  7844. t = strchr(s, '\n'); /* disallow \n in HTTP headers */
  7845. if (!t)
  7846. t = s + strlen(s);
  7847. if (soap_send_raw(soap, s, t - s))
  7848. return soap->error;
  7849. s = t + 1;
  7850. } while (*t);
  7851. return SOAP_OK;
  7852. }
  7853. #endif
  7854. /******************************************************************************/
  7855. #ifndef WITH_NOHTTP
  7856. static int
  7857. http_post_header(struct soap *soap, const char *key, const char *val)
  7858. {
  7859. if (key)
  7860. {
  7861. if (http_send_header(soap, key))
  7862. return soap->error;
  7863. if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val)))
  7864. return soap->error;
  7865. }
  7866. return soap_send_raw(soap, "\r\n", 2);
  7867. }
  7868. #endif
  7869. /******************************************************************************/
  7870. #ifndef WITH_NOHTTP
  7871. static int
  7872. http_response(struct soap *soap, int status, ULONG64 count)
  7873. {
  7874. int err;
  7875. char http[32];
  7876. int code = status;
  7877. const char *line;
  7878. #ifdef WMW_RPM_IO
  7879. if (soap->rpmreqid)
  7880. httpOutputEnable(soap->rpmreqid);
  7881. if (soap->rpmreqid
  7882. || soap_valid_socket(soap->master)
  7883. || soap_valid_socket(soap->socket)
  7884. || soap->recvfd != 0
  7885. || soap->sendfd != 1
  7886. || soap->os) /* RPM behaves as if standalone */
  7887. #else
  7888. if (soap_valid_socket(soap->master)
  7889. || soap_valid_socket(soap->socket)
  7890. #ifndef UNDER_CE
  7891. || soap->recvfd != 0
  7892. || soap->sendfd != 1
  7893. #else
  7894. || soap->recvfd != stdin
  7895. || soap->sendfd != stdout
  7896. #endif
  7897. || soap->os) /* standalone server application (over sockets), not CGI (over stdin/out) */
  7898. #endif
  7899. (SOAP_SNPRINTF(http, sizeof(http), strlen(soap->http_version) + 5), "HTTP/%s", soap->http_version);
  7900. else
  7901. soap_strcpy(http, sizeof(http), "Status:");
  7902. if (status >= SOAP_FILE && status < SOAP_FILE + 600)
  7903. {
  7904. code = status - SOAP_FILE;
  7905. if (code == 0)
  7906. code = 200;
  7907. }
  7908. else if (!status || status == SOAP_HTML)
  7909. {
  7910. if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
  7911. code = 200;
  7912. else
  7913. code = 202;
  7914. }
  7915. else if (status < 200 || status >= 600)
  7916. {
  7917. const char *s = *soap_faultcode(soap);
  7918. if (status >= SOAP_GET_METHOD && status <= SOAP_HTTP_METHOD)
  7919. code = 405;
  7920. else if (soap->version == 2 && (!s || !strcmp(s, "SOAP-ENV:Sender")))
  7921. code = 400;
  7922. else
  7923. code = 500;
  7924. }
  7925. line = http_error(soap, code);
  7926. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP Status = %d %s\n", code, line));
  7927. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), sizeof(http) + 22 + strlen(line)), "%s %d %s", http, code, line);
  7928. err = soap->fposthdr(soap, soap->tmpbuf, NULL);
  7929. if (err)
  7930. return err;
  7931. #ifndef WITH_LEAN
  7932. if (status == 401)
  7933. {
  7934. (SOAP_SNPRINTF_SAFE(soap->tmpbuf, sizeof(soap->tmpbuf)), "Basic realm=\"%s\"", (soap->authrealm && strlen(soap->authrealm) + 14 < sizeof(soap->tmpbuf)) ? soap->authrealm : "gSOAP Web Service");
  7935. err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf);
  7936. if (err)
  7937. return err;
  7938. }
  7939. else if ((status >= 301 && status <= 303) || status == 307)
  7940. {
  7941. err = soap->fposthdr(soap, "Location", soap->endpoint);
  7942. if (err)
  7943. return err;
  7944. }
  7945. #endif
  7946. err = soap->fposthdr(soap, "Server", "gSOAP/2.8");
  7947. if (err)
  7948. return err;
  7949. if (soap->cors_origin)
  7950. {
  7951. err = soap->fposthdr(soap, "Access-Control-Allow-Origin", soap->cors_origin);
  7952. if (err)
  7953. return err;
  7954. err = soap->fposthdr(soap, "Access-Control-Allow-Credentials", "true");
  7955. if (err)
  7956. return err;
  7957. if (soap->cors_methods)
  7958. {
  7959. err = soap->fposthdr(soap, "Access-Control-Allow-Methods", soap->cors_methods);
  7960. if (err)
  7961. return err;
  7962. if (soap->cors_headers)
  7963. {
  7964. err = soap->fposthdr(soap, "Access-Control-Allow-Headers", soap->cors_headers);
  7965. if (err)
  7966. return err;
  7967. }
  7968. }
  7969. }
  7970. if (soap->x_frame_options)
  7971. {
  7972. err = soap->fposthdr(soap, "X-Frame-Options", soap->x_frame_options);
  7973. if (err)
  7974. return err;
  7975. }
  7976. soap->cors_origin = NULL;
  7977. soap->cors_methods = NULL;
  7978. soap->cors_headers = NULL;
  7979. err = soap_puthttphdr(soap, status, count);
  7980. if (err)
  7981. return err;
  7982. #ifdef WITH_COOKIES
  7983. if (soap_putsetcookies(soap))
  7984. return soap->error;
  7985. soap_free_cookies(soap);
  7986. #endif
  7987. return soap->fposthdr(soap, NULL, NULL);
  7988. }
  7989. #endif
  7990. /******************************************************************************/
  7991. SOAP_FMAC1
  7992. int
  7993. SOAP_FMAC2
  7994. soap_response(struct soap *soap, int status)
  7995. {
  7996. ULONG64 count;
  7997. if (!(soap->omode & (SOAP_ENC_PLAIN | SOAP_IO_STORE /* this tests for chunking too */))
  7998. && (status == SOAP_HTML || (status >= SOAP_FILE && status < SOAP_FILE + 600)))
  7999. soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE;
  8000. soap->status = status;
  8001. count = soap_count_attachments(soap);
  8002. if (soap_init_send(soap))
  8003. return soap->error;
  8004. #ifndef WITH_NOHTTP
  8005. if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_PLAIN))
  8006. {
  8007. int k = soap->mode;
  8008. soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
  8009. if ((k & SOAP_IO) != SOAP_IO_FLUSH)
  8010. soap->mode |= SOAP_IO_BUFFER;
  8011. soap->error = soap->fresponse(soap, status, count);
  8012. if (soap->error)
  8013. return soap->error;
  8014. #ifndef WITH_LEANER
  8015. if ((k & SOAP_IO) == SOAP_IO_CHUNK)
  8016. {
  8017. if (soap_flush(soap))
  8018. return soap->error;
  8019. }
  8020. #endif
  8021. soap->mode = k;
  8022. }
  8023. #endif
  8024. #ifndef WITH_LEANER
  8025. if (soap_begin_attachments(soap))
  8026. return soap->error;
  8027. #endif
  8028. return SOAP_OK;
  8029. }
  8030. /******************************************************************************/
  8031. SOAP_FMAC1
  8032. const char*
  8033. SOAP_FMAC2
  8034. soap_extend_url(struct soap *soap, const char *s, const char *t)
  8035. {
  8036. if (s)
  8037. soap_strcpy(soap->msgbuf, sizeof(soap->msgbuf), s);
  8038. else
  8039. *soap->msgbuf = '\0';
  8040. if (t && (*t == '/' || *t == '?'))
  8041. {
  8042. char *r = strchr(soap->msgbuf, '?');
  8043. if (r)
  8044. {
  8045. if (*t == '?')
  8046. {
  8047. soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), "&");
  8048. soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), t + 1);
  8049. }
  8050. else /* *t == '/' */
  8051. {
  8052. size_t l = r - soap->msgbuf;
  8053. *r = '\0';
  8054. soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), t);
  8055. if (s)
  8056. soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), s + l);
  8057. }
  8058. }
  8059. else
  8060. {
  8061. soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), t);
  8062. }
  8063. }
  8064. return soap->msgbuf;
  8065. }
  8066. /******************************************************************************/
  8067. SOAP_FMAC1
  8068. const char*
  8069. SOAP_FMAC2
  8070. soap_extend_url_query(struct soap *soap, const char *s, const char *t)
  8071. {
  8072. (void)soap_extend_url(soap, s, t); /* fills and returns soap->msgbuf */
  8073. if (strchr(soap->msgbuf, '?'))
  8074. soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), "&");
  8075. else
  8076. soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), "?");
  8077. return soap->msgbuf;
  8078. }
  8079. /******************************************************************************/
  8080. SOAP_FMAC1
  8081. void
  8082. SOAP_FMAC2
  8083. soap_url_query(struct soap *soap, const char *s, const char *t)
  8084. {
  8085. size_t n = strlen(s);
  8086. if (n)
  8087. {
  8088. char *r = soap->msgbuf;
  8089. size_t k = n - (s[n-1] == '=');
  8090. while ((r = strchr(r, '{')) != NULL)
  8091. if (!strncmp(++r, s, k) && r[k] == '}')
  8092. break;
  8093. if (r)
  8094. {
  8095. size_t m = t ? strlen(t) : 0;
  8096. (void)soap_memmove(r + m - 1, soap->msgbuf + sizeof(soap->msgbuf) - (r + n + 1), r + k + 1, strlen(r + k + 1) + 1);
  8097. if (m)
  8098. (void)soap_memmove(r - 1, soap->msgbuf + sizeof(soap->msgbuf) - (r - 1), t, m);
  8099. }
  8100. else
  8101. {
  8102. soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), s);
  8103. if (t)
  8104. {
  8105. int m = (int)strlen(soap->msgbuf); /* msgbuf length is max SOAP_TMPLEN or just 1024 bytes */
  8106. (void)soap_encode_url(t, soap->msgbuf + m, (int)sizeof(soap->msgbuf) - m);
  8107. }
  8108. soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), "&");
  8109. }
  8110. }
  8111. }
  8112. /******************************************************************************/
  8113. SOAP_FMAC1
  8114. int
  8115. SOAP_FMAC2
  8116. soap_encode_url(const char *s, char *t, int len)
  8117. {
  8118. int c;
  8119. int n = len;
  8120. if (s && n > 0)
  8121. {
  8122. while ((c = *s++) && --n > 0)
  8123. {
  8124. if (c == '-'
  8125. || c == '.'
  8126. || (c >= '0' && c <= '9')
  8127. || (c >= 'A' && c <= 'Z')
  8128. || c == '_'
  8129. || (c >= 'a' && c <= 'z')
  8130. || c == '~')
  8131. {
  8132. *t++ = c;
  8133. }
  8134. else if (n > 2)
  8135. {
  8136. *t++ = '%';
  8137. *t++ = (c >> 4) + (c > 159 ? '7' : '0');
  8138. c &= 0xF;
  8139. *t++ = c + (c > 9 ? '7' : '0');
  8140. n -= 2;
  8141. }
  8142. else
  8143. {
  8144. break;
  8145. }
  8146. }
  8147. *t = '\0';
  8148. }
  8149. return len - n;
  8150. }
  8151. /******************************************************************************/
  8152. SOAP_FMAC1
  8153. const char*
  8154. SOAP_FMAC2
  8155. soap_encode_url_string(struct soap *soap, const char *s)
  8156. {
  8157. if (s)
  8158. {
  8159. int n = 3 * (int)strlen(s) + 1;
  8160. char *t = (char*)soap_malloc(soap, n);
  8161. if (t)
  8162. {
  8163. (void)soap_encode_url(s, t, n);
  8164. return t;
  8165. }
  8166. }
  8167. return SOAP_STR_EOS;
  8168. }
  8169. /******************************************************************************\
  8170. *
  8171. * HTTP Cookies RFC 6265
  8172. *
  8173. \******************************************************************************/
  8174. #ifdef WITH_COOKIES
  8175. SOAP_FMAC1
  8176. struct soap_cookie*
  8177. SOAP_FMAC2
  8178. soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
  8179. {
  8180. return soap_cookie_env(soap, name, domain, path, 0);
  8181. }
  8182. /******************************************************************************/
  8183. SOAP_FMAC1
  8184. struct soap_cookie*
  8185. SOAP_FMAC2
  8186. soap_cookie_env(struct soap *soap, const char *name, const char *domain, const char *path, short env)
  8187. {
  8188. struct soap_cookie *p;
  8189. if (!domain && !env)
  8190. domain = soap->cookie_domain;
  8191. if (!path)
  8192. path = soap->cookie_path;
  8193. if (!path)
  8194. path = SOAP_STR_EOS;
  8195. else if (*path == '/')
  8196. path++;
  8197. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie='%s' domain='%s' path='%s' env=%hd\n", name, domain ? domain : "(null)", path ? path : "(null)", env));
  8198. for (p = soap->cookies; p; p = p->next)
  8199. {
  8200. 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));
  8201. if ((!env || p->env)
  8202. && !strcmp(p->name, name)
  8203. && (!domain || (domain && p->domain && !strcmp(p->domain, domain)))
  8204. && (!path || (path && p->path && !strncmp(p->path, path, strlen(p->path)))))
  8205. break;
  8206. }
  8207. return p;
  8208. }
  8209. /******************************************************************************/
  8210. SOAP_FMAC1
  8211. struct soap_cookie*
  8212. SOAP_FMAC2
  8213. soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path)
  8214. {
  8215. struct soap_cookie **p, *q;
  8216. int n;
  8217. if (!domain)
  8218. domain = soap->cookie_domain;
  8219. if (!path)
  8220. path = soap->cookie_path;
  8221. if (!path)
  8222. path = SOAP_STR_EOS;
  8223. else if (*path == '/')
  8224. path++;
  8225. q = soap_cookie(soap, name, domain, path);
  8226. 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)"));
  8227. if (!q)
  8228. {
  8229. q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie));
  8230. if (q)
  8231. {
  8232. size_t l = strlen(name) + 1;
  8233. q->name = NULL;
  8234. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8235. q->name = (char*)SOAP_MALLOC(soap, l);
  8236. if (q->name)
  8237. (void)soap_memcpy(q->name, l, name, l);
  8238. q->value = NULL;
  8239. q->domain = NULL;
  8240. q->path = NULL;
  8241. q->expire = 0;
  8242. q->maxage = -1;
  8243. q->version = 1;
  8244. q->secure = 0;
  8245. q->modified = 0;
  8246. for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--)
  8247. if (!strcmp((*p)->name, name) && (*p)->path && path && strcmp((*p)->path, path) < 0)
  8248. break;
  8249. if (n)
  8250. {
  8251. q->next = *p;
  8252. *p = q;
  8253. }
  8254. else
  8255. {
  8256. SOAP_FREE(soap, q->name);
  8257. SOAP_FREE(soap, q);
  8258. q = NULL;
  8259. }
  8260. }
  8261. }
  8262. else
  8263. {
  8264. q->modified = 1;
  8265. }
  8266. if (q)
  8267. {
  8268. if (q->value)
  8269. {
  8270. if (!value || strcmp(value, q->value))
  8271. {
  8272. SOAP_FREE(soap, q->value);
  8273. q->value = NULL;
  8274. }
  8275. }
  8276. if (value && *value && !q->value)
  8277. {
  8278. size_t l = strlen(value) + 1;
  8279. q->value = NULL;
  8280. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8281. q->value = (char*)SOAP_MALLOC(soap, l);
  8282. if (q->value)
  8283. soap_strcpy(q->value, l, value);
  8284. }
  8285. if (q->domain)
  8286. {
  8287. if (!domain || strcmp(domain, q->domain))
  8288. {
  8289. SOAP_FREE(soap, q->domain);
  8290. q->domain = NULL;
  8291. }
  8292. }
  8293. if (domain && !q->domain)
  8294. {
  8295. size_t l = strlen(domain) + 1;
  8296. q->domain = NULL;
  8297. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8298. q->domain = (char*)SOAP_MALLOC(soap, l);
  8299. if (q->domain)
  8300. soap_strcpy(q->domain, l, domain);
  8301. }
  8302. if (q->path)
  8303. {
  8304. if (!path || strncmp(path, q->path, strlen(q->path)))
  8305. {
  8306. SOAP_FREE(soap, q->path);
  8307. q->path = NULL;
  8308. }
  8309. }
  8310. if (path && !q->path)
  8311. {
  8312. size_t l = strlen(path) + 1;
  8313. q->path = NULL;
  8314. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8315. q->path = (char*)SOAP_MALLOC(soap, l);
  8316. if (q->path)
  8317. soap_strcpy(q->path, l, path);
  8318. }
  8319. q->session = 1;
  8320. q->env = 0;
  8321. }
  8322. return q;
  8323. }
  8324. /******************************************************************************/
  8325. SOAP_FMAC1
  8326. void
  8327. SOAP_FMAC2
  8328. soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
  8329. {
  8330. struct soap_cookie **p, *q;
  8331. if (!domain)
  8332. domain = soap->cookie_domain;
  8333. if (!domain)
  8334. {
  8335. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie='%s': cookie domain not set\n", name ? name : "(null)"));
  8336. return;
  8337. }
  8338. if (!path)
  8339. path = soap->cookie_path;
  8340. if (!path)
  8341. path = SOAP_STR_EOS;
  8342. else if (*path == '/')
  8343. path++;
  8344. for (p = &soap->cookies, q = *p; q; q = *p)
  8345. {
  8346. if (!strcmp(q->name, name) && (!q->domain || !strcmp(q->domain, domain)) && (!q->path || !strncmp(q->path, path, strlen(q->path))))
  8347. {
  8348. SOAP_FREE(soap, q->name);
  8349. if (q->value)
  8350. SOAP_FREE(soap, q->value);
  8351. if (q->domain)
  8352. SOAP_FREE(soap, q->domain);
  8353. if (q->path)
  8354. SOAP_FREE(soap, q->path);
  8355. *p = q->next;
  8356. SOAP_FREE(soap, q);
  8357. }
  8358. else
  8359. p = &q->next;
  8360. }
  8361. }
  8362. /******************************************************************************/
  8363. SOAP_FMAC1
  8364. const char *
  8365. SOAP_FMAC2
  8366. soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
  8367. {
  8368. struct soap_cookie *p;
  8369. p = soap_cookie(soap, name, domain, path);
  8370. if (p)
  8371. return p->value;
  8372. return NULL;
  8373. }
  8374. /******************************************************************************/
  8375. SOAP_FMAC1
  8376. const char *
  8377. SOAP_FMAC2
  8378. soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
  8379. {
  8380. struct soap_cookie *p;
  8381. p = soap_cookie(soap, name, domain, path);
  8382. if (p && p->env)
  8383. return p->value;
  8384. return NULL;
  8385. }
  8386. /******************************************************************************/
  8387. SOAP_FMAC1
  8388. time_t
  8389. SOAP_FMAC2
  8390. soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path)
  8391. {
  8392. struct soap_cookie *p;
  8393. p = soap_cookie(soap, name, domain, path);
  8394. if (p)
  8395. return (time_t)p->expire;
  8396. return -1;
  8397. }
  8398. /******************************************************************************/
  8399. SOAP_FMAC1
  8400. int
  8401. SOAP_FMAC2
  8402. soap_set_cookie_expire(struct soap *soap, const char *name, long maxage, const char *domain, const char *path)
  8403. {
  8404. struct soap_cookie *p;
  8405. 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)"));
  8406. p = soap_cookie(soap, name, domain, path);
  8407. if (p)
  8408. {
  8409. p->maxage = maxage;
  8410. p->modified = 1;
  8411. return SOAP_OK;
  8412. }
  8413. return SOAP_ERR;
  8414. }
  8415. /******************************************************************************/
  8416. SOAP_FMAC1
  8417. int
  8418. SOAP_FMAC2
  8419. soap_set_cookie_secure(struct soap *soap, const char *name, const char *domain, const char *path)
  8420. {
  8421. struct soap_cookie *p;
  8422. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie secure: cookie='%s' domain='%s' path='%s'\n", name, domain ? domain : "(null)", path ? path : "(null)"));
  8423. p = soap_cookie(soap, name, domain, path);
  8424. if (p)
  8425. {
  8426. p->secure = 1;
  8427. p->modified = 1;
  8428. return SOAP_OK;
  8429. }
  8430. return SOAP_ERR;
  8431. }
  8432. /******************************************************************************/
  8433. SOAP_FMAC1
  8434. int
  8435. SOAP_FMAC2
  8436. soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
  8437. {
  8438. struct soap_cookie *p;
  8439. p = soap_cookie(soap, name, domain, path);
  8440. if (p)
  8441. {
  8442. p->session = 1;
  8443. p->modified = 1;
  8444. return SOAP_OK;
  8445. }
  8446. return SOAP_ERR;
  8447. }
  8448. /******************************************************************************/
  8449. SOAP_FMAC1
  8450. int
  8451. SOAP_FMAC2
  8452. soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
  8453. {
  8454. struct soap_cookie *p;
  8455. p = soap_cookie(soap, name, domain, path);
  8456. if (p)
  8457. {
  8458. p->session = 0;
  8459. p->modified = 1;
  8460. return SOAP_OK;
  8461. }
  8462. return SOAP_ERR;
  8463. }
  8464. /******************************************************************************/
  8465. SOAP_FMAC1
  8466. int
  8467. SOAP_FMAC2
  8468. soap_putsetcookies(struct soap *soap)
  8469. {
  8470. struct soap_cookie *p;
  8471. char *s, tmp[4096];
  8472. const char *t;
  8473. for (p = soap->cookies; p; p = p->next)
  8474. {
  8475. if ((p->modified
  8476. #ifdef WITH_OPENSSL
  8477. || (!p->env && !soap->ssl == !p->secure)
  8478. #endif
  8479. ) && p->name && p->value && *p->name && *p->value)
  8480. {
  8481. s = tmp;
  8482. s += soap_encode_url(p->name, s, 3967);
  8483. *s++ = '=';
  8484. s += soap_encode_url(p->value, s, 3968 - (int)(s-tmp));
  8485. t = p->domain ? p->domain : soap->cookie_domain;
  8486. if (t && (int)strlen(t) < 3968 - (int)(s-tmp))
  8487. {
  8488. soap_strcpy(s, 4096 - (s-tmp), ";Domain=");
  8489. s += 8;
  8490. soap_strcpy(s, 4096 - (s-tmp), t);
  8491. s += strlen(s);
  8492. }
  8493. t = p->path ? p->path : soap->cookie_path;
  8494. if (t && (int)strlen(t) < 3976 - (int)(s-tmp))
  8495. {
  8496. soap_strcpy(s, 4096 - (s-tmp), ";Path=/");
  8497. s += 7;
  8498. if (*t == '/')
  8499. t++;
  8500. if (strchr(t, '%')) /* already URL encoded? */
  8501. {
  8502. soap_strcpy(s, 4096 - (s-tmp), t);
  8503. s += strlen(s);
  8504. }
  8505. else
  8506. {
  8507. s += soap_encode_url(t, s, 4096 - (int)(s-tmp));
  8508. }
  8509. }
  8510. if (p->version > 0 && s-tmp < 3983)
  8511. {
  8512. (SOAP_SNPRINTF(s, 4096 - (s-tmp), 29), ";Version=%u", p->version);
  8513. s += strlen(s);
  8514. }
  8515. if (p->maxage >= 0 && s-tmp < 4012)
  8516. {
  8517. (SOAP_SNPRINTF(s, 4096 - (s-tmp), 29), ";Max-Age=%ld", p->maxage);
  8518. s += strlen(s);
  8519. }
  8520. #if !defined(WITH_LEAN)
  8521. #if defined(HAVE_GMTIME_R) || defined(HAVE_GMTIME)
  8522. if (p->maxage >= 0 && s-tmp < 4041)
  8523. {
  8524. time_t n = time(NULL) + p->maxage;
  8525. struct tm T, *pT = &T;
  8526. size_t l = 0;
  8527. /* format is Wed, 09 Jun 2021 10:18:14 GMT */
  8528. #if defined(HAVE_GMTIME_R)
  8529. if (gmtime_r(&n, pT) != SOAP_FUNC_R_ERR)
  8530. l = strftime(s, 4096 - (s-tmp), ";Expires=%a, %d %b %Y %H:%M:%S GMT", pT);
  8531. #else
  8532. pT = gmtime(&n);
  8533. if (pT)
  8534. l = strftime(s, 4096 - (s-tmp), ";Expires=%a, %d %b %Y %H:%M:%S GMT", pT);
  8535. #endif
  8536. s += l;
  8537. }
  8538. #endif
  8539. #endif
  8540. if (s-tmp < 4079
  8541. && (p->secure
  8542. #ifdef WITH_OPENSSL
  8543. || soap->ssl
  8544. #endif
  8545. ))
  8546. {
  8547. soap_strcpy(s, 4096 - (s-tmp), ";Secure");
  8548. s += strlen(s);
  8549. }
  8550. if (s-tmp < 4086)
  8551. soap_strcpy(s, 4096 - (s-tmp), ";HttpOnly");
  8552. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp));
  8553. soap->error = soap->fposthdr(soap, "Set-Cookie", tmp);
  8554. if (soap->error)
  8555. return soap->error;
  8556. }
  8557. }
  8558. return SOAP_OK;
  8559. }
  8560. /******************************************************************************/
  8561. SOAP_FMAC1
  8562. int
  8563. SOAP_FMAC2
  8564. soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure)
  8565. {
  8566. struct soap_cookie **p, *q;
  8567. char *s, tmp[4096];
  8568. unsigned int version = 0;
  8569. time_t now = time(NULL);
  8570. if (!domain || !path)
  8571. return SOAP_OK;
  8572. s = tmp;
  8573. p = &soap->cookies;
  8574. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain='%s' path='%s'\n", domain, path));
  8575. if (*path == '/')
  8576. path++;
  8577. while ((q = *p))
  8578. {
  8579. if (q->expire && now >= (time_t)q->expire)
  8580. {
  8581. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name));
  8582. SOAP_FREE(soap, q->name);
  8583. if (q->value)
  8584. SOAP_FREE(soap, q->value);
  8585. if (q->domain)
  8586. SOAP_FREE(soap, q->domain);
  8587. if (q->path)
  8588. SOAP_FREE(soap, q->path);
  8589. *p = q->next;
  8590. SOAP_FREE(soap, q);
  8591. }
  8592. else
  8593. {
  8594. int flag;
  8595. char *t = q->domain;
  8596. size_t n = 0;
  8597. if (!t)
  8598. flag = 1;
  8599. else
  8600. {
  8601. const char *r = strchr(t, ':');
  8602. if (r)
  8603. n = r - t;
  8604. else
  8605. n = strlen(t);
  8606. flag = !strncmp(t, domain, n);
  8607. }
  8608. /* domain-level cookies, cannot compile when WITH_NOIO set */
  8609. #ifndef WITH_NOIO
  8610. if (!flag)
  8611. {
  8612. struct hostent hostent;
  8613. if (!tcp_gethostbyname(soap, (char*)domain, &hostent, NULL))
  8614. {
  8615. const char *r = hostent.h_name;
  8616. if (*t == '.')
  8617. {
  8618. size_t k = strlen(hostent.h_name);
  8619. if (k >= n)
  8620. r = hostent.h_name + k - n;
  8621. }
  8622. flag = !strncmp(t, r, n);
  8623. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Domain cookie %s host %s (match=%d)\n", t, r, flag));
  8624. }
  8625. }
  8626. #endif
  8627. if (flag
  8628. && (!q->path || !strncmp(q->path, path, strlen(q->path)))
  8629. #ifndef WITH_INSECURE_COOKIES
  8630. && (!q->secure || secure)
  8631. #endif
  8632. )
  8633. {
  8634. size_t n = 12;
  8635. if (q->name)
  8636. n += 3*strlen(q->name);
  8637. if (q->value && *q->value)
  8638. n += 3*strlen(q->value) + 1;
  8639. if (q->path && *q->path)
  8640. n += strlen(q->path) + 9;
  8641. if (q->domain)
  8642. n += strlen(q->domain) + 11;
  8643. if (s + n >= tmp + sizeof(tmp))
  8644. {
  8645. if (s == tmp)
  8646. return SOAP_OK; /* header too big, cannot split */
  8647. /* split up HTTP header */
  8648. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp));
  8649. soap->error = soap->fposthdr(soap, "Cookie", tmp);
  8650. if (soap->error)
  8651. return soap->error;
  8652. s = tmp;
  8653. }
  8654. else if (s != tmp)
  8655. {
  8656. *s++ = ';';
  8657. }
  8658. 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)"));
  8659. if (q->version != version && (s-tmp) + (size_t)36 < sizeof(tmp))
  8660. {
  8661. (SOAP_SNPRINTF_SAFE(s, sizeof(tmp) - (s-tmp)), "$Version=%u;", q->version);
  8662. version = q->version;
  8663. s += strlen(s);
  8664. }
  8665. if (q->name && (s-tmp) + strlen(q->name) + (size_t)15 < sizeof(tmp))
  8666. {
  8667. s += soap_encode_url(q->name, s, (int)(tmp+sizeof(tmp)-s)-15);
  8668. }
  8669. if (q->value && *q->value && (s-tmp) + strlen(q->value) + (size_t)16 < sizeof(tmp))
  8670. {
  8671. *s++ = '=';
  8672. s += soap_encode_url(q->value, s, (int)(tmp+sizeof(tmp)-s)-16);
  8673. }
  8674. if (q->path && (s-tmp) + strlen(q->path) + (size_t)36 < sizeof(tmp))
  8675. {
  8676. (SOAP_SNPRINTF_SAFE(s, sizeof(tmp) - (s-tmp)), ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path));
  8677. s += strlen(s);
  8678. }
  8679. if (q->domain && (s-tmp) + strlen(q->domain) + (size_t)36 < sizeof(tmp))
  8680. {
  8681. (SOAP_SNPRINTF_SAFE(s, sizeof(tmp) - (s-tmp)), ";$Domain=\"%s\"", q->domain);
  8682. s += strlen(s);
  8683. }
  8684. }
  8685. p = &q->next;
  8686. }
  8687. }
  8688. if (s != tmp)
  8689. {
  8690. soap->error = soap->fposthdr(soap, "Cookie", tmp);
  8691. if (soap->error)
  8692. return soap->error;
  8693. }
  8694. return SOAP_OK;
  8695. }
  8696. /******************************************************************************/
  8697. SOAP_FMAC1
  8698. void
  8699. SOAP_FMAC2
  8700. soap_getcookies(struct soap *soap, const char *val)
  8701. {
  8702. struct soap_cookie *p = NULL, *q;
  8703. const char *s;
  8704. char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
  8705. char *domain = NULL;
  8706. char *path = NULL;
  8707. unsigned int version = 0;
  8708. time_t now = time(NULL);
  8709. if (!val)
  8710. return;
  8711. s = val;
  8712. while (*s)
  8713. {
  8714. s = soap_decode_key(tmp, sizeof(tmp), s);
  8715. if (!soap_tag_cmp(tmp, "$Version"))
  8716. {
  8717. s = soap_decode_val(tmp, sizeof(tmp), s);
  8718. if (s)
  8719. {
  8720. if (p)
  8721. p->version = (int)soap_strtol(tmp, NULL, 10);
  8722. else
  8723. version = (int)soap_strtol(tmp, NULL, 10);
  8724. }
  8725. }
  8726. else if (!soap_tag_cmp(tmp, "$Path"))
  8727. {
  8728. s = soap_decode_val(tmp, sizeof(tmp), s);
  8729. if (*tmp)
  8730. {
  8731. size_t l = strlen(tmp) + 1;
  8732. t = NULL;
  8733. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8734. t = (char*)SOAP_MALLOC(soap, l);
  8735. if (t)
  8736. (void)soap_memcpy((void*)t, l, (const void*)tmp, l);
  8737. }
  8738. else
  8739. {
  8740. t = NULL;
  8741. }
  8742. if (p)
  8743. {
  8744. if (p->path)
  8745. SOAP_FREE(soap, p->path);
  8746. p->path = t;
  8747. }
  8748. else
  8749. {
  8750. if (path)
  8751. SOAP_FREE(soap, path);
  8752. path = t;
  8753. }
  8754. }
  8755. else if (!soap_tag_cmp(tmp, "$Domain"))
  8756. {
  8757. s = soap_decode_val(tmp, sizeof(tmp), s);
  8758. if (*tmp)
  8759. {
  8760. size_t l = strlen(tmp) + 1;
  8761. t = NULL;
  8762. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8763. t = (char*)SOAP_MALLOC(soap, l);
  8764. if (t)
  8765. (void)soap_memcpy((void*)t, l, (const void*)tmp, l);
  8766. }
  8767. else
  8768. {
  8769. t = NULL;
  8770. }
  8771. if (p)
  8772. {
  8773. if (p->domain)
  8774. SOAP_FREE(soap, p->domain);
  8775. p->domain = t;
  8776. }
  8777. else
  8778. {
  8779. if (domain)
  8780. SOAP_FREE(soap, domain);
  8781. domain = t;
  8782. }
  8783. }
  8784. else if (p && !soap_tag_cmp(tmp, "Path"))
  8785. {
  8786. if (p->path)
  8787. SOAP_FREE(soap, p->path);
  8788. s = soap_decode_val(tmp, sizeof(tmp), s);
  8789. if (*tmp)
  8790. {
  8791. size_t l = strlen(tmp) + 1;
  8792. p->path = NULL;
  8793. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8794. p->path = (char*)SOAP_MALLOC(soap, l);
  8795. if (p->path)
  8796. (void)soap_memcpy((void*)p->path, l, (const void*)tmp, l);
  8797. }
  8798. else
  8799. {
  8800. p->path = NULL;
  8801. }
  8802. }
  8803. else if (p && !soap_tag_cmp(tmp, "Domain"))
  8804. {
  8805. if (p->domain)
  8806. SOAP_FREE(soap, p->domain);
  8807. s = soap_decode_val(tmp, sizeof(tmp), s);
  8808. if (*tmp)
  8809. {
  8810. size_t l = strlen(tmp) + 1;
  8811. p->domain = NULL;
  8812. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8813. p->domain = (char*)SOAP_MALLOC(soap, l);
  8814. if (p->domain)
  8815. (void)soap_memcpy((void*)p->domain, l, (const void*)tmp, l);
  8816. }
  8817. else
  8818. {
  8819. p->domain = NULL;
  8820. }
  8821. }
  8822. else if (p && !soap_tag_cmp(tmp, "Version"))
  8823. {
  8824. s = soap_decode_val(tmp, sizeof(tmp), s);
  8825. p->version = (unsigned int)soap_strtoul(tmp, NULL, 10);
  8826. }
  8827. else if (p && !soap_tag_cmp(tmp, "Max-Age"))
  8828. {
  8829. s = soap_decode_val(tmp, sizeof(tmp), s);
  8830. p->expire = (ULONG64)(now + soap_strtol(tmp, NULL, 10));
  8831. }
  8832. else if (p && !soap_tag_cmp(tmp, "Expires"))
  8833. {
  8834. if (*s == '=')
  8835. {
  8836. s = soap_decode(tmp, sizeof(tmp), s + 1, ";");
  8837. if (!p->expire && strlen(tmp) >= 23)
  8838. {
  8839. char a[3];
  8840. struct tm T;
  8841. static const char mns[] = "anebarprayunulugepctovec";
  8842. const char *t = strchr(tmp, ' ');
  8843. if (t)
  8844. {
  8845. a[2] = '\0';
  8846. memset((void*)&T, 0, sizeof(T));
  8847. if (t[1] >= 'A')
  8848. {
  8849. /* format is Sun Nov 6 08:49:37 94 */
  8850. a[0] = t[2];
  8851. a[1] = t[3];
  8852. T.tm_mon = (int)(strstr(mns, a) - mns) / 2;
  8853. a[0] = t[5];
  8854. a[1] = t[6];
  8855. T.tm_mday = (int)soap_strtol(a, NULL, 10);
  8856. if (t[17] && t[18] && t[19] != ' ')
  8857. t += 2; /* format is Sun Nov 6 08:49:37 2017 - ANSI-C */
  8858. a[0] = t[17];
  8859. a[1] = t[18];
  8860. T.tm_year = 100 + (int)soap_strtol(a, NULL, 10);
  8861. t += 6;
  8862. }
  8863. else
  8864. {
  8865. /* format is Sunday, 06-Nov-17 08:49:37 GMT - RFC 850 */
  8866. a[0] = t[1];
  8867. a[1] = t[2];
  8868. T.tm_mday = (int)soap_strtol(a, NULL, 10);
  8869. a[0] = t[5];
  8870. a[1] = t[6];
  8871. T.tm_mon = (int)(strstr(mns, a) - mns) / 2;
  8872. if (t[10] != ' ')
  8873. t += 2; /* format is Wed, 09 Jun 2021 10:18:14 GMT - RFC 822 */
  8874. a[0] = t[8];
  8875. a[1] = t[9];
  8876. T.tm_year = 100 + (int)soap_strtol(a, NULL, 10);
  8877. t += 11;
  8878. }
  8879. a[0] = t[0];
  8880. a[1] = t[1];
  8881. T.tm_hour = (int)soap_strtol(a, NULL, 10);
  8882. a[0] = t[3];
  8883. a[1] = t[4];
  8884. T.tm_min = (int)soap_strtol(a, NULL, 10);
  8885. a[0] = t[6];
  8886. a[1] = t[7];
  8887. T.tm_sec = (int)soap_strtol(a, NULL, 10);
  8888. p->expire = (ULONG64)soap_timegm(&T);
  8889. }
  8890. }
  8891. }
  8892. }
  8893. else if (p && !soap_tag_cmp(tmp, "Secure"))
  8894. {
  8895. p->secure = 1;
  8896. s = soap_decode_val(tmp, sizeof(tmp), s);
  8897. }
  8898. else if (p && !soap_tag_cmp(tmp, "HttpOnly"))
  8899. {
  8900. s = soap_decode_val(tmp, sizeof(tmp), s);
  8901. }
  8902. else if (p && !soap_tag_cmp(tmp, "Comment"))
  8903. {
  8904. s = soap_decode_val(tmp, sizeof(tmp), s);
  8905. }
  8906. else if (*tmp)
  8907. {
  8908. if (p)
  8909. {
  8910. 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));
  8911. q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path);
  8912. if (q)
  8913. {
  8914. q->version = p->version;
  8915. q->expire = p->expire;
  8916. q->secure = p->secure;
  8917. q->env = 1;
  8918. }
  8919. if (p->name)
  8920. SOAP_FREE(soap, p->name);
  8921. if (p->value)
  8922. SOAP_FREE(soap, p->value);
  8923. if (p->domain)
  8924. SOAP_FREE(soap, p->domain);
  8925. if (p->path)
  8926. SOAP_FREE(soap, p->path);
  8927. SOAP_FREE(soap, p);
  8928. }
  8929. p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie));
  8930. if (p)
  8931. {
  8932. size_t l = strlen(tmp) + 1;
  8933. p->name = NULL;
  8934. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8935. p->name = (char*)SOAP_MALLOC(soap, l);
  8936. if (p->name)
  8937. (void)soap_memcpy(p->name, l, tmp, l);
  8938. s = soap_decode_val(tmp, sizeof(tmp), s);
  8939. if (*tmp)
  8940. {
  8941. l = strlen(tmp) + 1;
  8942. p->value = NULL;
  8943. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8944. p->value = (char*)SOAP_MALLOC(soap, l);
  8945. if (p->value)
  8946. (void)soap_memcpy((void*)p->value, l, (const void*)tmp, l);
  8947. }
  8948. else
  8949. {
  8950. p->value = NULL;
  8951. }
  8952. if (domain)
  8953. {
  8954. p->domain = domain;
  8955. }
  8956. else
  8957. {
  8958. p->domain = NULL;
  8959. }
  8960. if (path)
  8961. {
  8962. p->path = path;
  8963. }
  8964. else if (*soap->path)
  8965. {
  8966. l = strlen(soap->path) + 1;
  8967. p->path = NULL;
  8968. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  8969. p->path = (char*)SOAP_MALLOC(soap, l);
  8970. if (p->path)
  8971. (void)soap_memcpy((void*)p->path, l, (const void*)soap->path, l);
  8972. }
  8973. else
  8974. {
  8975. p->path = (char*)SOAP_MALLOC(soap, 2);
  8976. if (p->path)
  8977. (void)soap_memcpy((void*)p->path, 2, (const void*)"/", 2);
  8978. }
  8979. p->expire = 0;
  8980. p->secure = 0;
  8981. p->version = version;
  8982. }
  8983. }
  8984. }
  8985. if (p)
  8986. {
  8987. 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));
  8988. q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path);
  8989. if (q)
  8990. {
  8991. q->version = p->version;
  8992. q->expire = p->expire;
  8993. q->secure = p->secure;
  8994. q->env = 1;
  8995. }
  8996. if (p->name)
  8997. SOAP_FREE(soap, p->name);
  8998. if (p->value)
  8999. SOAP_FREE(soap, p->value);
  9000. if (p->domain)
  9001. SOAP_FREE(soap, p->domain);
  9002. if (p->path)
  9003. SOAP_FREE(soap, p->path);
  9004. SOAP_FREE(soap, p);
  9005. }
  9006. if (domain)
  9007. SOAP_FREE(soap, domain);
  9008. if (path)
  9009. SOAP_FREE(soap, path);
  9010. }
  9011. /******************************************************************************/
  9012. SOAP_FMAC1
  9013. int
  9014. SOAP_FMAC2
  9015. soap_getenv_cookies(struct soap *soap)
  9016. {
  9017. struct soap_cookie *p;
  9018. const char *s;
  9019. char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
  9020. s = getenv("HTTP_COOKIE");
  9021. if (!s)
  9022. return SOAP_ERR;
  9023. do
  9024. {
  9025. s = soap_decode_key(key, sizeof(key), s);
  9026. s = soap_decode_val(val, sizeof(val), s);
  9027. p = soap_set_cookie(soap, key, val, NULL, NULL);
  9028. if (p)
  9029. p->env = 1;
  9030. } while (*s);
  9031. return SOAP_OK;
  9032. }
  9033. /******************************************************************************/
  9034. SOAP_FMAC1
  9035. struct soap_cookie*
  9036. SOAP_FMAC2
  9037. soap_copy_cookies(struct soap *copy, const struct soap *soap)
  9038. {
  9039. struct soap_cookie *p, **q, *r;
  9040. (void)copy;
  9041. q = &r;
  9042. for (p = soap->cookies; p; p = p->next)
  9043. {
  9044. *q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie));
  9045. if (!*q)
  9046. return r;
  9047. **q = *p;
  9048. if (p->name)
  9049. {
  9050. size_t l = strlen(p->name) + 1;
  9051. (*q)->name = NULL;
  9052. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  9053. (*q)->name = (char*)SOAP_MALLOC(copy, l);
  9054. if ((*q)->name)
  9055. (void)soap_memcpy((*q)->name, l, p->name, l);
  9056. }
  9057. if (p->value)
  9058. {
  9059. size_t l = strlen(p->value) + 1;
  9060. (*q)->value = NULL;
  9061. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  9062. (*q)->value = (char*)SOAP_MALLOC(copy, l);
  9063. if ((*q)->value)
  9064. (void)soap_memcpy((*q)->value, l, p->value, l);
  9065. }
  9066. if (p->domain)
  9067. {
  9068. size_t l = strlen(p->domain) + 1;
  9069. (*q)->domain = NULL;
  9070. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  9071. (*q)->domain = (char*)SOAP_MALLOC(copy, l);
  9072. if ((*q)->domain)
  9073. (void)soap_memcpy((*q)->domain, l, p->domain, l);
  9074. }
  9075. if (p->path)
  9076. {
  9077. size_t l = strlen(p->path) + 1;
  9078. (*q)->path = NULL;
  9079. if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
  9080. (*q)->path = (char*)SOAP_MALLOC(copy, l);
  9081. if ((*q)->path)
  9082. (void)soap_memcpy((*q)->path, l, p->path, l);
  9083. }
  9084. q = &(*q)->next;
  9085. }
  9086. *q = NULL;
  9087. return r;
  9088. }
  9089. /******************************************************************************/
  9090. SOAP_FMAC1
  9091. void
  9092. SOAP_FMAC2
  9093. soap_free_cookies(struct soap *soap)
  9094. {
  9095. struct soap_cookie *p;
  9096. for (p = soap->cookies; p; p = soap->cookies)
  9097. {
  9098. soap->cookies = p->next;
  9099. SOAP_FREE(soap, p->name);
  9100. if (p->value)
  9101. SOAP_FREE(soap, p->value);
  9102. if (p->domain)
  9103. SOAP_FREE(soap, p->domain);
  9104. if (p->path)
  9105. SOAP_FREE(soap, p->path);
  9106. SOAP_FREE(soap, p);
  9107. }
  9108. }
  9109. /******************************************************************************/
  9110. #endif /* WITH_COOKIES */
  9111. /******************************************************************************/
  9112. SOAP_FMAC1
  9113. size_t
  9114. SOAP_FMAC2
  9115. soap_hash(const char *s)
  9116. {
  9117. size_t h = 0;
  9118. while (*s)
  9119. h = 65599*h + *s++;
  9120. return h % SOAP_IDHASH;
  9121. }
  9122. /******************************************************************************/
  9123. static void
  9124. soap_init_pht(struct soap *soap)
  9125. {
  9126. int i;
  9127. soap->pblk = NULL;
  9128. soap->pidx = 0;
  9129. for (i = 0; i < (int)SOAP_PTRHASH; i++)
  9130. soap->pht[i] = NULL;
  9131. }
  9132. /******************************************************************************/
  9133. SOAP_FMAC1
  9134. struct soap*
  9135. SOAP_FMAC2
  9136. soap_versioning(soap_new)(soap_mode imode, soap_mode omode)
  9137. {
  9138. struct soap *soap;
  9139. #ifdef __cplusplus
  9140. soap = SOAP_NEW_UNMANAGED(struct soap);
  9141. #else
  9142. soap = (struct soap*)SOAP_MALLOC_UNMANAGED(sizeof(struct soap));
  9143. #endif
  9144. if (soap)
  9145. soap_versioning(soap_init)(soap, imode, omode);
  9146. return soap;
  9147. }
  9148. /******************************************************************************/
  9149. SOAP_FMAC1
  9150. void
  9151. SOAP_FMAC2
  9152. soap_free(struct soap *soap)
  9153. {
  9154. soap_done(soap);
  9155. #ifdef __cplusplus
  9156. SOAP_DELETE_UNMANAGED(soap);
  9157. #else
  9158. SOAP_FREE_UNMANAGED(soap);
  9159. #endif
  9160. }
  9161. /******************************************************************************/
  9162. SOAP_FMAC1
  9163. void
  9164. SOAP_FMAC2
  9165. soap_del(struct soap *soap)
  9166. {
  9167. free(soap);
  9168. }
  9169. /******************************************************************************/
  9170. static void
  9171. soap_free_pht(struct soap *soap)
  9172. {
  9173. struct soap_pblk *pb, *next;
  9174. int i;
  9175. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n"));
  9176. for (pb = soap->pblk; pb; pb = next)
  9177. {
  9178. next = pb->next;
  9179. SOAP_FREE(soap, pb);
  9180. }
  9181. soap->pblk = NULL;
  9182. soap->pidx = 0;
  9183. for (i = 0; i < (int)SOAP_PTRHASH; i++)
  9184. soap->pht[i] = NULL;
  9185. }
  9186. /******************************************************************************/
  9187. #ifndef WITH_NOIDREF
  9188. SOAP_FMAC1
  9189. int
  9190. SOAP_FMAC2
  9191. soap_embed(struct soap *soap, const void *p, const void *a, int n, int t)
  9192. {
  9193. int id;
  9194. struct soap_plist *pp;
  9195. if (soap->version == 2)
  9196. soap->encoding = 1;
  9197. if (!p || (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) || (soap->mode & SOAP_XML_TREE))
  9198. return 0;
  9199. if (a)
  9200. id = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
  9201. else
  9202. id = soap_pointer_lookup(soap, p, t, &pp);
  9203. if (id)
  9204. {
  9205. if (soap_is_embedded(soap, pp)
  9206. || soap_is_single(soap, pp))
  9207. return 0;
  9208. soap_set_embedded(soap, pp);
  9209. }
  9210. return id;
  9211. }
  9212. #endif
  9213. /******************************************************************************/
  9214. SOAP_FMAC1
  9215. int
  9216. SOAP_FMAC2
  9217. soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp)
  9218. {
  9219. struct soap_plist *pp;
  9220. *ppp = NULL;
  9221. if (p)
  9222. {
  9223. for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next)
  9224. {
  9225. if (pp->ptr == p && pp->type == type)
  9226. {
  9227. *ppp = pp;
  9228. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id));
  9229. return pp->id;
  9230. }
  9231. }
  9232. }
  9233. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type));
  9234. return 0;
  9235. }
  9236. /******************************************************************************/
  9237. SOAP_FMAC1
  9238. int
  9239. SOAP_FMAC2
  9240. soap_pointer_enter(struct soap *soap, const void *p, const void *a, int n, int type, struct soap_plist **ppp)
  9241. {
  9242. size_t h;
  9243. struct soap_plist *pp;
  9244. (void)n;
  9245. if (!soap->pblk || soap->pidx >= SOAP_PTRBLK)
  9246. {
  9247. struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk));
  9248. if (!pb)
  9249. {
  9250. soap->error = SOAP_EOM;
  9251. return 0;
  9252. }
  9253. pb->next = soap->pblk;
  9254. soap->pblk = pb;
  9255. soap->pidx = 0;
  9256. }
  9257. *ppp = pp = &soap->pblk->plist[soap->pidx++];
  9258. if (a)
  9259. h = soap_hash_ptr(a);
  9260. else
  9261. h = soap_hash_ptr(p);
  9262. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pointer enter location=%p array=%p size=%lu type=%d id=%d\n", p, a, (unsigned long)n, type, soap->idnum+1));
  9263. pp->next = soap->pht[h];
  9264. pp->type = type;
  9265. pp->mark1 = 0;
  9266. pp->mark2 = 0;
  9267. pp->ptr = p;
  9268. pp->dup = NULL;
  9269. pp->array = a;
  9270. pp->size = n;
  9271. soap->pht[h] = pp;
  9272. pp->id = ++soap->idnum;
  9273. return pp->id;
  9274. }
  9275. /******************************************************************************/
  9276. SOAP_FMAC1
  9277. int
  9278. SOAP_FMAC2
  9279. soap_array_pointer_lookup(struct soap *soap, const void *p, const void *a, int n, int type, struct soap_plist **ppp)
  9280. {
  9281. struct soap_plist *pp;
  9282. *ppp = NULL;
  9283. if (!p || !a)
  9284. return 0;
  9285. for (pp = soap->pht[soap_hash_ptr(a)]; pp; pp = pp->next)
  9286. {
  9287. if (pp->type == type && pp->array == a && pp->size == n)
  9288. {
  9289. *ppp = pp;
  9290. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a, type, pp->id));
  9291. return pp->id;
  9292. }
  9293. }
  9294. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a, type));
  9295. return 0;
  9296. }
  9297. /******************************************************************************/
  9298. SOAP_FMAC1
  9299. int
  9300. SOAP_FMAC2
  9301. soap_begin_count(struct soap *soap)
  9302. {
  9303. soap_free_ns(soap);
  9304. soap->error = SOAP_OK;
  9305. #ifndef WITH_LEANER
  9306. if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME))
  9307. {
  9308. soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME;
  9309. }
  9310. else
  9311. #endif
  9312. {
  9313. soap->mode = soap->omode;
  9314. if ((soap->mode & SOAP_IO_UDP))
  9315. {
  9316. soap->mode &= SOAP_IO;
  9317. soap->mode |= SOAP_IO_BUFFER | SOAP_ENC_PLAIN;
  9318. }
  9319. if ((soap->mode & SOAP_IO) == SOAP_IO_STORE
  9320. || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_PLAIN))
  9321. #ifndef WITH_LEANER
  9322. && !soap->fpreparesend
  9323. #endif
  9324. ))
  9325. soap->mode &= ~SOAP_IO_LENGTH;
  9326. else
  9327. soap->mode |= SOAP_IO_LENGTH;
  9328. }
  9329. #ifdef WITH_ZLIB
  9330. if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
  9331. {
  9332. if (!(soap->mode & SOAP_ENC_DIME))
  9333. soap->mode &= ~SOAP_IO_LENGTH;
  9334. if ((soap->mode & SOAP_ENC_PLAIN))
  9335. soap->mode |= SOAP_IO_BUFFER;
  9336. else
  9337. soap->mode |= SOAP_IO_STORE;
  9338. }
  9339. #endif
  9340. #ifndef WITH_LEANER
  9341. if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
  9342. soap->mode |= SOAP_ENC_MIME;
  9343. else if (!(soap->mode & SOAP_ENC_MIME))
  9344. soap->mode &= ~SOAP_ENC_MTOM;
  9345. if ((soap->mode & SOAP_ENC_MIME))
  9346. soap_select_mime_boundary(soap);
  9347. soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */
  9348. #endif
  9349. soap->count = 0;
  9350. soap->ns = 0;
  9351. soap->null = 0;
  9352. soap->position = 0;
  9353. soap->mustUnderstand = 0;
  9354. soap->encoding = 0;
  9355. soap->part = SOAP_BEGIN_SEND;
  9356. soap->event = 0;
  9357. soap->evlev = 0;
  9358. soap->idnum = 0;
  9359. soap->body = 1;
  9360. soap->level = 0;
  9361. soap_clr_attr(soap);
  9362. soap_set_local_namespaces(soap);
  9363. #ifndef WITH_LEANER
  9364. soap->dime.size = 0; /* accumulate total size of attachments */
  9365. if (soap->fprepareinitsend && (soap->mode & SOAP_IO) != SOAP_IO_STORE && (soap->error = soap->fprepareinitsend(soap)) != SOAP_OK)
  9366. return soap->error;
  9367. #endif
  9368. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=" SOAP_ULONG_FORMAT ")\n", (int)soap->socket, (unsigned int)soap->mode, soap->count));
  9369. #ifndef WITH_LEANER
  9370. if ((soap->mode & SOAP_IO_LENGTH))
  9371. return soap_begin_attachments(soap);
  9372. #endif
  9373. return SOAP_OK;
  9374. }
  9375. /******************************************************************************/
  9376. SOAP_FMAC1
  9377. int
  9378. SOAP_FMAC2
  9379. soap_end_count(struct soap *soap)
  9380. {
  9381. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n"));
  9382. #ifndef WITH_LEANER
  9383. if ((soap->mode & SOAP_IO_LENGTH))
  9384. {
  9385. if (soap_end_attachments(soap))
  9386. return soap->error;
  9387. if (soap->fpreparefinalsend && (soap->error = soap->fpreparefinalsend(soap)) != SOAP_OK)
  9388. return soap->error;
  9389. }
  9390. #else
  9391. (void)soap;
  9392. #endif
  9393. return SOAP_OK;
  9394. }
  9395. /******************************************************************************/
  9396. static int
  9397. soap_init_send(struct soap *soap)
  9398. {
  9399. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for output to socket=%d/fd=%d\n", (int)soap->socket, soap->sendfd));
  9400. *soap->tag = '\0';
  9401. soap_free_ns(soap);
  9402. soap->error = SOAP_OK;
  9403. soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME));
  9404. #ifndef WITH_LEAN
  9405. if ((soap->mode & SOAP_IO_UDP))
  9406. {
  9407. soap->mode &= ~SOAP_IO;
  9408. soap->mode |= SOAP_IO_BUFFER | SOAP_ENC_PLAIN;
  9409. if ((soap->mode & SOAP_IO_LENGTH) && soap->count > sizeof(soap->buf))
  9410. return soap->error = SOAP_UDP_ERROR;
  9411. }
  9412. #endif
  9413. #ifdef WITH_ZLIB
  9414. if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
  9415. {
  9416. if ((soap->mode & SOAP_ENC_PLAIN))
  9417. soap->mode |= SOAP_IO_BUFFER;
  9418. else
  9419. soap->mode |= SOAP_IO_STORE;
  9420. }
  9421. #endif
  9422. #if !defined(__cplusplus) || defined(WITH_COMPAT)
  9423. if (soap->os)
  9424. {
  9425. *soap->os = NULL;
  9426. soap->mode = (soap->mode & ~SOAP_IO) | SOAP_IO_STORE;
  9427. }
  9428. else
  9429. #endif
  9430. if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket))
  9431. {
  9432. if ((soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_PLAIN))
  9433. soap->mode |= SOAP_IO_BUFFER;
  9434. else
  9435. soap->mode |= SOAP_IO_STORE;
  9436. }
  9437. soap->mode &= ~SOAP_IO_LENGTH;
  9438. if ((soap->mode & SOAP_IO) == SOAP_IO_STORE && soap_alloc_block(soap) == NULL)
  9439. return soap->error;
  9440. if (!(soap->mode & SOAP_IO_KEEPALIVE))
  9441. soap->keep_alive = 0;
  9442. #ifndef WITH_LEANER
  9443. if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
  9444. {
  9445. soap->mode |= SOAP_ENC_MIME;
  9446. soap->mode &= ~SOAP_ENC_DIME;
  9447. }
  9448. else if (!(soap->mode & SOAP_ENC_MIME))
  9449. {
  9450. soap->mode &= ~SOAP_ENC_MTOM;
  9451. }
  9452. if ((soap->mode & SOAP_ENC_MIME))
  9453. soap_select_mime_boundary(soap);
  9454. #ifdef WIN32
  9455. #ifndef UNDER_CE
  9456. #ifndef WITH_FASTCGI
  9457. if (!soap_valid_socket(soap->socket) && !soap->os && soap->sendfd >= 0) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
  9458. #ifdef __BORLANDC__
  9459. setmode(soap->sendfd, _O_BINARY);
  9460. #else
  9461. _setmode(soap->sendfd, _O_BINARY);
  9462. #endif
  9463. #endif
  9464. #endif
  9465. #endif
  9466. #endif
  9467. if ((soap->mode & SOAP_IO))
  9468. soap->buflen = soap->bufidx = 0;
  9469. soap->chunksize = 0;
  9470. soap->ns = 0;
  9471. soap->null = 0;
  9472. soap->position = 0;
  9473. soap->mustUnderstand = 0;
  9474. soap->encoding = 0;
  9475. soap->event = 0;
  9476. soap->evlev = 0;
  9477. soap->idnum = 0;
  9478. soap->body = 1;
  9479. soap->level = 0;
  9480. soap_clr_attr(soap);
  9481. soap_set_local_namespaces(soap);
  9482. #ifdef WITH_ZLIB
  9483. soap->z_ratio_out = 1.0;
  9484. if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE)
  9485. {
  9486. if (!soap->d_stream)
  9487. {
  9488. soap->d_stream = (z_stream*)SOAP_MALLOC(soap, sizeof(z_stream));
  9489. if (!soap->d_stream)
  9490. return soap->error = SOAP_EOM;
  9491. soap->d_stream->zalloc = Z_NULL;
  9492. soap->d_stream->zfree = Z_NULL;
  9493. soap->d_stream->opaque = Z_NULL;
  9494. soap->d_stream->next_in = Z_NULL;
  9495. }
  9496. if (!soap->z_buf)
  9497. soap->z_buf = (char*)SOAP_MALLOC(soap, sizeof(soap->buf));
  9498. if (!soap->z_buf)
  9499. return soap->error = SOAP_EOM;
  9500. soap->d_stream->next_out = (Byte*)soap->z_buf;
  9501. soap->d_stream->avail_out = sizeof(soap->buf);
  9502. #ifdef WITH_GZIP
  9503. if (soap->zlib_out != SOAP_ZLIB_DEFLATE)
  9504. {
  9505. (void)soap_memcpy((void*)soap->z_buf, sizeof(soap->buf), (const void*)"\37\213\10\0\0\0\0\0\0\377", 10);
  9506. soap->d_stream->next_out = (Byte*)soap->z_buf + 10;
  9507. soap->d_stream->avail_out = sizeof(soap->buf) - 10;
  9508. soap->z_crc = crc32(0L, NULL, 0);
  9509. soap->zlib_out = SOAP_ZLIB_GZIP;
  9510. if (soap->z_dict)
  9511. *((Byte*)soap->z_buf + 2) = 0xff;
  9512. if (deflateInit2(soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK)
  9513. return soap->error = SOAP_ZLIB_ERROR;
  9514. }
  9515. else
  9516. #endif
  9517. if (deflateInit(soap->d_stream, soap->z_level) != Z_OK)
  9518. return soap->error = SOAP_ZLIB_ERROR;
  9519. if (soap->z_dict)
  9520. {
  9521. if (deflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
  9522. return soap->error = SOAP_ZLIB_ERROR;
  9523. }
  9524. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n"));
  9525. soap->zlib_state = SOAP_ZLIB_DEFLATE;
  9526. }
  9527. #endif
  9528. #ifdef WITH_OPENSSL
  9529. if (soap->ssl)
  9530. ERR_clear_error();
  9531. #endif
  9532. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=" SOAP_ULONG_FORMAT ")\n", (int)soap->socket, soap->mode, soap->count));
  9533. soap->part = SOAP_BEGIN_SEND;
  9534. #ifndef WITH_LEANER
  9535. if (soap->fprepareinitsend && (soap->mode & SOAP_IO) == SOAP_IO_STORE && (soap->error = soap->fprepareinitsend(soap)) != SOAP_OK)
  9536. return soap->error;
  9537. #endif
  9538. #ifndef WITH_LEAN
  9539. soap->start = (ULONG64)time(NULL);
  9540. #endif
  9541. return SOAP_OK;
  9542. }
  9543. /******************************************************************************/
  9544. SOAP_FMAC1
  9545. int
  9546. SOAP_FMAC2
  9547. soap_begin_send(struct soap *soap)
  9548. {
  9549. #ifndef WITH_LEANER
  9550. if (soap_init_send(soap))
  9551. return soap->error;
  9552. return soap_begin_attachments(soap);
  9553. #else
  9554. return soap_init_send(soap);
  9555. #endif
  9556. }
  9557. /******************************************************************************/
  9558. #ifndef WITH_NOIDREF
  9559. SOAP_FMAC1
  9560. void
  9561. SOAP_FMAC2
  9562. soap_embedded(struct soap *soap, const void *p, int t)
  9563. {
  9564. struct soap_plist *pp;
  9565. if (soap_pointer_lookup(soap, p, t, &pp))
  9566. {
  9567. pp->mark1 = 1;
  9568. pp->mark2 = 1;
  9569. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t));
  9570. }
  9571. }
  9572. #endif
  9573. /******************************************************************************/
  9574. #ifndef WITH_NOIDREF
  9575. SOAP_FMAC1
  9576. int
  9577. SOAP_FMAC2
  9578. soap_reference(struct soap *soap, const void *p, int t)
  9579. {
  9580. struct soap_plist *pp;
  9581. if (!p || (!soap->encodingStyle && !(soap->omode & (SOAP_ENC_DIME | SOAP_ENC_MIME | SOAP_ENC_MTOM | SOAP_XML_GRAPH))) || (soap->omode & SOAP_XML_TREE))
  9582. return 1;
  9583. if (soap_pointer_lookup(soap, p, t, &pp))
  9584. {
  9585. if (pp->mark1 == 0)
  9586. {
  9587. pp->mark1 = 2;
  9588. pp->mark2 = 2;
  9589. }
  9590. }
  9591. else if (!soap_pointer_enter(soap, p, NULL, 0, t, &pp))
  9592. {
  9593. return 1;
  9594. }
  9595. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2));
  9596. return pp->mark1;
  9597. }
  9598. #endif
  9599. /******************************************************************************/
  9600. #ifndef WITH_NOIDREF
  9601. SOAP_FMAC1
  9602. int
  9603. SOAP_FMAC2
  9604. soap_array_reference(struct soap *soap, const void *p, const void *a, int n, int t)
  9605. {
  9606. struct soap_plist *pp;
  9607. if (!p || !a || (!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH)) || (soap->omode & SOAP_XML_TREE))
  9608. return 1;
  9609. if (soap_array_pointer_lookup(soap, p, a, n, t, &pp))
  9610. {
  9611. if (pp->mark1 == 0)
  9612. {
  9613. pp->mark1 = 2;
  9614. pp->mark2 = 2;
  9615. }
  9616. }
  9617. else if (!soap_pointer_enter(soap, p, a, n, t, &pp))
  9618. {
  9619. return 1;
  9620. }
  9621. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array reference %p ptr=%p n=%lu t=%d (%d %d)\n", p, a, (unsigned long)n, t, (int)pp->mark1, (int)pp->mark2));
  9622. return pp->mark1;
  9623. }
  9624. #endif
  9625. /******************************************************************************/
  9626. #ifndef WITH_NOIDREF
  9627. SOAP_FMAC1
  9628. int
  9629. SOAP_FMAC2
  9630. soap_attachment_reference(struct soap *soap, const void *p, const void *a, int n, int t, const char *id, const char *type)
  9631. {
  9632. struct soap_plist *pp;
  9633. if (!p || !a || (!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH) && !id && !type) || (soap->omode & SOAP_XML_TREE))
  9634. return 1;
  9635. if (soap_array_pointer_lookup(soap, p, a, n, t, &pp))
  9636. {
  9637. if (pp->mark1 == 0)
  9638. {
  9639. pp->mark1 = 2;
  9640. pp->mark2 = 2;
  9641. }
  9642. }
  9643. else if (!soap_pointer_enter(soap, p, a, n, t, &pp))
  9644. {
  9645. return 1;
  9646. }
  9647. if (id || type)
  9648. soap->mode |= SOAP_ENC_DIME;
  9649. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment reference %p ptr=%p n=%lu t=%d (%d %d)\n", p, a, (unsigned long)n, t, (int)pp->mark1, (int)pp->mark2));
  9650. return pp->mark1;
  9651. }
  9652. #endif
  9653. /******************************************************************************/
  9654. #ifndef WITH_NOIDREF
  9655. SOAP_FMAC1
  9656. int
  9657. SOAP_FMAC2
  9658. soap_embedded_id(struct soap *soap, int id, const void *p, int t)
  9659. {
  9660. struct soap_plist *pp = NULL;
  9661. if (id >= 0 || (!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH)) || (soap->omode & SOAP_XML_TREE))
  9662. return id;
  9663. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id));
  9664. if (id < -1)
  9665. return soap_embed(soap, p, NULL, 0, t);
  9666. if (id < 0)
  9667. {
  9668. id = soap_pointer_lookup(soap, p, t, &pp);
  9669. if (soap->version == 1 && soap->part != SOAP_IN_HEADER)
  9670. {
  9671. if (id)
  9672. {
  9673. if ((soap->mode & SOAP_IO_LENGTH))
  9674. pp->mark1 = 2;
  9675. else
  9676. pp->mark2 = 2;
  9677. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id multiref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2));
  9678. }
  9679. return -1;
  9680. }
  9681. else if (id)
  9682. {
  9683. if ((soap->mode & SOAP_IO_LENGTH))
  9684. pp->mark1 = 1;
  9685. else
  9686. pp->mark2 = 1;
  9687. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id embedded ref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2));
  9688. }
  9689. }
  9690. return id;
  9691. }
  9692. #endif
  9693. /******************************************************************************/
  9694. #ifndef WITH_NOIDREF
  9695. SOAP_FMAC1
  9696. int
  9697. SOAP_FMAC2
  9698. soap_is_embedded(struct soap *soap, struct soap_plist *pp)
  9699. {
  9700. if (!pp)
  9701. return 0;
  9702. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2));
  9703. if (soap->version == 1 && soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
  9704. {
  9705. if ((soap->mode & SOAP_IO_LENGTH))
  9706. return pp->mark1 != 0;
  9707. return pp->mark2 != 0;
  9708. }
  9709. if ((soap->mode & SOAP_IO_LENGTH))
  9710. return pp->mark1 == 1;
  9711. return pp->mark2 == 1;
  9712. }
  9713. #endif
  9714. /******************************************************************************/
  9715. #ifndef WITH_NOIDREF
  9716. SOAP_FMAC1
  9717. int
  9718. SOAP_FMAC2
  9719. soap_is_single(struct soap *soap, struct soap_plist *pp)
  9720. {
  9721. if (soap->part == SOAP_IN_HEADER)
  9722. return 1;
  9723. if (!pp)
  9724. return 0;
  9725. if ((soap->mode & SOAP_IO_LENGTH))
  9726. return pp->mark1 == 0;
  9727. return pp->mark2 == 0;
  9728. }
  9729. #endif
  9730. /******************************************************************************/
  9731. #ifndef WITH_NOIDREF
  9732. SOAP_FMAC1
  9733. void
  9734. SOAP_FMAC2
  9735. soap_set_embedded(struct soap *soap, struct soap_plist *pp)
  9736. {
  9737. if (!pp)
  9738. return;
  9739. if ((soap->mode & SOAP_IO_LENGTH))
  9740. pp->mark1 = 1;
  9741. else
  9742. pp->mark2 = 1;
  9743. }
  9744. #endif
  9745. /******************************************************************************/
  9746. #ifndef WITH_LEANER
  9747. SOAP_FMAC1
  9748. int
  9749. SOAP_FMAC2
  9750. soap_attachment(struct soap *soap, const char *tag, int id, const void *p, const void *a, int n, const char *aid, const char *atype, const char *aoptions, const char *type, int t)
  9751. {
  9752. struct soap_plist *pp;
  9753. int i;
  9754. if (!p || !a || (!aid && !atype) || (!soap->encodingStyle && !(soap->omode & (SOAP_ENC_DIME | SOAP_ENC_MIME | SOAP_ENC_MTOM | SOAP_XML_GRAPH))) || (soap->omode & SOAP_XML_TREE))
  9755. return soap_element_id(soap, tag, id, p, a, n, type, t, NULL);
  9756. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid ? aid : SOAP_STR_EOS, id, atype ? atype : SOAP_STR_EOS));
  9757. i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
  9758. if (!i)
  9759. {
  9760. i = soap_pointer_enter(soap, p, a, n, t, &pp);
  9761. if (!i)
  9762. {
  9763. soap->error = SOAP_EOM;
  9764. return -1;
  9765. }
  9766. }
  9767. if (id <= 0)
  9768. id = i;
  9769. if (!aid)
  9770. {
  9771. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(soap->dime_id_format) + 20), soap->dime_id_format, id);
  9772. aid = soap_strdup(soap, soap->tmpbuf);
  9773. if (!aid)
  9774. return -1;
  9775. }
  9776. /* Add MTOM xop:Include element when necessary */
  9777. /* TODO: this code to be obsoleted with new import/xop.h conventions */
  9778. if ((soap->omode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include"))
  9779. {
  9780. if (soap_element_begin_out(soap, tag, 0, type)
  9781. || soap_element_href(soap, "xop:Include", 0, "xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" href", aid)
  9782. || soap_element_end_out(soap, tag))
  9783. return soap->error;
  9784. }
  9785. else if (soap_element_href(soap, tag, 0, "href", aid))
  9786. {
  9787. return soap->error;
  9788. }
  9789. if ((soap->mode & SOAP_IO_LENGTH))
  9790. {
  9791. if (pp->mark1 != 3)
  9792. {
  9793. struct soap_multipart *content;
  9794. if ((soap->omode & SOAP_ENC_MTOM))
  9795. content = soap_alloc_multipart(soap, &soap->mime.first, &soap->mime.last, (const char*)a, n);
  9796. else
  9797. content = soap_alloc_multipart(soap, &soap->dime.first, &soap->dime.last, (const char*)a, n);
  9798. if (!content)
  9799. {
  9800. soap->error = SOAP_EOM;
  9801. return -1;
  9802. }
  9803. if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */
  9804. {
  9805. if ((soap->omode & SOAP_ENC_MTOM))
  9806. {
  9807. size_t l = strlen(aid) - 1;
  9808. char *s = (char*)soap_malloc(soap, l);
  9809. if (s)
  9810. {
  9811. s[0] = '<';
  9812. (void)soap_strncpy(s + 1, l - 1, aid + 4, l - 3);
  9813. s[l - 2] = '>';
  9814. s[l - 1] = '\0';
  9815. content->id = s;
  9816. }
  9817. }
  9818. else
  9819. {
  9820. content->id = aid + 4;
  9821. }
  9822. }
  9823. else
  9824. {
  9825. content->id = aid;
  9826. }
  9827. content->type = atype;
  9828. content->options = aoptions;
  9829. content->encoding = SOAP_MIME_BINARY;
  9830. pp->mark1 = 3;
  9831. }
  9832. }
  9833. else
  9834. {
  9835. pp->mark2 = 3;
  9836. }
  9837. return -1;
  9838. }
  9839. #endif
  9840. /******************************************************************************/
  9841. #ifndef WITH_NOIDREF
  9842. static void
  9843. soap_init_iht(struct soap *soap)
  9844. {
  9845. int i;
  9846. for (i = 0; i < SOAP_IDHASH; i++)
  9847. soap->iht[i] = NULL;
  9848. }
  9849. #endif
  9850. /******************************************************************************/
  9851. #ifndef WITH_NOIDREF
  9852. static void
  9853. soap_free_iht(struct soap *soap)
  9854. {
  9855. int i;
  9856. struct soap_ilist *ip = NULL, *p = NULL;
  9857. struct soap_flist *fp = NULL, *fq = NULL;
  9858. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n"));
  9859. for (i = 0; i < SOAP_IDHASH; i++)
  9860. {
  9861. for (ip = soap->iht[i]; ip; ip = p)
  9862. {
  9863. for (fp = ip->flist; fp; fp = fq)
  9864. {
  9865. fq = fp->next;
  9866. SOAP_FREE(soap, fp);
  9867. }
  9868. p = ip->next;
  9869. SOAP_FREE(soap, ip);
  9870. }
  9871. soap->iht[i] = NULL;
  9872. }
  9873. }
  9874. #endif
  9875. /******************************************************************************/
  9876. #ifndef WITH_NOIDREF
  9877. SOAP_FMAC1
  9878. struct soap_ilist *
  9879. SOAP_FMAC2
  9880. soap_lookup(struct soap *soap, const char *id)
  9881. {
  9882. struct soap_ilist *ip = NULL;
  9883. for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next)
  9884. if (!strcmp(ip->id, id))
  9885. return ip;
  9886. return NULL;
  9887. }
  9888. #endif
  9889. /******************************************************************************/
  9890. #ifndef WITH_NOIDREF
  9891. SOAP_FMAC1
  9892. struct soap_ilist *
  9893. SOAP_FMAC2
  9894. soap_enter(struct soap *soap, const char *id, int t, size_t n)
  9895. {
  9896. size_t h;
  9897. struct soap_ilist *ip = NULL;
  9898. size_t l = strlen(id);
  9899. if (sizeof(struct soap_ilist) + l > l && (SOAP_MAXALLOCSIZE <= 0 || sizeof(struct soap_ilist) + l <= SOAP_MAXALLOCSIZE))
  9900. ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + l);
  9901. if (ip)
  9902. {
  9903. ip->type = t;
  9904. ip->size = n;
  9905. ip->ptr = NULL;
  9906. ip->spine = NULL;
  9907. ip->link = NULL;
  9908. ip->copy = NULL;
  9909. ip->flist = NULL;
  9910. ip->smart = NULL;
  9911. ip->shaky = 0;
  9912. (void)soap_memcpy((char*)ip->id, l + 1, id, l + 1);
  9913. h = soap_hash(id); /* h = (HASH(id) % SOAP_IDHASH) so soap->iht[h] is safe */
  9914. ip->next = soap->iht[h];
  9915. soap->iht[h] = ip;
  9916. }
  9917. return ip;
  9918. }
  9919. #endif
  9920. /******************************************************************************/
  9921. SOAP_FMAC1
  9922. void*
  9923. SOAP_FMAC2
  9924. soap_malloc(struct soap *soap, size_t n)
  9925. {
  9926. char *p;
  9927. size_t k = n;
  9928. if (SOAP_MAXALLOCSIZE > 0 && n > SOAP_MAXALLOCSIZE)
  9929. {
  9930. soap->error = SOAP_EOM;
  9931. return NULL;
  9932. }
  9933. if (!soap)
  9934. return SOAP_MALLOC(soap, n);
  9935. n += sizeof(short);
  9936. n += (~n+1) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary by rounding up */
  9937. if (n + sizeof(void*) + sizeof(size_t) < k)
  9938. {
  9939. soap->error = SOAP_EOM;
  9940. return NULL;
  9941. }
  9942. p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t));
  9943. if (!p)
  9944. {
  9945. soap->error = SOAP_EOM;
  9946. return NULL;
  9947. }
  9948. /* set a canary word to detect memory overruns and data corruption */
  9949. *(unsigned short*)(p + n - sizeof(unsigned short)) = (unsigned short)SOAP_CANARY;
  9950. /* keep chain of alloced cells for destruction */
  9951. *(void**)(p + n) = soap->alist;
  9952. *(size_t*)(p + n + sizeof(void*)) = n;
  9953. soap->alist = p + n;
  9954. return p;
  9955. }
  9956. /******************************************************************************/
  9957. #ifdef SOAP_MEM_DEBUG
  9958. static void
  9959. soap_init_mht(struct soap *soap)
  9960. {
  9961. int i;
  9962. for (i = 0; i < (int)SOAP_PTRHASH; i++)
  9963. soap->mht[i] = NULL;
  9964. }
  9965. #endif
  9966. /******************************************************************************/
  9967. #ifdef SOAP_MEM_DEBUG
  9968. static void
  9969. soap_free_mht(struct soap *soap)
  9970. {
  9971. int i;
  9972. struct soap_mlist *mp, *mq;
  9973. for (i = 0; i < (int)SOAP_PTRHASH; i++)
  9974. {
  9975. for (mp = soap->mht[i]; mp; mp = mq)
  9976. {
  9977. mq = mp->next;
  9978. if (mp->live)
  9979. fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr);
  9980. free(mp);
  9981. }
  9982. soap->mht[i] = NULL;
  9983. }
  9984. }
  9985. #endif
  9986. /******************************************************************************/
  9987. #ifdef SOAP_MEM_DEBUG
  9988. SOAP_FMAC1
  9989. void*
  9990. SOAP_FMAC2
  9991. soap_track_malloc(struct soap *soap, const char *file, int line, size_t size)
  9992. {
  9993. void *p = malloc(size);
  9994. if (soap)
  9995. {
  9996. size_t h = soap_hash_ptr(p);
  9997. struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist));
  9998. if (soap->fdebug[SOAP_INDEX_TEST])
  9999. {
  10000. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p));
  10001. }
  10002. mp->next = soap->mht[h];
  10003. mp->ptr = p;
  10004. mp->file = file;
  10005. mp->line = line;
  10006. mp->live = 1;
  10007. soap->mht[h] = mp;
  10008. }
  10009. return p;
  10010. }
  10011. #endif
  10012. /******************************************************************************/
  10013. #ifdef SOAP_MEM_DEBUG
  10014. SOAP_FMAC1
  10015. void
  10016. SOAP_FMAC2
  10017. soap_track_free(struct soap *soap, const char *file, int line, void *p)
  10018. {
  10019. if (!soap)
  10020. {
  10021. free(p);
  10022. }
  10023. else
  10024. {
  10025. size_t h = soap_hash_ptr(p);
  10026. struct soap_mlist *mp;
  10027. for (mp = soap->mht[h]; mp; mp = mp->next)
  10028. if (mp->ptr == p)
  10029. break;
  10030. if (mp)
  10031. {
  10032. if (mp->live)
  10033. {
  10034. if (soap->fdebug[SOAP_INDEX_TEST])
  10035. {
  10036. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p));
  10037. }
  10038. free(p);
  10039. mp->live = 0;
  10040. }
  10041. else
  10042. {
  10043. fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line);
  10044. }
  10045. }
  10046. else
  10047. {
  10048. fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p);
  10049. }
  10050. }
  10051. }
  10052. #endif
  10053. /******************************************************************************/
  10054. #ifdef SOAP_MEM_DEBUG
  10055. static void
  10056. soap_track_unlink(struct soap *soap, const void *p)
  10057. {
  10058. size_t h = soap_hash_ptr(p);
  10059. struct soap_mlist *mp;
  10060. for (mp = soap->mht[h]; mp; mp = mp->next)
  10061. if (mp->ptr == p)
  10062. break;
  10063. if (mp)
  10064. mp->live = 0;
  10065. }
  10066. #endif
  10067. /******************************************************************************/
  10068. SOAP_FMAC1
  10069. void
  10070. SOAP_FMAC2
  10071. soap_dealloc(struct soap *soap, void *p)
  10072. {
  10073. if (soap_check_state(soap))
  10074. return;
  10075. if (p)
  10076. {
  10077. char **q;
  10078. for (q = (char**)(void*)&soap->alist; *q; q = *(char***)q)
  10079. {
  10080. if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
  10081. {
  10082. #ifdef SOAP_MEM_DEBUG
  10083. fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
  10084. #endif
  10085. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
  10086. DBGHEX(TEST, *q - 200, 200);
  10087. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
  10088. soap->error = SOAP_MOE;
  10089. return;
  10090. }
  10091. if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
  10092. {
  10093. *q = **(char***)q;
  10094. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p));
  10095. SOAP_FREE(soap, p);
  10096. return;
  10097. }
  10098. }
  10099. soap_delete(soap, p);
  10100. }
  10101. else
  10102. {
  10103. char *q;
  10104. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n"));
  10105. while (soap->alist)
  10106. {
  10107. q = (char*)soap->alist;
  10108. if (*(unsigned short*)(char*)(q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
  10109. {
  10110. #ifdef SOAP_MEM_DEBUG
  10111. fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
  10112. #endif
  10113. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
  10114. DBGHEX(TEST, q - 200, 200);
  10115. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
  10116. soap->error = SOAP_MOE;
  10117. return;
  10118. }
  10119. soap->alist = *(void**)q;
  10120. q -= *(size_t*)(q + sizeof(void*));
  10121. SOAP_FREE(soap, q);
  10122. }
  10123. /* assume these were deallocated: */
  10124. soap->http_content = NULL;
  10125. soap->action = NULL;
  10126. soap->fault = NULL;
  10127. soap->header = NULL;
  10128. soap->bearer = NULL;
  10129. soap->userid = NULL;
  10130. soap->passwd = NULL;
  10131. soap->authrealm = NULL;
  10132. #ifdef WITH_NTLM
  10133. soap->ntlm_challenge = NULL;
  10134. #endif
  10135. #ifndef WITH_LEANER
  10136. soap_clr_mime(soap);
  10137. #endif
  10138. }
  10139. }
  10140. /******************************************************************************/
  10141. SOAP_FMAC1
  10142. void
  10143. SOAP_FMAC2
  10144. soap_delete(struct soap *soap, void *p)
  10145. {
  10146. struct soap_clist **cp;
  10147. if (soap_check_state(soap))
  10148. return;
  10149. cp = &soap->clist;
  10150. if (p)
  10151. {
  10152. while (*cp)
  10153. {
  10154. if (p == (*cp)->ptr)
  10155. {
  10156. struct soap_clist *q = *cp;
  10157. *cp = q->next;
  10158. if (q->fdelete(soap, q))
  10159. {
  10160. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type=%d\n", q->ptr, q->type));
  10161. #ifdef SOAP_MEM_DEBUG
  10162. fprintf(stderr, "new(object type=%d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
  10163. #endif
  10164. }
  10165. SOAP_FREE(soap, q);
  10166. return;
  10167. }
  10168. cp = &(*cp)->next;
  10169. }
  10170. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p));
  10171. }
  10172. else
  10173. {
  10174. while (*cp)
  10175. {
  10176. struct soap_clist *q = *cp;
  10177. *cp = q->next;
  10178. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Delete %p type=%d (cp=%p)\n", q->ptr, q->type, (void*)q));
  10179. if (q->fdelete(soap, q))
  10180. {
  10181. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type=%d\n", q->ptr, q->type));
  10182. #ifdef SOAP_MEM_DEBUG
  10183. fprintf(stderr, "new(object type=%d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
  10184. #endif
  10185. }
  10186. SOAP_FREE(soap, q);
  10187. }
  10188. }
  10189. soap->fault = NULL; /* assume this was deallocated */
  10190. soap->header = NULL; /* assume this was deallocated */
  10191. }
  10192. /******************************************************************************/
  10193. SOAP_FMAC1
  10194. void
  10195. SOAP_FMAC2
  10196. soap_delegate_deletion(struct soap *soap, struct soap *soap_to)
  10197. {
  10198. struct soap_clist *cp;
  10199. char **q;
  10200. #ifdef SOAP_MEM_DEBUG
  10201. void *p;
  10202. struct soap_mlist **mp, *mq;
  10203. size_t h;
  10204. #endif
  10205. for (q = (char**)(void*)&soap->alist; *q; q = *(char***)q)
  10206. {
  10207. if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
  10208. {
  10209. #ifdef SOAP_MEM_DEBUG
  10210. fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
  10211. #endif
  10212. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
  10213. DBGHEX(TEST, *q - 200, 200);
  10214. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
  10215. soap->error = SOAP_MOE;
  10216. return;
  10217. }
  10218. #ifdef SOAP_MEM_DEBUG
  10219. p = (void*)(*q - *(size_t*)(*q + sizeof(void*)));
  10220. h = soap_hash_ptr(p);
  10221. for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next)
  10222. {
  10223. if ((*mp)->ptr == p)
  10224. {
  10225. mq = *mp;
  10226. *mp = mq->next;
  10227. mq->next = soap_to->mht[h];
  10228. soap_to->mht[h] = mq;
  10229. break;
  10230. }
  10231. }
  10232. #endif
  10233. }
  10234. *q = (char*)soap_to->alist;
  10235. soap_to->alist = soap->alist;
  10236. soap->alist = NULL;
  10237. #ifdef SOAP_MEM_DEBUG
  10238. cp = soap->clist;
  10239. while (cp)
  10240. {
  10241. h = soap_hash_ptr(cp);
  10242. for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next)
  10243. {
  10244. if ((*mp)->ptr == cp)
  10245. {
  10246. mq = *mp;
  10247. *mp = mq->next;
  10248. mq->next = soap_to->mht[h];
  10249. soap_to->mht[h] = mq;
  10250. break;
  10251. }
  10252. }
  10253. cp = cp->next;
  10254. }
  10255. #endif
  10256. cp = soap_to->clist;
  10257. if (cp)
  10258. {
  10259. while (cp->next)
  10260. cp = cp->next;
  10261. cp->next = soap->clist;
  10262. }
  10263. else
  10264. {
  10265. soap_to->clist = soap->clist;
  10266. }
  10267. soap->clist = NULL;
  10268. }
  10269. /******************************************************************************/
  10270. SOAP_FMAC1
  10271. struct soap_clist *
  10272. SOAP_FMAC2
  10273. soap_link(struct soap *soap, int t, int n, int (*fdelete)(struct soap*, struct soap_clist*))
  10274. {
  10275. struct soap_clist *cp = NULL;
  10276. if (soap)
  10277. {
  10278. if (n != SOAP_NO_LINK_TO_DELETE)
  10279. {
  10280. cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist));
  10281. if (!cp)
  10282. {
  10283. soap->error = SOAP_EOM;
  10284. }
  10285. else
  10286. {
  10287. cp->next = soap->clist;
  10288. cp->type = t;
  10289. cp->size = n;
  10290. cp->ptr = NULL;
  10291. cp->fdelete = fdelete;
  10292. soap->clist = cp;
  10293. }
  10294. }
  10295. soap->alloced = t;
  10296. }
  10297. return cp;
  10298. }
  10299. /******************************************************************************/
  10300. SOAP_FMAC1
  10301. int
  10302. SOAP_FMAC2
  10303. soap_unlink(struct soap *soap, const void *p)
  10304. {
  10305. char **q;
  10306. struct soap_clist **cp;
  10307. if (soap && p)
  10308. {
  10309. for (q = (char**)(void*)&soap->alist; *q; q = *(char***)q)
  10310. {
  10311. if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
  10312. {
  10313. *q = **(char***)q;
  10314. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p));
  10315. #ifdef SOAP_MEM_DEBUG
  10316. soap_track_unlink(soap, p);
  10317. #endif
  10318. return SOAP_OK; /* found and removed from dealloc chain */
  10319. }
  10320. }
  10321. for (cp = &soap->clist; *cp; cp = &(*cp)->next)
  10322. {
  10323. if (p == (*cp)->ptr)
  10324. {
  10325. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p));
  10326. q = (char**)*cp;
  10327. *cp = (*cp)->next;
  10328. SOAP_FREE(soap, q);
  10329. return SOAP_OK; /* found and removed from dealloc chain */
  10330. }
  10331. }
  10332. }
  10333. return SOAP_ERR;
  10334. }
  10335. /******************************************************************************/
  10336. #ifndef WITH_NOIDREF
  10337. SOAP_FMAC1
  10338. int
  10339. SOAP_FMAC2
  10340. soap_lookup_type(struct soap *soap, const char *id)
  10341. {
  10342. struct soap_ilist *ip;
  10343. if (id && *id)
  10344. {
  10345. ip = soap_lookup(soap, id);
  10346. if (ip)
  10347. {
  10348. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type));
  10349. return ip->type;
  10350. }
  10351. }
  10352. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id));
  10353. return 0;
  10354. }
  10355. #endif
  10356. /******************************************************************************/
  10357. #ifndef WITH_NOIDREF
  10358. SOAP_FMAC1
  10359. short
  10360. SOAP_FMAC2
  10361. soap_begin_shaky(struct soap *soap)
  10362. {
  10363. short f = soap->shaky;
  10364. soap->shaky = 1;
  10365. return f;
  10366. }
  10367. #endif
  10368. /******************************************************************************/
  10369. #ifndef WITH_NOIDREF
  10370. SOAP_FMAC1
  10371. void
  10372. SOAP_FMAC2
  10373. soap_end_shaky(struct soap *soap, short f)
  10374. {
  10375. soap->shaky = f;
  10376. }
  10377. #endif
  10378. /******************************************************************************/
  10379. #ifndef WITH_NOIDREF
  10380. static int
  10381. soap_is_shaky(struct soap *soap, void *p)
  10382. {
  10383. (void)p;
  10384. if (!soap->blist && !soap->shaky)
  10385. return 0;
  10386. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shaky %p\n", p));
  10387. return 1;
  10388. }
  10389. #endif
  10390. /******************************************************************************/
  10391. #ifndef WITH_NOIDREF
  10392. SOAP_FMAC1
  10393. void*
  10394. SOAP_FMAC2
  10395. soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k, int (*fbase)(int, int))
  10396. {
  10397. struct soap_ilist *ip;
  10398. if (!p || !id || !*id)
  10399. return p;
  10400. ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
  10401. if (!ip)
  10402. {
  10403. ip = soap_enter(soap, id, t, n); /* new hash table entry for string id */
  10404. if (!ip)
  10405. return NULL;
  10406. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d location=%p (%u bytes) level=%u\n", id, t, (void*)p, (unsigned int)n, k));
  10407. *p = NULL;
  10408. if (k)
  10409. {
  10410. int i;
  10411. if (k > SOAP_MAXPTRS)
  10412. return NULL;
  10413. ip->spine = (void**)soap_malloc(soap, SOAP_MAXPTRS * sizeof(void*));
  10414. if (!ip->spine)
  10415. return NULL;
  10416. ip->spine[0] = NULL;
  10417. for (i = 1; i < SOAP_MAXPTRS; i++)
  10418. ip->spine[i] = &ip->spine[i - 1];
  10419. *p = &ip->spine[k - 1];
  10420. }
  10421. else
  10422. {
  10423. ip->link = p;
  10424. ip->shaky = soap_is_shaky(soap, (void*)p);
  10425. }
  10426. }
  10427. else if (ip->type != t && (!fbase || !fbase(ip->type, t)) && (!fbase || !fbase(t, ip->type) || soap_type_punned(soap, ip)))
  10428. {
  10429. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup type incompatibility: ref='%s' id-type=%d ref-type=%d\n", id, ip->type, t));
  10430. (void)soap_id_nullify(soap, id);
  10431. return NULL;
  10432. }
  10433. else if (k == 0 && ip->ptr && !ip->shaky) /* when block lists are in use, ip->ptr will change */
  10434. {
  10435. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes) level=%u\n", id, t, ip->ptr, (unsigned int)n, k));
  10436. *p = ip->ptr;
  10437. }
  10438. else
  10439. {
  10440. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes) level=%u\n", id, t, (void*)p, (unsigned int)n, k));
  10441. if (fbase && fbase(t, ip->type) && !soap_type_punned(soap, ip))
  10442. {
  10443. ip->type = t;
  10444. ip->size = n;
  10445. }
  10446. *p = NULL;
  10447. if (k)
  10448. {
  10449. if (!ip->spine)
  10450. {
  10451. int i;
  10452. if (k > SOAP_MAXPTRS)
  10453. return NULL;
  10454. ip->spine = (void**)soap_malloc(soap, SOAP_MAXPTRS * sizeof(void*));
  10455. if (!ip->spine)
  10456. return NULL;
  10457. ip->spine[0] = NULL;
  10458. for (i = 1; i < SOAP_MAXPTRS; i++)
  10459. ip->spine[i] = &ip->spine[i - 1];
  10460. }
  10461. *p = &ip->spine[k - 1];
  10462. if (ip->ptr && !ip->shaky)
  10463. ip->spine[0] = ip->ptr;
  10464. }
  10465. else
  10466. {
  10467. void *q = ip->link;
  10468. ip->link = p;
  10469. ip->shaky = soap_is_shaky(soap, (void*)p);
  10470. *p = q;
  10471. }
  10472. }
  10473. return p;
  10474. }
  10475. #endif
  10476. /******************************************************************************/
  10477. #ifndef WITH_NOIDREF
  10478. SOAP_FMAC1
  10479. void*
  10480. SOAP_FMAC2
  10481. soap_id_forward(struct soap *soap, const char *href, void *p, size_t i, int t, int tt, size_t n, unsigned int k, void (*finsert)(struct soap*, int, int, void*, size_t, const void*, void**), int (*fbase)(int, int))
  10482. {
  10483. struct soap_ilist *ip;
  10484. if (!p || !href || !*href)
  10485. return p;
  10486. ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */
  10487. if (!ip)
  10488. {
  10489. ip = soap_enter(soap, href, t, n); /* new hash table entry for string id */
  10490. if (!ip)
  10491. return NULL;
  10492. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New entry href='%s' type=%d size=%lu level=%d location=%p\n", href, t, (unsigned long)n, k, p));
  10493. }
  10494. else if ((ip->type != t || ip->size != n) && k == 0)
  10495. {
  10496. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forward type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n));
  10497. (void)soap_id_nullify(soap, href);
  10498. return NULL;
  10499. }
  10500. if (finsert || n < sizeof(void*))
  10501. {
  10502. struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist));
  10503. if (!fp)
  10504. {
  10505. soap->error = SOAP_EOM;
  10506. return NULL;
  10507. }
  10508. if (fbase && fbase(t, ip->type) && !soap_type_punned(soap, ip))
  10509. {
  10510. ip->type = t;
  10511. ip->size = n;
  10512. }
  10513. if ((ip->type != t || ip->size != n) && (!fbase || !fbase(ip->type, t)))
  10514. {
  10515. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forward type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n));
  10516. SOAP_FREE(soap, fp);
  10517. (void)soap_id_nullify(soap, href);
  10518. return NULL;
  10519. }
  10520. fp->next = ip->flist;
  10521. fp->type = tt;
  10522. fp->ptr = p;
  10523. fp->level = k;
  10524. fp->index = i;
  10525. fp->finsert = finsert;
  10526. ip->flist = fp;
  10527. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u index=%lu href='%s'\n", t, tt, (unsigned long)n, p, k, (unsigned long)i, href));
  10528. }
  10529. else
  10530. {
  10531. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, t, href));
  10532. *(void**)p = ip->copy;
  10533. ip->copy = p;
  10534. }
  10535. ip->shaky = soap_is_shaky(soap, p);
  10536. return p;
  10537. }
  10538. #endif
  10539. /******************************************************************************/
  10540. SOAP_FMAC1
  10541. void*
  10542. SOAP_FMAC2
  10543. soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*), int (*fbase)(int, int))
  10544. {
  10545. #ifndef WITH_NOIDREF
  10546. struct soap_ilist *ip;
  10547. #endif
  10548. (void)id; (void)fbase;
  10549. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d location=%p size=%lu\n", id, t, p, (unsigned long)n));
  10550. soap->alloced = 0;
  10551. if (!p)
  10552. {
  10553. if (finstantiate)
  10554. {
  10555. p = finstantiate(soap, t, type, arrayType, &n); /* soap->alloced is set in soap_link() */
  10556. t = soap->alloced;
  10557. }
  10558. else
  10559. {
  10560. p = soap_malloc(soap, n);
  10561. soap->alloced = t;
  10562. }
  10563. }
  10564. #ifndef WITH_NOIDREF
  10565. if (!id || !*id)
  10566. #endif
  10567. return p;
  10568. #ifndef WITH_NOIDREF
  10569. ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
  10570. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup entry id='%s' for location=%p type=%d\n", id, p, t));
  10571. if (!ip)
  10572. {
  10573. ip = soap_enter(soap, id, t, n); /* new hash table entry for string id */
  10574. if (!ip)
  10575. return NULL;
  10576. ip->ptr = p;
  10577. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New entry id='%s' type=%d size=%lu location=%p\n", id, t, (unsigned long)n, p));
  10578. if (!soap->alloced)
  10579. ip->shaky = soap_is_shaky(soap, p);
  10580. }
  10581. else if (ip->ptr)
  10582. {
  10583. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id));
  10584. soap_strcpy(soap->id, sizeof(soap->id), id);
  10585. soap->error = SOAP_DUPLICATE_ID;
  10586. return NULL;
  10587. }
  10588. else if ((ip->type != t && (!fbase || !fbase(t, ip->type) || soap_type_punned(soap, ip)))
  10589. || (ip->type == t && ip->size != n && soap_type_punned(soap, ip)))
  10590. {
  10591. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enter type incompatibility id='%s' expect type=%d size=%lu got type=%d size=%lu\n", id, ip->type, (unsigned long)ip->size, t, (unsigned long)n));
  10592. (void)soap_id_nullify(soap, id);
  10593. return NULL;
  10594. }
  10595. else
  10596. {
  10597. ip->type = t;
  10598. ip->size = n;
  10599. ip->ptr = p;
  10600. if (!soap->alloced)
  10601. ip->shaky = soap_is_shaky(soap, p);
  10602. if (soap->alloced || !ip->shaky)
  10603. {
  10604. void **q; /* ptr will not change later, so resolve links now */
  10605. if (ip->spine)
  10606. ip->spine[0] = p;
  10607. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s' type=%d\n", ip->id, ip->type));
  10608. q = (void**)ip->link;
  10609. while (q)
  10610. {
  10611. void *r = *q;
  10612. *q = p;
  10613. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... link %p -> %p\n", (void*)q, p));
  10614. q = (void**)r;
  10615. }
  10616. ip->link = NULL;
  10617. }
  10618. }
  10619. return ip->ptr;
  10620. #endif
  10621. }
  10622. /******************************************************************************/
  10623. SOAP_FMAC1
  10624. void**
  10625. SOAP_FMAC2
  10626. soap_id_smart(struct soap *soap, const char *id, int t, size_t n)
  10627. {
  10628. (void)soap; (void)id; (void)t; (void)n;
  10629. #ifndef WITH_NOIDREF
  10630. if (id && *id)
  10631. {
  10632. struct soap_ilist *ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
  10633. if (!ip)
  10634. {
  10635. ip = soap_enter(soap, id, t, n); /* new hash table entry for string id */
  10636. if (!ip)
  10637. return NULL;
  10638. }
  10639. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New smart shared pointer entry id='%s' type=%d size=%lu smart=%p\n", id, t, (unsigned long)n, ip->smart));
  10640. return &ip->smart;
  10641. }
  10642. #endif
  10643. return NULL;
  10644. }
  10645. /******************************************************************************/
  10646. #ifndef WITH_NOIDREF
  10647. static int
  10648. soap_type_punned(struct soap *soap, const struct soap_ilist *ip)
  10649. {
  10650. const struct soap_flist *fp;
  10651. (void)soap;
  10652. if (ip->ptr || ip->copy)
  10653. return 1;
  10654. for (fp = ip->flist; fp; fp = fp->next)
  10655. if (fp->level == 0)
  10656. return 1;
  10657. return 0;
  10658. }
  10659. #endif
  10660. /******************************************************************************/
  10661. #ifndef WITH_NOIDREF
  10662. SOAP_FMAC1
  10663. int
  10664. SOAP_FMAC2
  10665. soap_id_nullify(struct soap *soap, const char *id)
  10666. {
  10667. int i;
  10668. for (i = 0; i < SOAP_IDHASH; i++)
  10669. {
  10670. struct soap_ilist *ip;
  10671. for (ip = soap->iht[i]; ip; ip = ip->next)
  10672. {
  10673. void *p, *q;
  10674. for (p = ip->link; p; p = q)
  10675. {
  10676. q = *(void**)p;
  10677. *(void**)p = NULL;
  10678. }
  10679. ip->link = NULL;
  10680. }
  10681. }
  10682. soap_strcpy(soap->id, sizeof(soap->id), id);
  10683. return soap->error = SOAP_HREF;
  10684. }
  10685. #endif
  10686. /******************************************************************************/
  10687. SOAP_FMAC1
  10688. int
  10689. SOAP_FMAC2
  10690. soap_end_send(struct soap *soap)
  10691. {
  10692. #ifndef WITH_LEANER
  10693. int err;
  10694. err = soap_end_attachments(soap);
  10695. if (soap->dime.list)
  10696. {
  10697. /* SOAP body referenced attachments must appear first */
  10698. soap->dime.last->next = soap->dime.first;
  10699. soap->dime.first = soap->dime.list->next;
  10700. soap->dime.list->next = NULL;
  10701. soap->dime.last = soap->dime.list;
  10702. }
  10703. if (!err)
  10704. err = soap_putdime(soap);
  10705. if (!err)
  10706. err = soap_putmime(soap);
  10707. soap->mime.list = NULL;
  10708. soap->mime.first = NULL;
  10709. soap->mime.last = NULL;
  10710. soap->dime.list = NULL;
  10711. soap->dime.first = NULL;
  10712. soap->dime.last = NULL;
  10713. if (err)
  10714. return err;
  10715. #endif
  10716. return soap_end_send_flush(soap);
  10717. }
  10718. /******************************************************************************/
  10719. SOAP_FMAC1
  10720. int
  10721. SOAP_FMAC2
  10722. soap_end_send_flush(struct soap *soap)
  10723. {
  10724. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send mode=0x%x\n", soap->mode));
  10725. if ((soap->mode & SOAP_IO)) /* need to flush the remaining data in buffer */
  10726. {
  10727. if (soap_flush(soap))
  10728. #ifdef WITH_ZLIB
  10729. {
  10730. if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state == SOAP_ZLIB_DEFLATE)
  10731. {
  10732. soap->zlib_state = SOAP_ZLIB_NONE;
  10733. deflateEnd(soap->d_stream);
  10734. }
  10735. return soap->error;
  10736. }
  10737. #else
  10738. return soap->error;
  10739. #endif
  10740. #ifdef WITH_ZLIB
  10741. if ((soap->mode & SOAP_ENC_ZLIB) && soap->d_stream)
  10742. {
  10743. int r;
  10744. soap->d_stream->avail_in = 0;
  10745. do
  10746. {
  10747. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n"));
  10748. r = deflate(soap->d_stream, Z_FINISH);
  10749. if (soap->d_stream->avail_out != sizeof(soap->buf))
  10750. {
  10751. if (soap_flush_raw(soap, soap->z_buf, sizeof(soap->buf) - soap->d_stream->avail_out))
  10752. {
  10753. soap->zlib_state = SOAP_ZLIB_NONE;
  10754. deflateEnd(soap->d_stream);
  10755. return soap->error;
  10756. }
  10757. soap->d_stream->next_out = (Byte*)soap->z_buf;
  10758. soap->d_stream->avail_out = sizeof(soap->buf);
  10759. }
  10760. } while (r == Z_OK);
  10761. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
  10762. soap->z_ratio_out = (float)soap->d_stream->total_out / (float)soap->d_stream->total_in;
  10763. soap->mode &= ~SOAP_ENC_ZLIB;
  10764. soap->zlib_state = SOAP_ZLIB_NONE;
  10765. if (deflateEnd(soap->d_stream) != Z_OK || r != Z_STREAM_END)
  10766. {
  10767. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
  10768. return soap->error = SOAP_ZLIB_ERROR;
  10769. }
  10770. #ifdef WITH_GZIP
  10771. if (soap->zlib_out != SOAP_ZLIB_DEFLATE)
  10772. {
  10773. soap->z_buf[0] = soap->z_crc & 0xFF;
  10774. soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF;
  10775. soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF;
  10776. soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF;
  10777. soap->z_buf[4] = soap->d_stream->total_in & 0xFF;
  10778. soap->z_buf[5] = (soap->d_stream->total_in >> 8) & 0xFF;
  10779. soap->z_buf[6] = (soap->d_stream->total_in >> 16) & 0xFF;
  10780. soap->z_buf[7] = (soap->d_stream->total_in >> 24) & 0xFF;
  10781. if (soap_flush_raw(soap, soap->z_buf, 8))
  10782. return soap->error;
  10783. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc));
  10784. }
  10785. #endif
  10786. }
  10787. #endif
  10788. if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
  10789. {
  10790. #if !defined(__cplusplus) || defined(WITH_COMPAT)
  10791. if (soap->os)
  10792. {
  10793. char *b = (char*)soap_push_block(soap, NULL, 1);
  10794. if (b)
  10795. {
  10796. *b = '\0';
  10797. *soap->os = soap_save_block(soap, NULL, NULL, 0);
  10798. }
  10799. }
  10800. else
  10801. #endif
  10802. {
  10803. char *p;
  10804. #ifndef WITH_NOHTTP
  10805. if (!(soap->mode & SOAP_ENC_PLAIN))
  10806. {
  10807. soap->mode--;
  10808. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size));
  10809. if (soap->status >= SOAP_POST)
  10810. soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size);
  10811. else if (soap->status != SOAP_STOP)
  10812. soap->error = soap->fresponse(soap, soap->status, soap->blist->size);
  10813. if (soap->error || soap_flush(soap))
  10814. return soap->error;
  10815. soap->mode++;
  10816. }
  10817. #endif
  10818. for (p = soap_first_block(soap, NULL); p; p = soap_next_block(soap, NULL))
  10819. {
  10820. DBGMSG(SENT, p, soap_block_size(soap, NULL));
  10821. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send %u bytes to socket=%d/fd=%d\n", (unsigned int)soap_block_size(soap, NULL), (int)soap->socket, soap->sendfd));
  10822. soap->error = soap->fsend(soap, p, soap_block_size(soap, NULL));
  10823. if (soap->error)
  10824. {
  10825. soap_end_block(soap, NULL);
  10826. return soap->error;
  10827. }
  10828. }
  10829. soap_end_block(soap, NULL);
  10830. }
  10831. #ifndef WITH_LEANER
  10832. if (soap->fpreparefinalsend && (soap->error = soap->fpreparefinalsend(soap)) != SOAP_OK)
  10833. return soap->error;
  10834. #endif
  10835. if ((soap->omode & SOAP_IO) == SOAP_IO_STORE && (soap->imode & SOAP_IO) != SOAP_IO_STORE)
  10836. soap->omode = (soap->omode & ~SOAP_IO) | (soap->imode & SOAP_IO);
  10837. }
  10838. #ifndef WITH_LEANER
  10839. else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
  10840. {
  10841. DBGMSG(SENT, "\r\n0\r\n\r\n", 7);
  10842. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send 7 bytes to socket=%d/fd=%d\n", (int)soap->socket, soap->sendfd));
  10843. soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7);
  10844. if (soap->error)
  10845. return soap->error;
  10846. }
  10847. #endif
  10848. }
  10849. #ifdef WITH_TCPFIN
  10850. #if defined(WITH_OPENSSL) || defined(WITH_SYSTEMSSL)
  10851. if (!soap->ssl)
  10852. #endif
  10853. if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
  10854. soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR); /* Send TCP FIN */
  10855. #endif
  10856. #if defined(__cplusplus) && !defined(WITH_COMPAT)
  10857. if (soap->os)
  10858. soap->os->flush();
  10859. #endif
  10860. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n"));
  10861. soap->omode &= ~SOAP_SEC_WSUID;
  10862. soap->count = 0;
  10863. soap->part = SOAP_END;
  10864. return SOAP_OK;
  10865. }
  10866. /******************************************************************************/
  10867. SOAP_FMAC1
  10868. int
  10869. SOAP_FMAC2
  10870. soap_end_recv(struct soap *soap)
  10871. {
  10872. soap->part = SOAP_END;
  10873. #ifndef WITH_LEAN
  10874. soap->wsuid = NULL; /* reset before next send */
  10875. soap->c14nexclude = NULL; /* reset before next send */
  10876. soap->c14ninclude = NULL; /* reset before next send */
  10877. #endif
  10878. #ifndef WITH_LEANER
  10879. soap->ffilterrecv = NULL;
  10880. if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap))
  10881. {
  10882. soap->dime.first = NULL;
  10883. soap->dime.last = NULL;
  10884. return soap->error;
  10885. }
  10886. soap->dime.list = soap->dime.first;
  10887. soap->dime.first = NULL;
  10888. soap->dime.last = NULL;
  10889. /* Check if MIME attachments and mime-post-check flag is set, if so call soap_resolve() and return */
  10890. if ((soap->mode & SOAP_ENC_MIME))
  10891. {
  10892. if ((soap->mode & SOAP_MIME_POSTCHECK))
  10893. {
  10894. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Post checking MIME attachments\n"));
  10895. if (!soap->keep_alive)
  10896. soap->keep_alive = -2; /* special case to keep alive */
  10897. #ifndef WITH_NOIDREF
  10898. soap_resolve(soap);
  10899. #endif
  10900. return SOAP_OK;
  10901. }
  10902. if (soap_getmime(soap))
  10903. return soap->error;
  10904. }
  10905. soap->mime.list = soap->mime.first;
  10906. soap->mime.first = NULL;
  10907. soap->mime.last = NULL;
  10908. soap->mime.boundary = NULL;
  10909. if (soap->xlist)
  10910. {
  10911. struct soap_multipart *content;
  10912. for (content = soap->mime.list; content; content = content->next)
  10913. soap_resolve_attachment(soap, content);
  10914. }
  10915. #endif
  10916. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of receive message ok\n"));
  10917. #ifdef WITH_ZLIB
  10918. if ((soap->mode & SOAP_ENC_ZLIB) && soap->d_stream)
  10919. {
  10920. /* Make sure end of compressed content is reached */
  10921. while (soap->d_stream->next_out != Z_NULL)
  10922. if ((int)soap_get1(soap) == EOF)
  10923. break;
  10924. soap->mode &= ~SOAP_ENC_ZLIB;
  10925. (void)soap_memcpy((void*)soap->buf, sizeof(soap->buf), (const void*)soap->z_buf, sizeof(soap->buf));
  10926. soap->bufidx = (char*)soap->d_stream->next_in - soap->z_buf;
  10927. soap->buflen = soap->z_buflen;
  10928. soap->zlib_state = SOAP_ZLIB_NONE;
  10929. if (inflateEnd(soap->d_stream) != Z_OK)
  10930. return soap->error = SOAP_ZLIB_ERROR;
  10931. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate end ok\n"));
  10932. #ifdef WITH_GZIP
  10933. if (soap->zlib_in == SOAP_ZLIB_GZIP)
  10934. {
  10935. soap_wchar c;
  10936. short i;
  10937. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate gzip crc check\n"));
  10938. for (i = 0; i < 8; i++)
  10939. {
  10940. if ((int)(c = soap_get1(soap)) == EOF)
  10941. {
  10942. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Gzip error: unable to read crc value\n"));
  10943. return soap->error = SOAP_ZLIB_ERROR;
  10944. }
  10945. soap->z_buf[i] = (char)c;
  10946. }
  10947. 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)))
  10948. {
  10949. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Gzip inflate error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc));
  10950. return soap->error = SOAP_ZLIB_ERROR;
  10951. }
  10952. 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)))
  10953. {
  10954. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Gzip inflate error: incorrect message length\n"));
  10955. return soap->error = SOAP_ZLIB_ERROR;
  10956. }
  10957. }
  10958. soap->zlib_in = SOAP_ZLIB_NONE;
  10959. #endif
  10960. }
  10961. #endif
  10962. if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
  10963. while ((int)soap->ahead != EOF && !soap_recv_raw(soap))
  10964. continue;
  10965. #ifndef WITH_NOIDREF
  10966. if (soap_resolve(soap))
  10967. return soap->error;
  10968. #endif
  10969. #ifndef WITH_LEANER
  10970. if (soap->xlist)
  10971. {
  10972. if ((soap->mode & SOAP_ENC_MTOM))
  10973. return soap->error = SOAP_MIME_HREF;
  10974. return soap->error = SOAP_DIME_HREF;
  10975. }
  10976. #endif
  10977. soap_free_ns(soap);
  10978. #ifndef WITH_LEANER
  10979. if (soap->fpreparefinalrecv)
  10980. return soap->error = soap->fpreparefinalrecv(soap);
  10981. #endif
  10982. return SOAP_OK;
  10983. }
  10984. /******************************************************************************/
  10985. SOAP_FMAC1
  10986. void
  10987. SOAP_FMAC2
  10988. soap_free_temp(struct soap *soap)
  10989. {
  10990. struct soap_attribute *tp, *tq;
  10991. struct Namespace *ns;
  10992. soap_free_ns(soap);
  10993. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n"));
  10994. while (soap->blist)
  10995. soap_end_block(soap, NULL);
  10996. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n"));
  10997. for (tp = soap->attributes; tp; tp = tq)
  10998. {
  10999. tq = tp->next;
  11000. if (tp->value)
  11001. SOAP_FREE(soap, tp->value);
  11002. SOAP_FREE(soap, tp);
  11003. }
  11004. soap->attributes = NULL;
  11005. #ifdef WITH_FAST
  11006. if (soap->labbuf)
  11007. SOAP_FREE(soap, soap->labbuf);
  11008. soap->labbuf = NULL;
  11009. soap->lablen = 0;
  11010. soap->labidx = 0;
  11011. #endif
  11012. ns = soap->local_namespaces;
  11013. if (ns)
  11014. {
  11015. for (; ns->id; ns++)
  11016. {
  11017. if (ns->out)
  11018. {
  11019. SOAP_FREE(soap, ns->out);
  11020. ns->out = NULL;
  11021. }
  11022. }
  11023. SOAP_FREE(soap, soap->local_namespaces);
  11024. soap->local_namespaces = NULL;
  11025. }
  11026. #ifndef WITH_LEANER
  11027. while (soap->xlist)
  11028. {
  11029. struct soap_xlist *xp = soap->xlist->next;
  11030. SOAP_FREE(soap, soap->xlist);
  11031. soap->xlist = xp;
  11032. }
  11033. #endif
  11034. #ifndef WITH_NOIDREF
  11035. soap_free_iht(soap);
  11036. #endif
  11037. soap_free_pht(soap);
  11038. }
  11039. /******************************************************************************/
  11040. static void
  11041. soap_free_ns(struct soap *soap)
  11042. {
  11043. struct soap_nlist *np, *nq;
  11044. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n"));
  11045. for (np = soap->nlist; np; np = nq)
  11046. {
  11047. nq = np->next;
  11048. SOAP_FREE(soap, np);
  11049. }
  11050. soap->nlist = NULL;
  11051. }
  11052. /******************************************************************************/
  11053. #ifdef SOAP_DEBUG
  11054. static void
  11055. soap_init_logs(struct soap *soap)
  11056. {
  11057. int i;
  11058. for (i = 0; i < SOAP_MAXLOGS; i++)
  11059. {
  11060. soap->logfile[i] = NULL;
  11061. soap->fdebug[i] = NULL;
  11062. }
  11063. }
  11064. #endif
  11065. /******************************************************************************/
  11066. #ifdef SOAP_DEBUG
  11067. SOAP_FMAC1
  11068. void
  11069. SOAP_FMAC2
  11070. soap_open_logfile(struct soap *soap, int i)
  11071. {
  11072. if (soap->logfile[i])
  11073. soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a");
  11074. }
  11075. #endif
  11076. /******************************************************************************/
  11077. #ifdef SOAP_DEBUG
  11078. static void
  11079. soap_close_logfile(struct soap *soap, int i)
  11080. {
  11081. if (soap->fdebug[i])
  11082. {
  11083. fclose(soap->fdebug[i]);
  11084. soap->fdebug[i] = NULL;
  11085. }
  11086. }
  11087. #endif
  11088. /******************************************************************************/
  11089. #ifdef SOAP_DEBUG
  11090. SOAP_FMAC1
  11091. void
  11092. SOAP_FMAC2
  11093. soap_close_logfiles(struct soap *soap)
  11094. {
  11095. int i;
  11096. for (i = 0; i < SOAP_MAXLOGS; i++)
  11097. soap_close_logfile(soap, i);
  11098. }
  11099. #endif
  11100. /******************************************************************************/
  11101. #ifdef SOAP_DEBUG
  11102. static void
  11103. soap_set_logfile(struct soap *soap, int i, const char *logfile)
  11104. {
  11105. const char *s;
  11106. char *t = NULL;
  11107. soap_close_logfile(soap, i);
  11108. s = soap->logfile[i];
  11109. if (s)
  11110. SOAP_FREE_UNMANAGED(s);
  11111. if (logfile)
  11112. {
  11113. size_t l = strlen(logfile) + 1;
  11114. t = (char*)SOAP_MALLOC_UNMANAGED(l);
  11115. if (t)
  11116. (void)soap_memcpy((void*)t, l, (const void*)logfile, l);
  11117. }
  11118. soap->logfile[i] = t;
  11119. }
  11120. #endif
  11121. /******************************************************************************/
  11122. SOAP_FMAC1
  11123. void
  11124. SOAP_FMAC2
  11125. soap_set_recv_logfile(struct soap *soap, const char *logfile)
  11126. {
  11127. (void)soap; (void)logfile;
  11128. #ifdef SOAP_DEBUG
  11129. soap_set_logfile(soap, SOAP_INDEX_RECV, logfile);
  11130. #endif
  11131. }
  11132. /******************************************************************************/
  11133. SOAP_FMAC1
  11134. void
  11135. SOAP_FMAC2
  11136. soap_set_sent_logfile(struct soap *soap, const char *logfile)
  11137. {
  11138. (void)soap; (void)logfile;
  11139. #ifdef SOAP_DEBUG
  11140. soap_set_logfile(soap, SOAP_INDEX_SENT, logfile);
  11141. #endif
  11142. }
  11143. /******************************************************************************/
  11144. SOAP_FMAC1
  11145. void
  11146. SOAP_FMAC2
  11147. soap_set_test_logfile(struct soap *soap, const char *logfile)
  11148. {
  11149. (void)soap; (void)logfile;
  11150. #ifdef SOAP_DEBUG
  11151. soap_set_logfile(soap, SOAP_INDEX_TEST, logfile);
  11152. #endif
  11153. }
  11154. /******************************************************************************/
  11155. SOAP_FMAC1
  11156. struct soap*
  11157. SOAP_FMAC2
  11158. soap_copy(const struct soap *soap)
  11159. {
  11160. struct soap *copy = soap_versioning(soap_new)(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT);
  11161. soap_done(copy);
  11162. if (soap_copy_context(copy, soap) != NULL)
  11163. return copy;
  11164. soap_free(copy);
  11165. return NULL;
  11166. }
  11167. /******************************************************************************/
  11168. SOAP_FMAC1
  11169. struct soap*
  11170. SOAP_FMAC2
  11171. soap_copy_context(struct soap *copy, const struct soap *soap)
  11172. {
  11173. if (copy == soap)
  11174. return copy;
  11175. if (soap_check_state(soap))
  11176. return NULL;
  11177. if (copy)
  11178. {
  11179. struct soap_plugin *p = NULL;
  11180. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying context\n"));
  11181. (void)soap_memcpy((void*)copy, sizeof(struct soap), (const void*)soap, sizeof(struct soap));
  11182. copy->state = SOAP_COPY;
  11183. copy->error = SOAP_OK;
  11184. copy->bearer = NULL;
  11185. copy->userid = NULL;
  11186. copy->passwd = NULL;
  11187. #ifdef WITH_NTLM
  11188. copy->ntlm_challenge = NULL;
  11189. #endif
  11190. copy->nlist = NULL;
  11191. copy->blist = NULL;
  11192. copy->clist = NULL;
  11193. copy->alist = NULL;
  11194. copy->attributes = NULL;
  11195. copy->labbuf = NULL;
  11196. copy->lablen = 0;
  11197. copy->labidx = 0;
  11198. #ifdef SOAP_MEM_DEBUG
  11199. soap_init_mht(copy);
  11200. #endif
  11201. #ifdef SOAP_DEBUG
  11202. soap_init_logs(copy);
  11203. soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]);
  11204. soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]);
  11205. soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]);
  11206. #endif
  11207. copy->namespaces = soap->local_namespaces;
  11208. copy->local_namespaces = NULL;
  11209. soap_set_local_namespaces(copy); /* copy content of soap->local_namespaces */
  11210. copy->namespaces = soap->namespaces; /* point to shared read-only namespaces table */
  11211. copy->c_locale = NULL;
  11212. #ifdef WITH_OPENSSL
  11213. copy->bio = NULL;
  11214. copy->ssl = NULL;
  11215. copy->session = NULL;
  11216. copy->session_host[0] = '\0';
  11217. copy->session_port = 443;
  11218. #endif
  11219. #ifdef WITH_GNUTLS
  11220. copy->session = NULL;
  11221. #endif
  11222. #ifdef WITH_ZLIB
  11223. copy->d_stream = NULL;
  11224. copy->z_buf = NULL;
  11225. #endif
  11226. #ifndef WITH_NOIDREF
  11227. soap_init_iht(copy);
  11228. #endif
  11229. soap_init_pht(copy);
  11230. copy->header = NULL;
  11231. copy->fault = NULL;
  11232. copy->action = NULL;
  11233. #ifndef WITH_LEAN
  11234. #ifdef WITH_COOKIES
  11235. copy->cookies = soap_copy_cookies(copy, soap);
  11236. #else
  11237. copy->cookies = NULL;
  11238. #endif
  11239. #endif
  11240. copy->plugins = NULL;
  11241. for (p = soap->plugins; p; p = p->next)
  11242. {
  11243. struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin));
  11244. if (!q)
  11245. {
  11246. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not allocate plugin '%s'\n", p->id));
  11247. soap_end(copy);
  11248. soap_done(copy);
  11249. return NULL;
  11250. }
  11251. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id));
  11252. *q = *p;
  11253. if (p->fcopy && (copy->error = p->fcopy(copy, q, p)) != SOAP_OK)
  11254. {
  11255. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s' error = %d\n", p->id, copy->error));
  11256. SOAP_FREE(copy, q);
  11257. soap_end(copy);
  11258. soap_done(copy);
  11259. return NULL;
  11260. }
  11261. q->next = copy->plugins;
  11262. copy->plugins = q;
  11263. }
  11264. }
  11265. #ifdef WITH_SELF_PIPE
  11266. pipe(copy->pipe_fd);
  11267. SOAP_SOCKNONBLOCK(copy->pipe_fd[0])
  11268. SOAP_SOCKNONBLOCK(copy->pipe_fd[1])
  11269. #endif
  11270. return copy;
  11271. }
  11272. /******************************************************************************/
  11273. SOAP_FMAC1
  11274. void
  11275. SOAP_FMAC2
  11276. soap_copy_stream(struct soap *copy, struct soap *soap)
  11277. {
  11278. struct soap_attribute *tp = NULL, *tq;
  11279. if (copy == soap)
  11280. return;
  11281. copy->header = soap->header;
  11282. copy->mode = soap->mode;
  11283. copy->imode = soap->imode;
  11284. copy->omode = soap->omode;
  11285. copy->socket = soap->socket;
  11286. copy->sendsk = soap->sendsk;
  11287. copy->recvsk = soap->recvsk;
  11288. copy->transfer_timeout = soap->transfer_timeout;
  11289. copy->recv_maxlength = soap->recv_maxlength;
  11290. copy->recv_timeout = soap->recv_timeout;
  11291. copy->send_timeout = soap->send_timeout;
  11292. copy->connect_timeout = soap->connect_timeout;
  11293. copy->accept_timeout = soap->accept_timeout;
  11294. copy->socket_flags = soap->socket_flags;
  11295. copy->connect_flags = soap->connect_flags;
  11296. copy->bind_flags = soap->bind_flags;
  11297. copy->bind_inet6 = soap->bind_inet6;
  11298. copy->bind_v6only = soap->bind_v6only;
  11299. copy->accept_flags = soap->accept_flags;
  11300. copy->sndbuf = soap->sndbuf;
  11301. copy->rcvbuf = soap->rcvbuf;
  11302. copy->linger_time = soap->linger_time;
  11303. copy->maxlevel = soap->maxlevel;
  11304. copy->maxlength = soap->maxlength;
  11305. copy->maxoccurs = soap->maxoccurs;
  11306. copy->os = soap->os;
  11307. copy->is = soap->is;
  11308. copy->sendfd = soap->sendfd;
  11309. copy->recvfd = soap->recvfd;
  11310. copy->bufidx = soap->bufidx;
  11311. copy->buflen = soap->buflen;
  11312. copy->ahead = soap->ahead;
  11313. copy->cdata = soap->cdata;
  11314. copy->chunksize = soap->chunksize;
  11315. copy->chunkbuflen = soap->chunkbuflen;
  11316. copy->keep_alive = soap->keep_alive;
  11317. copy->tcp_keep_alive = soap->tcp_keep_alive;
  11318. copy->tcp_keep_idle = soap->tcp_keep_idle;
  11319. copy->tcp_keep_intvl = soap->tcp_keep_intvl;
  11320. copy->tcp_keep_cnt = soap->tcp_keep_cnt;
  11321. copy->max_keep_alive = soap->max_keep_alive;
  11322. #ifndef WITH_NOIO
  11323. copy->peer = soap->peer;
  11324. copy->peerlen = soap->peerlen;
  11325. copy->ip = soap->ip;
  11326. copy->ip6[0] = soap->ip6[0];
  11327. copy->ip6[1] = soap->ip6[1];
  11328. copy->ip6[2] = soap->ip6[2];
  11329. copy->ip6[3] = soap->ip6[3];
  11330. copy->port = soap->port;
  11331. (void)soap_memcpy((void*)copy->host, sizeof(copy->host), (const void*)soap->host, sizeof(soap->host));
  11332. (void)soap_memcpy((void*)copy->endpoint, sizeof(copy->endpoint), (const void*)soap->endpoint, sizeof(soap->endpoint));
  11333. #endif
  11334. #ifdef WITH_OPENSSL
  11335. copy->bio = soap->bio;
  11336. copy->ctx = soap->ctx;
  11337. copy->ssl = soap->ssl;
  11338. #endif
  11339. #ifdef WITH_GNUTLS
  11340. copy->session = soap->session;
  11341. #endif
  11342. #ifdef WITH_SYSTEMSSL
  11343. copy->ctx = soap->ctx;
  11344. copy->ssl = soap->ssl;
  11345. #endif
  11346. #ifdef WITH_ZLIB
  11347. copy->zlib_state = soap->zlib_state;
  11348. copy->zlib_in = soap->zlib_in;
  11349. copy->zlib_out = soap->zlib_out;
  11350. if (soap->d_stream && soap->zlib_state != SOAP_ZLIB_NONE)
  11351. {
  11352. if (!copy->d_stream)
  11353. copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream));
  11354. if (copy->d_stream)
  11355. (void)soap_memcpy((void*)copy->d_stream, sizeof(z_stream), (const void*)soap->d_stream, sizeof(z_stream));
  11356. }
  11357. copy->z_crc = soap->z_crc;
  11358. copy->z_ratio_in = soap->z_ratio_in;
  11359. copy->z_ratio_out = soap->z_ratio_out;
  11360. copy->z_buf = NULL;
  11361. copy->z_buflen = soap->z_buflen;
  11362. copy->z_level = soap->z_level;
  11363. if (soap->z_buf && soap->zlib_state != SOAP_ZLIB_NONE)
  11364. {
  11365. copy->z_buf = (char*)SOAP_MALLOC(copy, sizeof(soap->buf));
  11366. if (copy->z_buf)
  11367. (void)soap_memcpy((void*)copy->z_buf, sizeof(soap->buf), (const void*)soap->z_buf, sizeof(soap->buf));
  11368. }
  11369. copy->z_dict = soap->z_dict;
  11370. copy->z_dict_len = soap->z_dict_len;
  11371. #endif
  11372. (void)soap_memcpy((void*)copy->buf, sizeof(copy->buf), (const void*)soap->buf, sizeof(soap->buf));
  11373. /* copy XML parser state */
  11374. soap_free_ns(copy);
  11375. soap_set_local_namespaces(copy);
  11376. copy->version = soap->version;
  11377. if (soap->nlist && soap->local_namespaces)
  11378. {
  11379. struct soap_nlist *np = NULL, *nq;
  11380. /* copy reversed nlist */
  11381. for (nq = soap->nlist; nq; nq = nq->next)
  11382. {
  11383. struct soap_nlist *nr = np;
  11384. size_t n = sizeof(struct soap_nlist) + strlen(nq->id);
  11385. np = (struct soap_nlist*)SOAP_MALLOC(copy, n);
  11386. if (!np)
  11387. {
  11388. np = nr;
  11389. break;
  11390. }
  11391. (void)soap_memcpy((void*)np, n, (const void*)nq, n);
  11392. np->next = nr;
  11393. }
  11394. while (np)
  11395. {
  11396. const char *s = np->ns;
  11397. copy->level = np->level; /* preserve element nesting level */
  11398. if (!s && np->index >= 0)
  11399. {
  11400. s = soap->local_namespaces[np->index].out;
  11401. if (!s)
  11402. s = soap->local_namespaces[np->index].ns;
  11403. }
  11404. if (s)
  11405. (void)soap_push_namespace(copy, np->id, s);
  11406. nq = np;
  11407. np = np->next;
  11408. SOAP_FREE(copy, nq);
  11409. }
  11410. }
  11411. (void)soap_memcpy((void*)copy->tag, sizeof(copy->tag), (const void*)soap->tag, sizeof(soap->tag));
  11412. (void)soap_memcpy((void*)copy->id, sizeof(copy->id), (const void*)soap->id, sizeof(soap->id));
  11413. (void)soap_memcpy((void*)copy->href, sizeof(copy->href), (const void*)soap->href, sizeof(soap->href));
  11414. (void)soap_memcpy((void*)copy->type, sizeof(copy->type), (const void*)soap->type, sizeof(soap->type));
  11415. copy->other = soap->other;
  11416. copy->root = soap->root;
  11417. copy->null = soap->null;
  11418. copy->body = soap->body;
  11419. copy->part = soap->part;
  11420. copy->mustUnderstand = soap->mustUnderstand;
  11421. copy->level = soap->level;
  11422. copy->peeked = soap->peeked;
  11423. /* copy attributes */
  11424. for (tq = soap->attributes; tq; tq = tq->next)
  11425. {
  11426. struct soap_attribute *tr = tp;
  11427. size_t n = sizeof(struct soap_attribute) + strlen(tq->name);
  11428. tp = (struct soap_attribute*)SOAP_MALLOC(copy, n);
  11429. (void)soap_memcpy((void*)tp, n, (const void*)tq, n);
  11430. if (tp->size)
  11431. {
  11432. tp->value = (char*)SOAP_MALLOC(copy, tp->size);
  11433. if (tp->value)
  11434. (void)soap_memcpy((void*)tp->value, tp->size, (const void*)tq->value, tp->size);
  11435. }
  11436. tp->ns = NULL;
  11437. tp->next = tr;
  11438. }
  11439. copy->attributes = tp;
  11440. }
  11441. /******************************************************************************/
  11442. SOAP_FMAC1
  11443. void
  11444. SOAP_FMAC2
  11445. soap_free_stream(struct soap *soap)
  11446. {
  11447. soap->socket = SOAP_INVALID_SOCKET;
  11448. soap->sendsk = SOAP_INVALID_SOCKET;
  11449. soap->recvsk = SOAP_INVALID_SOCKET;
  11450. #ifdef WITH_OPENSSL
  11451. soap->bio = NULL;
  11452. soap->ctx = NULL;
  11453. soap->ssl = NULL;
  11454. #endif
  11455. #ifdef WITH_GNUTLS
  11456. soap->xcred = NULL;
  11457. soap->acred = NULL;
  11458. soap->cache = NULL;
  11459. soap->session = NULL;
  11460. soap->dh_params = NULL;
  11461. soap->rsa_params = NULL;
  11462. #endif
  11463. #ifdef WITH_SYSTEMSSL
  11464. soap->ctx = (gsk_handle)NULL;
  11465. soap->ssl = (gsk_handle)NULL;
  11466. #endif
  11467. #ifdef WITH_ZLIB
  11468. if (soap->z_buf)
  11469. SOAP_FREE(soap, soap->z_buf);
  11470. soap->z_buf = NULL;
  11471. #endif
  11472. }
  11473. /******************************************************************************/
  11474. SOAP_FMAC1
  11475. void
  11476. SOAP_FMAC2
  11477. soap_initialize(struct soap *soap)
  11478. {
  11479. soap_versioning(soap_init)(soap, SOAP_IO_DEFAULT, SOAP_IO_DEFAULT);
  11480. }
  11481. /******************************************************************************/
  11482. SOAP_FMAC1
  11483. void
  11484. SOAP_FMAC2
  11485. soap_versioning(soap_init)(struct soap *soap, soap_mode imode, soap_mode omode)
  11486. {
  11487. size_t i;
  11488. soap->state = SOAP_INIT;
  11489. #ifdef SOAP_MEM_DEBUG
  11490. soap_init_mht(soap);
  11491. #endif
  11492. #ifdef SOAP_DEBUG
  11493. soap_init_logs(soap);
  11494. #endif
  11495. #ifdef TANDEM_NONSTOP
  11496. soap_set_test_logfile(soap, "TESTLOG");
  11497. soap_set_sent_logfile(soap, "SENTLOG");
  11498. soap_set_recv_logfile(soap, "RECVLOG");
  11499. #else
  11500. soap_set_test_logfile(soap, "TEST.log");
  11501. soap_set_sent_logfile(soap, "SENT.log");
  11502. soap_set_recv_logfile(soap, "RECV.log");
  11503. #endif
  11504. #ifdef WITH_SELF_PIPE
  11505. pipe(soap->pipe_fd);
  11506. SOAP_SOCKNONBLOCK(soap->pipe_fd[0])
  11507. SOAP_SOCKNONBLOCK(soap->pipe_fd[1])
  11508. #endif
  11509. soap->version = 0;
  11510. soap->imode = imode;
  11511. soap->omode = omode;
  11512. soap->mode = imode;
  11513. soap->plugins = NULL;
  11514. soap->user = NULL;
  11515. for (i = 0; i < sizeof(soap->data)/sizeof(*soap->data); i++)
  11516. soap->data[i] = NULL;
  11517. soap->bearer = NULL;
  11518. soap->userid = NULL;
  11519. soap->passwd = NULL;
  11520. soap->authrealm = NULL;
  11521. #ifdef WITH_NTLM
  11522. soap->ntlm_challenge = NULL;
  11523. #endif
  11524. #ifndef WITH_NOHTTP
  11525. soap->fpost = http_post;
  11526. soap->fget = http_get;
  11527. soap->fput = http_put;
  11528. soap->fpatch = http_patch;
  11529. soap->fdel = http_del;
  11530. soap->fopt = http_200;
  11531. soap->fhead = http_200;
  11532. soap->fform = NULL;
  11533. soap->fposthdr = http_post_header;
  11534. soap->fresponse = http_response;
  11535. soap->fparse = http_parse;
  11536. soap->fparsehdr = http_parse_header;
  11537. #endif
  11538. soap->fheader = NULL;
  11539. soap->fconnect = NULL;
  11540. soap->fdisconnect = NULL;
  11541. #ifndef WITH_NOIO
  11542. soap->ipv6_multicast_if = 0; /* in_addr_t value */
  11543. soap->ipv4_multicast_if = NULL; /* points to struct in_addr or in_addr_t */
  11544. soap->ipv4_multicast_ttl = 0; /* 0: use default */
  11545. soap->client_port = -1; /* client port to bind, -1 for none */
  11546. soap->client_interface = NULL; /* client interface address, NULL for none */
  11547. #ifndef WITH_IPV6
  11548. soap->fresolve = tcp_gethost;
  11549. #else
  11550. soap->fresolve = NULL;
  11551. #endif
  11552. soap->faccept = tcp_accept;
  11553. soap->fopen = tcp_connect;
  11554. soap->fclose = tcp_disconnect;
  11555. soap->fclosesocket = tcp_closesocket;
  11556. soap->fshutdownsocket = tcp_shutdownsocket;
  11557. soap->fsend = fsend;
  11558. soap->frecv = frecv;
  11559. soap->fpoll = soap_poll;
  11560. #else
  11561. soap->fopen = NULL;
  11562. soap->fclose = NULL;
  11563. soap->fpoll = NULL;
  11564. #endif
  11565. soap->fseterror = NULL;
  11566. soap->fignore = NULL;
  11567. soap->fserveloop = NULL;
  11568. soap->fplugin = fplugin;
  11569. #ifndef WITH_LEANER
  11570. soap->fsvalidate = NULL;
  11571. soap->fwvalidate = NULL;
  11572. soap->feltbegin = NULL;
  11573. soap->feltendin = NULL;
  11574. soap->feltbegout = NULL;
  11575. soap->feltendout = NULL;
  11576. soap->fprepareinitsend = NULL;
  11577. soap->fprepareinitrecv = NULL;
  11578. soap->fpreparesend = NULL;
  11579. soap->fpreparerecv = NULL;
  11580. soap->fpreparefinalsend = NULL;
  11581. soap->fpreparefinalrecv = NULL;
  11582. soap->ffiltersend = NULL;
  11583. soap->ffilterrecv = NULL;
  11584. soap->fdimereadopen = NULL;
  11585. soap->fdimewriteopen = NULL;
  11586. soap->fdimereadclose = NULL;
  11587. soap->fdimewriteclose = NULL;
  11588. soap->fdimeread = NULL;
  11589. soap->fdimewrite = NULL;
  11590. soap->fmimereadopen = NULL;
  11591. soap->fmimewriteopen = NULL;
  11592. soap->fmimereadclose = NULL;
  11593. soap->fmimewriteclose = NULL;
  11594. soap->fmimeread = NULL;
  11595. soap->fmimewrite = NULL;
  11596. #endif
  11597. soap->float_format = "%.9G"; /* Alternative: use "%G" */
  11598. soap->double_format = "%.17lG"; /* Alternative: use "%lG" */
  11599. soap->long_double_format = NULL; /* Defined in custom serializer custom/long_double.c */
  11600. soap->dime_id_format = "cid:id%d"; /* default DIME id format for int id index */
  11601. soap->recv_maxlength = 0x7FFFFFFF; /* default max length of messages received (2GB) */
  11602. soap->recv_timeout = 0;
  11603. soap->send_timeout = 0;
  11604. soap->transfer_timeout = 0;
  11605. soap->connect_timeout = 0;
  11606. soap->accept_timeout = 0;
  11607. soap->socket_flags = 0;
  11608. soap->connect_flags = 0;
  11609. soap->bind_flags = 0;
  11610. #ifdef WITH_IPV6_V6ONLY
  11611. soap->bind_inet6 = 1;
  11612. soap->bind_v6only = 1;
  11613. #else
  11614. soap->bind_inet6 = 0;
  11615. soap->bind_v6only = 0;
  11616. #endif
  11617. soap->accept_flags = 0;
  11618. #ifdef WIN32
  11619. soap->sndbuf = SOAP_BUFLEN + 1; /* this size speeds up windows xfer */
  11620. soap->rcvbuf = SOAP_BUFLEN + 1;
  11621. #else
  11622. soap->sndbuf = SOAP_BUFLEN;
  11623. soap->rcvbuf = SOAP_BUFLEN;
  11624. #endif
  11625. soap->linger_time = 0;
  11626. soap->maxlevel = SOAP_MAXLEVEL;
  11627. soap->maxlength = SOAP_MAXLENGTH;
  11628. soap->maxoccurs = SOAP_MAXOCCURS;
  11629. soap->http_version = "1.1";
  11630. soap->proxy_http_version = "1.0";
  11631. soap->http_content = NULL;
  11632. soap->http_extra_header = NULL;
  11633. soap->actor = NULL;
  11634. soap->lang = "en";
  11635. soap->keep_alive = 0;
  11636. soap->tcp_keep_alive = 0;
  11637. soap->tcp_keep_idle = 0;
  11638. soap->tcp_keep_intvl = 0;
  11639. soap->tcp_keep_cnt = 0;
  11640. soap->max_keep_alive = SOAP_MAXKEEPALIVE;
  11641. soap->ip = 0;
  11642. soap->ip6[0] = 0;
  11643. soap->ip6[1] = 0;
  11644. soap->ip6[2] = 0;
  11645. soap->ip6[3] = 0;
  11646. soap->labbuf = NULL;
  11647. soap->lablen = 0;
  11648. soap->labidx = 0;
  11649. soap->encodingStyle = NULL;
  11650. #ifndef WITH_NONAMESPACES
  11651. soap->namespaces = namespaces;
  11652. #else
  11653. soap->namespaces = NULL;
  11654. #endif
  11655. soap->local_namespaces = NULL;
  11656. soap->nlist = NULL;
  11657. soap->blist = NULL;
  11658. soap->clist = NULL;
  11659. soap->alist = NULL;
  11660. soap->shaky = 0;
  11661. soap->attributes = NULL;
  11662. soap->header = NULL;
  11663. soap->fault = NULL;
  11664. soap->master = SOAP_INVALID_SOCKET;
  11665. soap->socket = SOAP_INVALID_SOCKET;
  11666. soap->sendsk = SOAP_INVALID_SOCKET;
  11667. soap->recvsk = SOAP_INVALID_SOCKET;
  11668. soap->os = NULL;
  11669. soap->is = NULL;
  11670. #ifndef WITH_LEANER
  11671. soap->dom = NULL;
  11672. soap->dime.list = NULL;
  11673. soap->dime.first = NULL;
  11674. soap->dime.last = NULL;
  11675. soap->mime.list = NULL;
  11676. soap->mime.first = NULL;
  11677. soap->mime.last = NULL;
  11678. soap->mime.boundary = NULL;
  11679. soap->mime.start = NULL;
  11680. soap->xlist = NULL;
  11681. #endif
  11682. #ifndef UNDER_CE
  11683. soap->recvfd = 0;
  11684. soap->sendfd = 1;
  11685. #else
  11686. soap->recvfd = stdin;
  11687. soap->sendfd = stdout;
  11688. #endif
  11689. soap->tag[0] = '\0';
  11690. soap->id[0] = '\0';
  11691. soap->href[0] = '\0';
  11692. soap->type[0] = '\0';
  11693. soap->arrayType[0] = '\0';
  11694. soap->arraySize[0] = '\0';
  11695. soap->arrayOffset[0] = '\0';
  11696. soap->endpoint[0] = '\0';
  11697. soap->host[0] = '\0';
  11698. soap->path[0] = '\0';
  11699. soap->port = 0;
  11700. soap->override_host = NULL;
  11701. soap->override_port = 0;
  11702. soap->action = NULL;
  11703. soap->proxy_host = NULL;
  11704. soap->proxy_port = 8080;
  11705. soap->proxy_userid = NULL;
  11706. soap->proxy_passwd = NULL;
  11707. soap->proxy_from = NULL;
  11708. soap->origin = NULL;
  11709. soap->cors_origin = NULL;
  11710. soap->cors_allow = "*";
  11711. soap->cors_method = NULL;
  11712. soap->cors_header = NULL;
  11713. soap->cors_methods = NULL;
  11714. soap->cors_headers = NULL;
  11715. soap->x_frame_options = "SAMEORIGIN";
  11716. soap->prolog = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
  11717. soap->zlib_state = SOAP_ZLIB_NONE;
  11718. soap->zlib_in = SOAP_ZLIB_NONE;
  11719. soap->zlib_out = SOAP_ZLIB_NONE;
  11720. soap->d_stream = NULL;
  11721. soap->z_buf = NULL;
  11722. soap->z_level = 6;
  11723. soap->z_dict = NULL;
  11724. soap->z_dict_len = 0;
  11725. #ifndef WITH_LEAN
  11726. soap->wsuid = NULL;
  11727. soap->c14nexclude = NULL;
  11728. soap->c14ninclude = NULL;
  11729. soap->cookies = NULL;
  11730. soap->cookie_domain = NULL;
  11731. soap->cookie_path = NULL;
  11732. soap->cookie_max = 32;
  11733. #endif
  11734. #ifdef WMW_RPM_IO
  11735. soap->rpmreqid = NULL;
  11736. #endif
  11737. #ifndef WITH_NOIDREF
  11738. soap_init_iht(soap);
  11739. #endif
  11740. soap_init_pht(soap);
  11741. #ifdef WITH_OPENSSL
  11742. if (!soap_ssl_init_done)
  11743. soap_ssl_init();
  11744. soap->fsslauth = ssl_auth_init;
  11745. soap->fsslverify = NULL;
  11746. soap->bio = NULL;
  11747. soap->ssl = NULL;
  11748. soap->ctx = NULL;
  11749. soap->session = NULL;
  11750. soap->session_host[0] = '\0';
  11751. soap->session_port = 443;
  11752. soap->ssl_flags = SOAP_SSL_DEFAULT;
  11753. soap->keyfile = NULL;
  11754. soap->keyid = NULL;
  11755. soap->password = NULL;
  11756. soap->cafile = NULL;
  11757. soap->capath = NULL;
  11758. soap->crlfile = NULL;
  11759. soap->dhfile = NULL;
  11760. soap->randfile = NULL;
  11761. #endif
  11762. #ifdef WITH_GNUTLS
  11763. if (!soap_ssl_init_done)
  11764. soap_ssl_init();
  11765. soap->fsslauth = ssl_auth_init;
  11766. soap->fsslverify = NULL;
  11767. soap->xcred = NULL;
  11768. soap->acred = NULL;
  11769. soap->cache = NULL;
  11770. soap->session = NULL;
  11771. soap->ssl_flags = SOAP_SSL_DEFAULT;
  11772. soap->keyfile = NULL;
  11773. soap->keyid = NULL;
  11774. soap->password = NULL;
  11775. soap->cafile = NULL;
  11776. soap->capath = NULL;
  11777. soap->crlfile = NULL;
  11778. soap->dh_params = NULL;
  11779. soap->rsa_params = NULL;
  11780. #endif
  11781. #ifdef WITH_SYSTEMSSL
  11782. soap->fsslauth = ssl_auth_init;
  11783. soap->fsslverify = NULL;
  11784. soap->bio = NULL;
  11785. soap->ssl = (gsk_handle)NULL;
  11786. soap->ctx = (gsk_handle)NULL;
  11787. soap->session = NULL;
  11788. soap->ssl_flags = SOAP_SSL_DEFAULT;
  11789. soap->keyfile = NULL;
  11790. soap->keyid = NULL;
  11791. soap->password = NULL;
  11792. soap->cafile = NULL;
  11793. soap->capath = NULL;
  11794. soap->crlfile = NULL;
  11795. soap->dhfile = NULL;
  11796. soap->randfile = NULL;
  11797. #endif
  11798. soap->c_locale = NULL;
  11799. soap->buflen = 0;
  11800. soap->bufidx = 0;
  11801. #ifndef WITH_LEANER
  11802. soap->dime.chunksize = 0;
  11803. soap->dime.buflen = 0;
  11804. #endif
  11805. soap->other = 0;
  11806. soap->root = -1;
  11807. soap->null = 0;
  11808. soap->position = 0;
  11809. soap->encoding = 0;
  11810. soap->mustUnderstand = 0;
  11811. soap->ns = 0;
  11812. soap->part = SOAP_END;
  11813. soap->event = 0;
  11814. soap->evlev = 0;
  11815. soap->alloced = 0;
  11816. soap->count = 0;
  11817. soap->length = 0;
  11818. soap->cdata = 0;
  11819. soap->peeked = 0;
  11820. soap->ahead = 0;
  11821. soap->idnum = 0;
  11822. soap->level = 0;
  11823. soap->status = 0;
  11824. soap->error = SOAP_OK;
  11825. soap->errmode = 0;
  11826. soap->errnum = 0;
  11827. }
  11828. /******************************************************************************/
  11829. SOAP_FMAC1
  11830. void
  11831. SOAP_FMAC2
  11832. soap_begin(struct soap *soap)
  11833. {
  11834. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Clean up for input/output\n"));
  11835. soap->error = SOAP_OK;
  11836. if (!soap->keep_alive)
  11837. {
  11838. soap->buflen = 0;
  11839. soap->bufidx = 0;
  11840. }
  11841. soap->encoding = 0;
  11842. soap->mode = 0;
  11843. soap->part = SOAP_END;
  11844. soap->peeked = 0;
  11845. soap->ahead = 0;
  11846. soap->level = 0;
  11847. *soap->endpoint = '\0';
  11848. soap->encodingStyle = SOAP_STR_EOS;
  11849. soap_free_temp(soap);
  11850. }
  11851. /******************************************************************************/
  11852. SOAP_FMAC1
  11853. void
  11854. SOAP_FMAC2
  11855. soap_end(struct soap *soap)
  11856. {
  11857. if (soap_check_state(soap))
  11858. return;
  11859. soap_free_temp(soap);
  11860. soap_dealloc(soap, NULL);
  11861. while (soap->clist)
  11862. {
  11863. struct soap_clist *cp = soap->clist->next;
  11864. SOAP_FREE(soap, soap->clist);
  11865. soap->clist = cp;
  11866. }
  11867. soap_closesock(soap);
  11868. #ifdef SOAP_DEBUG
  11869. soap_close_logfiles(soap);
  11870. #endif
  11871. }
  11872. /******************************************************************************/
  11873. SOAP_FMAC1
  11874. void
  11875. SOAP_FMAC2
  11876. soap_set_version(struct soap *soap, short version)
  11877. {
  11878. soap_set_local_namespaces(soap);
  11879. if (soap->version != version && soap->local_namespaces && soap->local_namespaces[0].id && soap->local_namespaces[1].id)
  11880. {
  11881. if (version == 1)
  11882. {
  11883. soap->local_namespaces[0].ns = soap_env1;
  11884. soap->local_namespaces[1].ns = soap_enc1;
  11885. }
  11886. else if (version == 2)
  11887. {
  11888. soap->local_namespaces[0].ns = soap_env2;
  11889. soap->local_namespaces[1].ns = soap_enc2;
  11890. }
  11891. soap->version = version;
  11892. }
  11893. if (version == 0)
  11894. soap->encodingStyle = SOAP_STR_EOS;
  11895. else
  11896. soap->encodingStyle = NULL;
  11897. }
  11898. /******************************************************************************/
  11899. static void
  11900. soap_version(struct soap *soap)
  11901. {
  11902. struct Namespace *p = soap->local_namespaces;
  11903. if (p)
  11904. {
  11905. const char *ns = p[0].out;
  11906. if (!ns)
  11907. ns = p[0].ns;
  11908. if (ns)
  11909. {
  11910. if (!strcmp(ns, soap_env1))
  11911. {
  11912. soap->version = 1; /* make sure we use SOAP 1.1 */
  11913. if (p[1].out)
  11914. SOAP_FREE(soap, p[1].out);
  11915. p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1));
  11916. if (p[1].out)
  11917. (void)soap_memcpy(p[1].out, sizeof(soap_enc1), soap_enc1, sizeof(soap_enc1));
  11918. }
  11919. else if (!strcmp(ns, soap_env2))
  11920. {
  11921. soap->version = 2; /* make sure we use SOAP 1.2 */
  11922. if (p[1].out)
  11923. SOAP_FREE(soap, p[1].out);
  11924. p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2));
  11925. if (p[1].out)
  11926. (void)soap_memcpy(p[1].out, sizeof(soap_enc2), soap_enc2, sizeof(soap_enc2));
  11927. }
  11928. }
  11929. }
  11930. }
  11931. /******************************************************************************/
  11932. SOAP_FMAC1
  11933. int
  11934. SOAP_FMAC2
  11935. soap_set_namespaces(struct soap *soap, const struct Namespace *p)
  11936. {
  11937. struct Namespace *ns = soap->local_namespaces;
  11938. struct soap_nlist *np, *nq, *nr;
  11939. unsigned int level = soap->level;
  11940. soap->namespaces = p;
  11941. soap->local_namespaces = NULL;
  11942. soap_set_local_namespaces(soap);
  11943. /* reverse the namespace list */
  11944. np = soap->nlist;
  11945. soap->nlist = NULL;
  11946. if (np)
  11947. {
  11948. nq = np->next;
  11949. np->next = NULL;
  11950. while (nq)
  11951. {
  11952. nr = nq->next;
  11953. nq->next = np;
  11954. np = nq;
  11955. nq = nr;
  11956. }
  11957. }
  11958. /* then push on new stack */
  11959. while (np)
  11960. {
  11961. const char *s;
  11962. soap->level = np->level; /* preserve element nesting level */
  11963. s = np->ns;
  11964. if (!s && np->index >= 0 && ns)
  11965. {
  11966. s = ns[np->index].out;
  11967. if (!s)
  11968. s = ns[np->index].ns;
  11969. }
  11970. if (s)
  11971. (void)soap_push_namespace(soap, np->id, s);
  11972. nq = np;
  11973. np = np->next;
  11974. SOAP_FREE(soap, nq);
  11975. }
  11976. if (ns)
  11977. {
  11978. int i;
  11979. for (i = 0; ns[i].id; i++)
  11980. {
  11981. if (ns[i].out)
  11982. {
  11983. SOAP_FREE(soap, ns[i].out);
  11984. ns[i].out = NULL;
  11985. }
  11986. }
  11987. SOAP_FREE(soap, ns);
  11988. }
  11989. soap->level = level; /* restore level */
  11990. return SOAP_OK;
  11991. }
  11992. /******************************************************************************/
  11993. SOAP_FMAC1
  11994. void
  11995. SOAP_FMAC2
  11996. soap_set_local_namespaces(struct soap *soap)
  11997. {
  11998. if (soap->namespaces && !soap->local_namespaces)
  11999. {
  12000. const struct Namespace *ns1;
  12001. struct Namespace *ns2;
  12002. size_t n = 1;
  12003. for (ns1 = soap->namespaces; ns1->id; ns1++)
  12004. n++;
  12005. n *= sizeof(struct Namespace);
  12006. ns2 = (struct Namespace*)SOAP_MALLOC(soap, n);
  12007. if (ns2)
  12008. {
  12009. (void)soap_memcpy((void*)ns2, n, (const void*)soap->namespaces, n);
  12010. if (ns2[0].ns)
  12011. {
  12012. if (!strcmp(ns2[0].ns, soap_env1))
  12013. soap->version = 1;
  12014. else if (!strcmp(ns2[0].ns, soap_env2))
  12015. soap->version = 2;
  12016. }
  12017. soap->local_namespaces = ns2;
  12018. for (; ns2->id; ns2++)
  12019. ns2->out = NULL;
  12020. }
  12021. }
  12022. }
  12023. /******************************************************************************/
  12024. #ifndef WITH_LEAN
  12025. SOAP_FMAC1
  12026. const char *
  12027. SOAP_FMAC2
  12028. soap_tagsearch(const char *big, const char *little)
  12029. {
  12030. if (big && little)
  12031. {
  12032. size_t n = strlen(little);
  12033. const char *s = big;
  12034. while (s)
  12035. {
  12036. const char *t = s;
  12037. size_t i;
  12038. for (i = 0; i < n; i++, t++)
  12039. {
  12040. if (*t != little[i])
  12041. break;
  12042. }
  12043. if (*t == '\0' || *t == ' ')
  12044. {
  12045. if (i == n || (i > 0 && little[i-1] == ':'))
  12046. return s;
  12047. }
  12048. s = strchr(t, ' ');
  12049. if (s)
  12050. s++;
  12051. }
  12052. }
  12053. return NULL;
  12054. }
  12055. #endif
  12056. /******************************************************************************/
  12057. SOAP_FMAC1
  12058. struct soap_nlist *
  12059. SOAP_FMAC2
  12060. soap_lookup_ns(struct soap *soap, const char *tag, size_t n)
  12061. {
  12062. struct soap_nlist *np;
  12063. for (np = soap->nlist; np; np = np->next)
  12064. if (!strncmp(np->id, tag, n) && !np->id[n])
  12065. return np;
  12066. return NULL;
  12067. }
  12068. /******************************************************************************/
  12069. #ifndef WITH_LEAN
  12070. static struct soap_nlist *
  12071. soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized, short isearly)
  12072. {
  12073. struct soap_nlist *np = NULL;
  12074. size_t n, k;
  12075. unsigned int level = soap->level + isearly;
  12076. if (soap_tagsearch(soap->c14nexclude, id))
  12077. return NULL;
  12078. if (!utilized)
  12079. {
  12080. for (np = soap->nlist; np; np = np->next)
  12081. {
  12082. if (!strcmp(np->id, id) && ((!np->ns && *id) || (np->ns && !strcmp(np->ns, ns))))
  12083. break;
  12084. }
  12085. if (np)
  12086. {
  12087. if ((np->level < level || (!np->ns && *id)) && np->index == 1)
  12088. utilized = 1;
  12089. else
  12090. return NULL;
  12091. }
  12092. }
  12093. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", level, id, ns ? ns : "(null)", utilized));
  12094. n = strlen(id);
  12095. if (ns)
  12096. k = strlen(ns) + 1;
  12097. else
  12098. k = 0;
  12099. if (sizeof(struct soap_nlist) + n + k > n && (SOAP_MAXALLOCSIZE <= 0 || sizeof(struct soap_nlist) + n + k <= SOAP_MAXALLOCSIZE))
  12100. np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k);
  12101. if (!np)
  12102. {
  12103. soap->error = SOAP_EOM;
  12104. return NULL;
  12105. }
  12106. np->next = soap->nlist;
  12107. soap->nlist = np;
  12108. soap_strcpy((char*)np->id, n + 1, id);
  12109. if (ns)
  12110. {
  12111. np->ns = np->id + n + 1;
  12112. soap_strcpy((char*)np->ns, k, ns);
  12113. }
  12114. else
  12115. {
  12116. np->ns = NULL;
  12117. }
  12118. np->level = level;
  12119. np->index = utilized;
  12120. return np;
  12121. }
  12122. #endif
  12123. /******************************************************************************/
  12124. #ifndef WITH_LEAN
  12125. static void
  12126. soap_utilize_ns(struct soap *soap, const char *tag, short isearly)
  12127. {
  12128. struct soap_nlist *np;
  12129. size_t n = 0;
  12130. if (!strncmp(tag, "xmlns:", 6))
  12131. {
  12132. tag += 6;
  12133. n = strlen(tag);
  12134. }
  12135. else
  12136. {
  12137. const char *t = strchr(tag, ':');
  12138. if (t)
  12139. n = t - tag;
  12140. }
  12141. np = soap_lookup_ns(soap, tag, n);
  12142. if (np)
  12143. {
  12144. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing namespace of '%s' at level %u utilized=%d at level=%u\n", tag, soap->level + isearly, np->index, np->level));
  12145. if (np->index <= 0)
  12146. {
  12147. if (np->level == soap->level + isearly)
  12148. np->index = 1;
  12149. else
  12150. (void)soap_push_ns(soap, np->id, np->ns, 1, isearly);
  12151. }
  12152. }
  12153. else if (strncmp(tag, "xml", 3))
  12154. {
  12155. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing default namespace of '%s' at level %u\n", tag, soap->level + isearly));
  12156. (void)soap_strncpy(soap->tag, sizeof(soap->tag), tag, n);
  12157. (void)soap_push_ns(soap, soap->tag, NULL, 1, isearly);
  12158. }
  12159. }
  12160. #endif
  12161. /******************************************************************************/
  12162. SOAP_FMAC1
  12163. int
  12164. SOAP_FMAC2
  12165. soap_element(struct soap *soap, const char *tag, int id, const char *type)
  12166. {
  12167. #ifndef WITH_LEAN
  12168. const char *s;
  12169. #endif
  12170. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' level='%u' id='%d' type='%s'\n", tag, soap->level, id, type ? type : SOAP_STR_EOS));
  12171. #ifdef WITH_DOM
  12172. #ifndef WITH_LEAN
  12173. if (soap_tagsearch(soap->wsuid, tag))
  12174. {
  12175. size_t i;
  12176. for (s = tag, i = 0; *s && i < sizeof(soap->href) - 1; s++, i++)
  12177. soap->href[i] = *s == ':' ? '-' : *s;
  12178. soap->href[i] = '\0';
  12179. if (soap_set_attr(soap, "wsu:Id", soap->href, 1))
  12180. return soap->error;
  12181. }
  12182. #endif
  12183. #endif
  12184. soap->level++;
  12185. if (soap->level > soap->maxlevel)
  12186. return soap->error = SOAP_LEVEL;
  12187. #ifdef WITH_DOM
  12188. #ifndef WITH_LEAN
  12189. if ((soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_DOM_ASIS))
  12190. {
  12191. if (soap->evlev >= soap->level)
  12192. soap->evlev = 0;
  12193. if (soap->event == SOAP_SEC_BEGIN && !soap->evlev)
  12194. {
  12195. struct soap_nlist *np;
  12196. /* non-nested wsu:Id found: clear xmlns, re-emit them for exc-c14n */
  12197. for (np = soap->nlist; np; np = np->next)
  12198. {
  12199. int p = soap->c14ninclude ? *soap->c14ninclude == '+' || soap_tagsearch(soap->c14ninclude, np->id) != NULL : 0;
  12200. if (np->index == 2 || p)
  12201. {
  12202. struct soap_nlist *np1 = soap_push_ns(soap, np->id, np->ns, 1, 0);
  12203. if (np1 && !p)
  12204. np1->index = 0;
  12205. }
  12206. }
  12207. soap->evlev = soap->level;
  12208. }
  12209. }
  12210. #endif
  12211. if ((soap->mode & SOAP_XML_DOM))
  12212. {
  12213. struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
  12214. if (!elt)
  12215. return soap->error = SOAP_EOM;
  12216. 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));
  12217. elt->soap = soap;
  12218. elt->next = NULL;
  12219. elt->prnt = soap->dom;
  12220. elt->elts = NULL;
  12221. elt->atts = NULL;
  12222. elt->nstr = NULL;
  12223. elt->name = soap_strdup(soap, tag);
  12224. elt->lead = NULL;
  12225. elt->text = NULL;
  12226. elt->code = NULL;
  12227. elt->tail = NULL;
  12228. elt->node = NULL;
  12229. elt->type = 0;
  12230. if (soap->dom)
  12231. {
  12232. struct soap_dom_element *p = soap->dom->elts;
  12233. if (p)
  12234. {
  12235. while (p->next)
  12236. p = p->next;
  12237. p->next = elt;
  12238. }
  12239. else
  12240. {
  12241. soap->dom->elts = elt;
  12242. }
  12243. }
  12244. soap->dom = elt;
  12245. if (!elt->name)
  12246. return soap->error = SOAP_EOM;
  12247. }
  12248. else
  12249. {
  12250. #endif
  12251. #ifndef WITH_LEAN
  12252. if (!soap->ns)
  12253. {
  12254. if (!(soap->mode & SOAP_XML_CANONICAL) && soap_send(soap, soap->prolog))
  12255. return soap->error;
  12256. }
  12257. else if ((soap->mode & SOAP_XML_INDENT))
  12258. {
  12259. if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
  12260. return soap->error;
  12261. soap->body = 1;
  12262. }
  12263. if ((soap->mode & SOAP_XML_DEFAULTNS))
  12264. {
  12265. size_t n = 0;
  12266. s = strchr(tag, ':');
  12267. if (s)
  12268. n = s++ - tag;
  12269. else
  12270. s = tag;
  12271. if (soap_send_raw(soap, "<", 1)
  12272. || soap_send(soap, s))
  12273. return soap->error;
  12274. if (n)
  12275. {
  12276. struct Namespace *ns = soap->local_namespaces;
  12277. for (; ns && ns->id; ns++)
  12278. {
  12279. if (*ns->id && ns->ns && !strncmp(ns->id, tag, n) && !ns->id[n])
  12280. {
  12281. if (!soap->nlist || *soap->nlist->id || (soap->nlist->ns && strcmp(soap->nlist->ns, ns->ns)))
  12282. {
  12283. (void)soap_push_ns(soap, SOAP_STR_EOS, ns->out ? ns->out : ns->ns, 0, 0);
  12284. if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns))
  12285. return soap->error;
  12286. }
  12287. break;
  12288. }
  12289. }
  12290. }
  12291. #ifndef WITH_NOEMPTYNAMESPACES
  12292. else if (!soap->nlist || *soap->nlist->id || (soap->nlist->ns && *soap->nlist->ns))
  12293. {
  12294. (void)soap_push_ns(soap, SOAP_STR_EOS, SOAP_STR_EOS, 0, 0);
  12295. if (soap_attribute(soap, "xmlns", SOAP_STR_EOS))
  12296. return soap->error;
  12297. }
  12298. #endif
  12299. }
  12300. else
  12301. #endif
  12302. if (soap_send_raw(soap, "<", 1)
  12303. || soap_send(soap, tag))
  12304. return soap->error;
  12305. #ifdef WITH_DOM
  12306. }
  12307. #endif
  12308. if (!soap->ns)
  12309. {
  12310. struct Namespace *ns = soap->local_namespaces;
  12311. int k = -1;
  12312. if (ns)
  12313. {
  12314. while (k-- && ns->id)
  12315. {
  12316. const char *t = ns->out;
  12317. if (!t)
  12318. t = ns->ns;
  12319. if (*ns->id && t && *t)
  12320. {
  12321. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(ns->id) + 6), "xmlns:%s", ns->id);
  12322. if (soap_attribute(soap, soap->tmpbuf, t))
  12323. return soap->error;
  12324. }
  12325. ns++;
  12326. }
  12327. }
  12328. }
  12329. soap->ns = 1; /* namespace table control: ns = 0 or 2 to start, then 1 to stop dumping the table */
  12330. #ifndef WITH_LEAN
  12331. if ((soap->mode & SOAP_XML_CANONICAL))
  12332. {
  12333. if ((soap->mode & SOAP_XML_DEFAULTNS))
  12334. soap_utilize_ns(soap, SOAP_STR_EOS, 0);
  12335. else
  12336. soap_utilize_ns(soap, tag, 0);
  12337. }
  12338. #endif
  12339. if (id > 0)
  12340. {
  12341. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), sizeof(SOAP_BASEREFNAME) + 20), SOAP_BASEREFNAME "%d", id);
  12342. if (soap->version == 2)
  12343. {
  12344. if (soap_attribute(soap, "SOAP-ENC:id", soap->tmpbuf))
  12345. return soap->error;
  12346. }
  12347. else if (soap_attribute(soap, "id", soap->tmpbuf))
  12348. {
  12349. return soap->error;
  12350. }
  12351. }
  12352. if (type && *type && !(soap->mode & SOAP_XML_NOTYPE))
  12353. {
  12354. #ifndef WITH_LEAN
  12355. if ((soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_XML_CANONICAL_NA))
  12356. soap_utilize_ns(soap, type, 0);
  12357. #endif
  12358. if (soap_attribute(soap, "xsi:type", type))
  12359. return soap->error;
  12360. }
  12361. if (soap->null && soap->position > 0 && soap->version == 1)
  12362. {
  12363. int i;
  12364. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf) - 1, 20), "[%d", soap->positions[0]);
  12365. for (i = 1; i < soap->position; i++)
  12366. {
  12367. size_t l = strlen(soap->tmpbuf);
  12368. (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l - 1, 20), ",%d", soap->positions[i]);
  12369. }
  12370. soap_strcat(soap->tmpbuf, sizeof(soap->tmpbuf), "]");
  12371. if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf))
  12372. return soap->error;
  12373. }
  12374. if (soap->mustUnderstand)
  12375. {
  12376. if (soap->actor && *soap->actor)
  12377. {
  12378. if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor))
  12379. return soap->error;
  12380. }
  12381. if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1"))
  12382. return soap->error;
  12383. soap->mustUnderstand = 0;
  12384. }
  12385. if (soap->encoding)
  12386. {
  12387. if (soap->encodingStyle && soap->local_namespaces && soap->local_namespaces[0].id && soap->local_namespaces[1].id)
  12388. {
  12389. if (!*soap->encodingStyle)
  12390. {
  12391. if (soap->local_namespaces[1].out)
  12392. soap->encodingStyle = soap->local_namespaces[1].out;
  12393. else
  12394. soap->encodingStyle = soap->local_namespaces[1].ns;
  12395. }
  12396. if (soap->encodingStyle && soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle))
  12397. return soap->error;
  12398. }
  12399. else
  12400. {
  12401. soap->encodingStyle = NULL;
  12402. }
  12403. soap->encoding = 0;
  12404. }
  12405. soap->null = 0;
  12406. soap->position = 0;
  12407. return SOAP_OK;
  12408. }
  12409. /******************************************************************************/
  12410. SOAP_FMAC1
  12411. int
  12412. SOAP_FMAC2
  12413. soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type)
  12414. {
  12415. if (*tag == '-')
  12416. return SOAP_OK;
  12417. #ifdef WITH_DOM
  12418. if (soap->feltbegout)
  12419. return soap->error = soap->feltbegout(soap, tag, id, type);
  12420. #endif
  12421. if (soap_element(soap, tag, id, type))
  12422. return soap->error;
  12423. return soap_element_start_end_out(soap, NULL);
  12424. }
  12425. /******************************************************************************/
  12426. #if _MSC_VER < 1400 && !defined(HAVE_STRLCAT)
  12427. /* concat string (truncating the result, strings must not be NULL) */
  12428. SOAP_FMAC1
  12429. void
  12430. SOAP_FMAC2
  12431. soap_strcat(char *t, size_t n, const char *s)
  12432. {
  12433. size_t k = strlen(t);
  12434. if (k < n)
  12435. {
  12436. t += k;
  12437. n -= k;
  12438. while (--n > 0 && *s)
  12439. *t++ = *s++;
  12440. *t = '\0';
  12441. }
  12442. }
  12443. #endif
  12444. /******************************************************************************/
  12445. #if _MSC_VER < 1400
  12446. /* concat string up to m chars (leaves destination intact on overrun and returns nonzero, zero if OK) */
  12447. SOAP_FMAC1
  12448. int
  12449. SOAP_FMAC2
  12450. soap_strncat(char *t, size_t n, const char *s, size_t m)
  12451. {
  12452. size_t k;
  12453. if (!t || !s)
  12454. return 1;
  12455. k = strlen(t);
  12456. if (n <= k + m)
  12457. return 1;
  12458. t += k;
  12459. n -= k;
  12460. while (--n > 0 && *s)
  12461. *t++ = *s++;
  12462. *t = '\0';
  12463. return 0;
  12464. }
  12465. #endif
  12466. /******************************************************************************/
  12467. #ifndef HAVE_STRRCHR
  12468. SOAP_FMAC1
  12469. char*
  12470. SOAP_FMAC2
  12471. soap_strrchr(const char *s, int t)
  12472. {
  12473. char *r = NULL;
  12474. while (*s)
  12475. if (*s++ == t)
  12476. r = (char*)s - 1;
  12477. return r;
  12478. }
  12479. #endif
  12480. /******************************************************************************/
  12481. #ifndef HAVE_STRTOL
  12482. SOAP_FMAC1
  12483. long
  12484. SOAP_FMAC2
  12485. soap_strtol(const char *s, char **t, int b)
  12486. {
  12487. long n = 0;
  12488. int c;
  12489. while (*s > 0 && *s <= 32)
  12490. s++;
  12491. if (b == 10)
  12492. {
  12493. short neg = 0;
  12494. if (*s == '-')
  12495. {
  12496. s++;
  12497. neg = 1;
  12498. }
  12499. else if (*s == '+')
  12500. {
  12501. s++;
  12502. }
  12503. while ((c = *s) && c >= '0' && c <= '9')
  12504. {
  12505. if (n >= 214748364 && (n > 214748364 || c >= '8'))
  12506. {
  12507. if (neg && n == 214748364 && c == '8')
  12508. {
  12509. if (t)
  12510. *t = (char*)(s + 1);
  12511. return -2147483648;
  12512. }
  12513. break;
  12514. }
  12515. n *= 10;
  12516. n += c - '0';
  12517. s++;
  12518. }
  12519. if (neg)
  12520. n = -n;
  12521. }
  12522. else /* assume b == 16 and value is always positive */
  12523. {
  12524. while ((c = *s))
  12525. {
  12526. if (c >= '0' && c <= '9')
  12527. c -= '0';
  12528. else if (c >= 'A' && c <= 'F')
  12529. c -= 'A' - 10;
  12530. else if (c >= 'a' && c <= 'f')
  12531. c -= 'a' - 10;
  12532. if (n > 0x07FFFFFF)
  12533. break;
  12534. n <<= 4;
  12535. n += c;
  12536. s++;
  12537. }
  12538. }
  12539. if (t)
  12540. *t = (char*)s;
  12541. return n;
  12542. }
  12543. #endif
  12544. /******************************************************************************/
  12545. #ifndef HAVE_STRTOUL
  12546. SOAP_FMAC1
  12547. unsigned long
  12548. SOAP_FMAC2
  12549. soap_strtoul(const char *s, char **t, int b)
  12550. {
  12551. unsigned long n = 0;
  12552. int c;
  12553. while (*s > 0 && *s <= 32)
  12554. s++;
  12555. if (b == 10)
  12556. {
  12557. short neg = 0;
  12558. if (*s == '-')
  12559. {
  12560. s++;
  12561. neg = 1;
  12562. }
  12563. else if (*s == '+')
  12564. {
  12565. s++;
  12566. }
  12567. while ((c = *s) && c >= '0' && c <= '9')
  12568. {
  12569. if (n >= 429496729 && (n > 429496729 || c >= '6'))
  12570. break;
  12571. n *= 10;
  12572. n += c - '0';
  12573. s++;
  12574. }
  12575. if (neg && n > 0)
  12576. s--;
  12577. }
  12578. else /* b == 16 */
  12579. {
  12580. while ((c = *s))
  12581. {
  12582. if (c >= '0' && c <= '9')
  12583. c -= '0';
  12584. else if (c >= 'A' && c <= 'F')
  12585. c -= 'A' - 10;
  12586. else if (c >= 'a' && c <= 'f')
  12587. c -= 'a' - 10;
  12588. if (n > 0x0FFFFFFF)
  12589. break;
  12590. n <<= 4;
  12591. n += c;
  12592. s++;
  12593. }
  12594. }
  12595. if (t)
  12596. *t = (char*)s;
  12597. return n;
  12598. }
  12599. #endif
  12600. /******************************************************************************/
  12601. #ifndef soap_strtoll
  12602. SOAP_FMAC1
  12603. LONG64
  12604. SOAP_FMAC2
  12605. soap_strtoll(const char *s, char **t, int b)
  12606. {
  12607. LONG64 n = 0LL;
  12608. int c;
  12609. while (*s > 0 && *s <= 32)
  12610. s++;
  12611. if (b == 10)
  12612. {
  12613. short neg = 0;
  12614. if (*s == '-')
  12615. {
  12616. s++;
  12617. neg = 1;
  12618. }
  12619. else if (*s == '+')
  12620. {
  12621. s++;
  12622. }
  12623. while ((c = *s) && c >= '0' && c <= '9')
  12624. {
  12625. if (n >= 922337203685477580LL && (n > 922337203685477580LL || c >= '8'))
  12626. {
  12627. if (neg && n == 922337203685477580LL && c == '8')
  12628. {
  12629. if (t)
  12630. *t = (char*)(s + 1);
  12631. return -9223372036854775807LL - 1LL; /* appease compilers that complain */
  12632. }
  12633. break;
  12634. }
  12635. n *= 10LL;
  12636. n += c - '0';
  12637. s++;
  12638. }
  12639. if (neg)
  12640. n = -n;
  12641. }
  12642. else /* assume b == 16 and value is always positive */
  12643. {
  12644. while ((c = *s))
  12645. {
  12646. if (c >= '0' && c <= '9')
  12647. c -= '0';
  12648. else if (c >= 'A' && c <= 'F')
  12649. c -= 'A' - 10;
  12650. else if (c >= 'a' && c <= 'f')
  12651. c -= 'a' - 10;
  12652. if (n > 0x07FFFFFFFFFFFFFFLL)
  12653. break;
  12654. n <<= 4;
  12655. n += c;
  12656. s++;
  12657. }
  12658. }
  12659. if (t)
  12660. *t = (char*)s;
  12661. return n;
  12662. }
  12663. #endif
  12664. /******************************************************************************/
  12665. #ifndef soap_strtoull
  12666. SOAP_FMAC1
  12667. ULONG64
  12668. SOAP_FMAC2
  12669. soap_strtoull(const char *s, char **t, int b)
  12670. {
  12671. ULONG64 n = 0UL;
  12672. int c;
  12673. while (*s > 0 && *s <= 32)
  12674. s++;
  12675. if (b == 10)
  12676. {
  12677. short neg = 0;
  12678. if (*s == '-')
  12679. {
  12680. s++;
  12681. neg = 1;
  12682. }
  12683. else if (*s == '+')
  12684. {
  12685. s++;
  12686. }
  12687. while ((c = *s) && c >= '0' && c <= '9')
  12688. {
  12689. if (n >= 1844674407370955161ULL)
  12690. break;
  12691. n *= 10UL;
  12692. n += c - '0';
  12693. s++;
  12694. }
  12695. if (neg && n > 0UL)
  12696. s--;
  12697. }
  12698. else /* b == 16 */
  12699. {
  12700. while ((c = *s))
  12701. {
  12702. if (c >= '0' && c <= '9')
  12703. c -= '0';
  12704. else if (c >= 'A' && c <= 'F')
  12705. c -= 'A' - 10;
  12706. else if (c >= 'a' && c <= 'f')
  12707. c -= 'a' - 10;
  12708. if (n > 0x0FFFFFFFFFFFFFFFULL)
  12709. break;
  12710. n <<= 4;
  12711. n += c;
  12712. s++;
  12713. }
  12714. }
  12715. if (t)
  12716. *t = (char*)s;
  12717. return n;
  12718. }
  12719. #endif
  12720. /******************************************************************************/
  12721. SOAP_FMAC1
  12722. int
  12723. SOAP_FMAC2
  12724. soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset)
  12725. {
  12726. if (!type || !*type || soap->version == 0)
  12727. return soap_element_begin_out(soap, tag, id, NULL);
  12728. if (soap_element(soap, tag, id, NULL))
  12729. return soap->error;
  12730. if (soap->version == 1)
  12731. {
  12732. if (offset && soap_attribute(soap, "SOAP-ENC:offset", offset))
  12733. return soap->error;
  12734. if (soap_attribute(soap, "SOAP-ENC:arrayType", type))
  12735. return soap->error;
  12736. }
  12737. else
  12738. {
  12739. const char *s;
  12740. s = strchr(type, '[');
  12741. if (s && (size_t)(s - type) < sizeof(soap->tmpbuf))
  12742. {
  12743. (void)soap_strncpy(soap->tmpbuf, sizeof(soap->tmpbuf), type, s - type);
  12744. if (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))
  12745. return soap->error;
  12746. s++;
  12747. if (*s && *s != ']')
  12748. {
  12749. soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), s);
  12750. soap->tmpbuf[strlen(soap->tmpbuf) - 1] = '\0';
  12751. if (soap_attribute(soap, "SOAP-ENC:arraySize", soap->tmpbuf))
  12752. return soap->error;
  12753. }
  12754. }
  12755. }
  12756. #ifndef WITH_LEAN
  12757. if ((soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_XML_CANONICAL_NA))
  12758. soap_utilize_ns(soap, type, 0);
  12759. #endif
  12760. return soap_element_start_end_out(soap, NULL);
  12761. }
  12762. /******************************************************************************/
  12763. SOAP_FMAC1
  12764. int
  12765. SOAP_FMAC2
  12766. soap_element_start_end_out(struct soap *soap, const char *tag)
  12767. {
  12768. struct soap_attribute *tp;
  12769. #ifndef WITH_LEAN
  12770. if ((soap->mode & SOAP_XML_CANONICAL))
  12771. {
  12772. struct soap_nlist *np;
  12773. for (tp = soap->attributes; tp; tp = tp->next)
  12774. {
  12775. if (tp->visible && *tp->name && strchr(tp->name, ':'))
  12776. soap_utilize_ns(soap, tp->name, 0);
  12777. }
  12778. if (soap->event == SOAP_SEC_BEGIN)
  12779. {
  12780. for (np = soap->nlist; np; np = np->next)
  12781. if (soap_tagsearch(soap->c14ninclude, np->id))
  12782. (void)soap_push_ns(soap, np->id, np->ns, 1, 0);
  12783. soap->event = 0;
  12784. soap->evlev = 0;
  12785. }
  12786. for (np = soap->nlist; np; np = np->next)
  12787. {
  12788. if (np->ns && np->index == 1)
  12789. {
  12790. if (*np->id)
  12791. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(np->id) + 6), "xmlns:%s", np->id);
  12792. else
  12793. soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns");
  12794. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enabling utilized binding (level=%u) %s='%s' SEC-BEGIN=%d c14ninclude='%s'\n", np->level, soap->tmpbuf, np->ns, soap->event == SOAP_SEC_BEGIN, soap->c14ninclude ? soap->c14ninclude : "(null)"));
  12795. np->index = 2;
  12796. soap->level--;
  12797. if (*np->id || *np->ns || soap->level > 1)
  12798. if (soap_set_attr(soap, soap->tmpbuf, np->ns, 1))
  12799. return soap->error;
  12800. soap->level++;
  12801. }
  12802. else
  12803. {
  12804. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Binding (level=%u) %s='%s' utilized=%d\n", np->level, np->id, np->ns, np->index));
  12805. }
  12806. }
  12807. }
  12808. #endif
  12809. #ifdef WITH_DOM
  12810. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  12811. {
  12812. struct soap_dom_attribute **att;
  12813. att = &soap->dom->atts;
  12814. for (tp = soap->attributes; tp; tp = tp->next)
  12815. {
  12816. if (tp->visible)
  12817. {
  12818. *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
  12819. if (!*att)
  12820. return soap->error;
  12821. (*att)->next = NULL;
  12822. (*att)->nstr = NULL;
  12823. (*att)->name = soap_strdup(soap, tp->name);
  12824. (*att)->text = soap_strdup(soap, tp->value);
  12825. (*att)->soap = soap;
  12826. if (!(*att)->name || (tp->value && !(*att)->text))
  12827. return soap->error = SOAP_EOM;
  12828. att = &(*att)->next;
  12829. tp->visible = 0;
  12830. }
  12831. }
  12832. return SOAP_OK;
  12833. }
  12834. #endif
  12835. for (tp = soap->attributes; tp; tp = tp->next)
  12836. {
  12837. if (tp->visible)
  12838. {
  12839. if (soap_send_raw(soap, " ", 1) || soap_send(soap, tp->name))
  12840. return soap->error;
  12841. if (tp->visible == 2 && tp->value)
  12842. {
  12843. if (soap_send_raw(soap, "=\"", 2)
  12844. || soap_string_out(soap, tp->value, tp->flag)
  12845. || soap_send_raw(soap, "\"", 1))
  12846. return soap->error;
  12847. }
  12848. else
  12849. {
  12850. if (soap_send_raw(soap, "=\"\"", 3))
  12851. return soap->error;
  12852. }
  12853. tp->visible = 0;
  12854. }
  12855. }
  12856. if (tag)
  12857. {
  12858. #ifndef WITH_LEAN
  12859. if ((soap->mode & SOAP_XML_CANONICAL))
  12860. {
  12861. if (soap_send_raw(soap, ">", 1)
  12862. || soap_element_end_out(soap, tag))
  12863. return soap->error;
  12864. return SOAP_OK;
  12865. }
  12866. #endif
  12867. if (soap->nlist)
  12868. soap_pop_namespace(soap);
  12869. soap->level--; /* decrement level just before /> */
  12870. soap->body = 0;
  12871. return soap_send_raw(soap, "/>", 2);
  12872. }
  12873. return soap_send_raw(soap, ">", 1);
  12874. }
  12875. /******************************************************************************/
  12876. SOAP_FMAC1
  12877. int
  12878. SOAP_FMAC2
  12879. soap_element_end_out(struct soap *soap, const char *tag)
  12880. {
  12881. if (*tag == '-')
  12882. return SOAP_OK;
  12883. #ifdef WITH_DOM
  12884. if (soap->feltendout)
  12885. return soap->error = soap->feltendout(soap, tag);
  12886. #endif
  12887. return soap_element_end(soap, tag);
  12888. }
  12889. /******************************************************************************/
  12890. SOAP_FMAC1
  12891. int
  12892. SOAP_FMAC2
  12893. soap_element_end(struct soap *soap, const char *tag)
  12894. {
  12895. #ifndef WITH_LEAN
  12896. const char *s;
  12897. #endif
  12898. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag));
  12899. #ifdef WITH_DOM
  12900. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  12901. {
  12902. if (soap->dom->prnt)
  12903. soap->dom = soap->dom->prnt;
  12904. return SOAP_OK;
  12905. }
  12906. #endif
  12907. #ifndef WITH_LEAN
  12908. if (soap->nlist)
  12909. soap_pop_namespace(soap);
  12910. if ((soap->mode & SOAP_XML_INDENT))
  12911. {
  12912. if (!soap->body)
  12913. {
  12914. if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
  12915. return soap->error;
  12916. }
  12917. soap->body = 0;
  12918. }
  12919. if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':')) != NULL)
  12920. tag = s + 1;
  12921. #endif
  12922. if (soap_send_raw(soap, "</", 2)
  12923. || soap_send(soap, tag))
  12924. return soap->error;
  12925. soap->level--; /* decrement level just before > */
  12926. return soap_send_raw(soap, ">", 1);
  12927. }
  12928. /******************************************************************************/
  12929. SOAP_FMAC1
  12930. int
  12931. SOAP_FMAC2
  12932. soap_element_ref(struct soap *soap, const char *tag, int id, int href)
  12933. {
  12934. const char *s = "ref";
  12935. int n = 1;
  12936. if (soap->version == 1)
  12937. {
  12938. s = "href";
  12939. n = 0;
  12940. }
  12941. else if (soap->version == 2)
  12942. {
  12943. s = "SOAP-ENC:ref";
  12944. }
  12945. (SOAP_SNPRINTF(soap->href, sizeof(soap->href), sizeof(SOAP_BASEREFNAME) + 21), "#" SOAP_BASEREFNAME "%d", href);
  12946. return soap_element_href(soap, tag, id, s, soap->href + n);
  12947. }
  12948. /******************************************************************************/
  12949. SOAP_FMAC1
  12950. int
  12951. SOAP_FMAC2
  12952. soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val)
  12953. {
  12954. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val));
  12955. if (soap_element(soap, tag, id, NULL)
  12956. || soap_attribute(soap, ref, val)
  12957. || soap_element_start_end_out(soap, tag))
  12958. return soap->error;
  12959. soap->body = 0;
  12960. return SOAP_OK;
  12961. }
  12962. /******************************************************************************/
  12963. SOAP_FMAC1
  12964. int
  12965. SOAP_FMAC2
  12966. soap_element_null(struct soap *soap, const char *tag, int id, const char *type)
  12967. {
  12968. struct soap_attribute *tp = NULL;
  12969. for (tp = soap->attributes; tp; tp = tp->next)
  12970. if (tp->visible)
  12971. break;
  12972. if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL))
  12973. {
  12974. if (soap_element(soap, tag, id, type)
  12975. || (!tp && soap_attribute(soap, "xsi:nil", "true"))
  12976. || soap_element_start_end_out(soap, tag))
  12977. return soap->error;
  12978. soap->body = 0;
  12979. }
  12980. else
  12981. {
  12982. soap->null = 1;
  12983. soap->position = 0;
  12984. soap->mustUnderstand = 0;
  12985. }
  12986. return SOAP_OK;
  12987. }
  12988. /******************************************************************************/
  12989. SOAP_FMAC1
  12990. int
  12991. SOAP_FMAC2
  12992. soap_element_empty(struct soap *soap, const char *tag)
  12993. {
  12994. if (soap_element(soap, tag, -1, NULL))
  12995. return soap->error;
  12996. return soap_element_start_end_out(soap, tag);
  12997. }
  12998. /******************************************************************************/
  12999. SOAP_FMAC1
  13000. int
  13001. SOAP_FMAC2
  13002. soap_element_nil(struct soap *soap, const char *tag)
  13003. {
  13004. if (soap_element(soap, tag, -1, NULL)
  13005. || (soap_attribute(soap, "xsi:nil", "true")))
  13006. return soap->error;
  13007. return soap_element_start_end_out(soap, tag);
  13008. }
  13009. /******************************************************************************/
  13010. SOAP_FMAC1
  13011. int
  13012. SOAP_FMAC2
  13013. soap_element_id(struct soap *soap, const char *tag, int id, const void *p, const void *a, int n, const char *type, int t, char **mark)
  13014. {
  13015. (void)a; (void)n;
  13016. if (!p)
  13017. {
  13018. soap->error = soap_element_null(soap, tag, id, type);
  13019. return -1;
  13020. }
  13021. #ifndef WITH_NOIDREF
  13022. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element_id %p type=%d id=%d\n", p, t, id));
  13023. if ((!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) || (soap->mode & SOAP_XML_TREE))
  13024. return soap_check_and_mark(soap, p, t, mark);
  13025. if (mark)
  13026. *mark = NULL;
  13027. if (id < -1)
  13028. return soap_embed(soap, p, a, n, t);
  13029. else if (id <= 0)
  13030. {
  13031. struct soap_plist *pp;
  13032. if (a)
  13033. id = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
  13034. else
  13035. id = soap_pointer_lookup(soap, p, t, &pp);
  13036. if (id)
  13037. {
  13038. if (soap_is_embedded(soap, pp))
  13039. {
  13040. soap_element_ref(soap, tag, 0, id);
  13041. return -1;
  13042. }
  13043. if (soap_is_single(soap, pp))
  13044. return 0;
  13045. soap_set_embedded(soap, pp);
  13046. }
  13047. }
  13048. return id;
  13049. #else
  13050. return soap_check_and_mark(soap, p, t, mark);
  13051. #endif
  13052. }
  13053. /******************************************************************************/
  13054. SOAP_FMAC1
  13055. int
  13056. SOAP_FMAC2
  13057. soap_check_and_mark(struct soap *soap, const void *p, int t, char **mark)
  13058. {
  13059. if (mark)
  13060. {
  13061. struct soap_plist *pp;
  13062. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Check %p and mark %p\n", p, (void*)mark));
  13063. if (!soap_pointer_lookup(soap, p, t, &pp))
  13064. if (!soap_pointer_enter(soap, p, NULL, 0, t, &pp))
  13065. return -1;
  13066. if ((soap->mode & SOAP_IO_LENGTH))
  13067. {
  13068. if (pp->mark1 > 0)
  13069. return -1;
  13070. pp->mark1 = 1;
  13071. *mark = &pp->mark1;
  13072. }
  13073. else
  13074. {
  13075. if (pp->mark2 > 0)
  13076. return -1;
  13077. pp->mark2 = 1;
  13078. *mark = &pp->mark2;
  13079. }
  13080. }
  13081. return 0;
  13082. }
  13083. /******************************************************************************/
  13084. SOAP_FMAC1
  13085. void *
  13086. SOAP_FMAC2
  13087. soap_mark_lookup(struct soap *soap, const void *p, int t, struct soap_plist **ppp, char **mark)
  13088. {
  13089. if (!soap)
  13090. return NULL;
  13091. if (mark || !(soap->mode & SOAP_XML_TREE))
  13092. {
  13093. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Mark lookup %p type=%d\n", p, t));
  13094. if (!soap_pointer_lookup(soap, p, t, ppp))
  13095. {
  13096. if (!soap_pointer_enter(soap, p, NULL, 0, t, ppp))
  13097. return NULL;
  13098. }
  13099. else if (!(soap->mode & SOAP_XML_TREE))
  13100. {
  13101. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Mark found %p\n", (*ppp)->dup));
  13102. return (*ppp)->dup;
  13103. }
  13104. if (mark)
  13105. {
  13106. if ((*ppp)->mark1 > 0)
  13107. (*ppp)->mark1 = 2; /* cycle */
  13108. else
  13109. (*ppp)->mark1 = 1; /* cycle detection */
  13110. *mark = &(*ppp)->mark1;
  13111. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Mark cycle %d\n", (*ppp)->mark1));
  13112. }
  13113. }
  13114. return NULL;
  13115. }
  13116. /******************************************************************************/
  13117. SOAP_FMAC1
  13118. int
  13119. SOAP_FMAC2
  13120. soap_mark_cycle(struct soap *soap, struct soap_plist *pp)
  13121. {
  13122. (void)soap;
  13123. return pp && pp->mark1 == 2 && (soap->mode & SOAP_XML_TREE);
  13124. }
  13125. /******************************************************************************/
  13126. SOAP_FMAC1
  13127. void
  13128. SOAP_FMAC2
  13129. soap_mark_dup(struct soap *soap, void *a, struct soap_plist *pp)
  13130. {
  13131. (void)soap;
  13132. if (pp)
  13133. pp->dup = a;
  13134. }
  13135. /******************************************************************************/
  13136. SOAP_FMAC1
  13137. void
  13138. SOAP_FMAC2
  13139. soap_unmark(struct soap *soap, char *mark)
  13140. {
  13141. (void)soap;
  13142. if (mark)
  13143. *mark = 0; /* release detection */
  13144. }
  13145. /******************************************************************************/
  13146. SOAP_FMAC1
  13147. int
  13148. SOAP_FMAC2
  13149. soap_element_result(struct soap *soap, const char *tag)
  13150. {
  13151. if (soap->version == 2 && soap->encodingStyle)
  13152. {
  13153. if (soap_element(soap, "SOAP-RPC:result", 0, NULL)
  13154. || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc)
  13155. || soap_element_start_end_out(soap, NULL)
  13156. || soap_string_out(soap, tag, 0)
  13157. || soap_element_end_out(soap, "SOAP-RPC:result"))
  13158. return soap->error;
  13159. }
  13160. return SOAP_OK;
  13161. }
  13162. /******************************************************************************/
  13163. SOAP_FMAC1
  13164. void
  13165. SOAP_FMAC2
  13166. soap_check_result(struct soap *soap, const char *tag)
  13167. {
  13168. (void)tag;
  13169. if (soap->version == 2 && soap->encodingStyle)
  13170. {
  13171. soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1, NULL);
  13172. /* just ignore content for compliance reasons, but should compare tag to element's QName value? */
  13173. }
  13174. }
  13175. /******************************************************************************/
  13176. SOAP_FMAC1
  13177. int
  13178. SOAP_FMAC2
  13179. soap_attribute(struct soap *soap, const char *name, const char *value)
  13180. {
  13181. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attribute '%s'='%s'\n", name, value));
  13182. #ifdef WITH_DOM
  13183. if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom)
  13184. {
  13185. struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
  13186. if (!a)
  13187. return soap->error;
  13188. a->next = soap->dom->atts;
  13189. a->nstr = NULL;
  13190. a->name = soap_strdup(soap, name);
  13191. a->text = soap_strdup(soap, value);
  13192. a->soap = soap;
  13193. soap->dom->atts = a;
  13194. if (!a->name || (value && !a->text))
  13195. return soap->error = SOAP_EOM;
  13196. return SOAP_OK;
  13197. }
  13198. #endif
  13199. #ifndef WITH_LEAN
  13200. if ((soap->mode & SOAP_XML_CANONICAL))
  13201. {
  13202. /* push namespace */
  13203. if (!strncmp(name, "xmlns", 5) && ((name[5] == ':') || name[5] == '\0'))
  13204. {
  13205. if (name[5] == ':' && soap->c14ninclude && ((*soap->c14ninclude == '*' || soap_tagsearch(soap->c14ninclude, name + 6))))
  13206. soap_utilize_ns(soap, name, 0);
  13207. (void)soap_push_ns(soap, name + 5 + (name[5] == ':'), value, 0, 0);
  13208. }
  13209. else
  13210. {
  13211. soap->level--;
  13212. if (soap_set_attr(soap, name, value, 1))
  13213. return soap->error;
  13214. soap->level++;
  13215. }
  13216. }
  13217. else
  13218. #endif
  13219. {
  13220. if (soap_send_raw(soap, " ", 1)
  13221. || soap_send(soap, name))
  13222. return soap->error;
  13223. if (value)
  13224. if (soap_send_raw(soap, "=\"", 2)
  13225. || soap_string_out(soap, value, 1)
  13226. || soap_send_raw(soap, "\"", 1))
  13227. return soap->error;
  13228. }
  13229. return SOAP_OK;
  13230. }
  13231. /******************************************************************************/
  13232. SOAP_FMAC1
  13233. int
  13234. SOAP_FMAC2
  13235. soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type)
  13236. {
  13237. if (!soap_peek_element(soap))
  13238. {
  13239. if (soap->other)
  13240. return soap->error = SOAP_TAG_MISMATCH;
  13241. if (tag && *tag == '-')
  13242. return SOAP_OK;
  13243. soap->error = soap_match_tag(soap, soap->tag, tag);
  13244. if (!soap->error)
  13245. {
  13246. if (type && *soap->type && soap_match_tag(soap, soap->type, type))
  13247. return soap->error = SOAP_TYPE;
  13248. soap->peeked = 0;
  13249. if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT))
  13250. return soap->error = SOAP_NULL;
  13251. if (soap->body)
  13252. {
  13253. soap->level++;
  13254. if (soap->level > soap->maxlevel)
  13255. return soap->error = SOAP_LEVEL;
  13256. }
  13257. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin tag found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag ? tag : SOAP_STR_EOS));
  13258. soap->error = SOAP_OK;
  13259. }
  13260. }
  13261. else if (soap->error == SOAP_NO_TAG && tag && *tag == '-')
  13262. {
  13263. soap->error = SOAP_OK;
  13264. }
  13265. return soap->error;
  13266. }
  13267. /******************************************************************************/
  13268. SOAP_FMAC1
  13269. int
  13270. SOAP_FMAC2
  13271. soap_element_end_in(struct soap *soap, const char *tag)
  13272. {
  13273. soap_wchar c;
  13274. char *s = NULL;
  13275. int n = 0;
  13276. if (tag && *tag == '-')
  13277. return SOAP_OK;
  13278. if (soap->error == SOAP_NO_TAG)
  13279. soap->error = SOAP_OK;
  13280. #ifdef WITH_DOM
  13281. /* this whitespace or mixed content is significant for DOM "as-is" */
  13282. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  13283. {
  13284. const char *t = soap->dom->code; /* save XML code */
  13285. s = soap_string_in(soap, -1, -1, -1, NULL);
  13286. if (!soap->peeked && !s)
  13287. return soap->error;
  13288. if (soap->dom->prnt)
  13289. soap->dom = soap->dom->prnt;
  13290. if (s && (soap->mode & SOAP_XML_STRICT))
  13291. {
  13292. for (; *s; s++)
  13293. if (!soap_coblank((soap_wchar)*s))
  13294. return soap->error = SOAP_END_TAG; /* reject mixed content before ending tag */
  13295. }
  13296. soap->dom->code = t; /* restore XML code */
  13297. }
  13298. #endif
  13299. if (soap->peeked)
  13300. {
  13301. if (*soap->tag)
  13302. n++;
  13303. soap->peeked = 0;
  13304. }
  13305. do
  13306. {
  13307. while (((c = soap_get(soap)) != SOAP_TT))
  13308. {
  13309. if ((int)c == EOF)
  13310. return soap->error = SOAP_CHK_EOF;
  13311. if (!soap_coblank(c))
  13312. {
  13313. if ((soap->mode & SOAP_XML_STRICT))
  13314. return soap->error = SOAP_END_TAG; /* reject mixed content before ending tag */
  13315. if (c == SOAP_LT)
  13316. n++;
  13317. else if (c == '/')
  13318. {
  13319. c = soap_get(soap);
  13320. if (c == SOAP_GT && n > 0)
  13321. n--;
  13322. else
  13323. soap_unget(soap, c);
  13324. }
  13325. }
  13326. }
  13327. } while (n-- > 0);
  13328. s = soap->tag;
  13329. n = sizeof(soap->tag);
  13330. while ((c = soap_get(soap)) > 32)
  13331. {
  13332. if (n > 1)
  13333. {
  13334. *s++ = (char)c;
  13335. n--;
  13336. }
  13337. }
  13338. *s = '\0';
  13339. if ((int)c == EOF)
  13340. return soap->error = SOAP_CHK_EOF;
  13341. while (soap_coblank(c))
  13342. c = soap_get(soap);
  13343. if (c != SOAP_GT)
  13344. return soap->error = SOAP_SYNTAX_ERROR;
  13345. #ifndef WITH_LEAN
  13346. #ifdef WITH_DOM
  13347. if (soap->feltendin)
  13348. {
  13349. int err = soap->error;
  13350. soap->error = soap->feltendin(soap, soap->tag, tag);
  13351. if (soap->error)
  13352. return soap->error;
  13353. if (err)
  13354. return soap->error = err; /* restore error */
  13355. }
  13356. #endif
  13357. #endif
  13358. if (tag && (soap->mode & SOAP_XML_STRICT))
  13359. {
  13360. soap_pop_namespace(soap);
  13361. if (soap_match_tag(soap, soap->tag, tag))
  13362. {
  13363. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End tag '%s' does not match '%s'\n", soap->tag, tag ? tag : SOAP_STR_EOS));
  13364. return soap->error = SOAP_SYNTAX_ERROR;
  13365. }
  13366. }
  13367. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End tag found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag ? tag : SOAP_STR_EOS));
  13368. soap->level--;
  13369. return SOAP_OK;
  13370. }
  13371. /******************************************************************************/
  13372. SOAP_FMAC1
  13373. const char *
  13374. SOAP_FMAC2
  13375. soap_attr_value(struct soap *soap, const char *name, int flag, int occurs)
  13376. {
  13377. struct soap_attribute *tp;
  13378. if (*name == '-')
  13379. return SOAP_STR_EOS;
  13380. for (tp = soap->attributes; tp; tp = tp->next)
  13381. {
  13382. if (tp->visible == 2 && !soap_match_att(soap, tp->name, name))
  13383. break;
  13384. }
  13385. if (tp)
  13386. {
  13387. if (occurs == 4 || (occurs == 2 && (soap->mode & SOAP_XML_STRICT)))
  13388. soap->error = SOAP_PROHIBITED;
  13389. else if (flag >= 4)
  13390. return soap_collapse(soap, tp->value, flag, 1);
  13391. else
  13392. return tp->value;
  13393. }
  13394. else if (occurs == 3 || (occurs == 1 && (soap->mode & SOAP_XML_STRICT)))
  13395. {
  13396. soap->error = SOAP_REQUIRED;
  13397. }
  13398. else
  13399. {
  13400. soap->error = SOAP_OK;
  13401. }
  13402. return NULL;
  13403. }
  13404. /******************************************************************************/
  13405. SOAP_FMAC1
  13406. int
  13407. SOAP_FMAC2
  13408. soap_set_attr(struct soap *soap, const char *name, const char *value, int flag)
  13409. {
  13410. struct soap_attribute *tp, *tq;
  13411. if (*name == '-')
  13412. return SOAP_OK;
  13413. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value ? value : SOAP_STR_EOS));
  13414. tq = NULL;
  13415. for (tp = soap->attributes; tp; tq = tp, tp = tp->next)
  13416. {
  13417. if (!strcmp(tp->name, name))
  13418. break;
  13419. }
  13420. if (!tp)
  13421. {
  13422. size_t l = strlen(name);
  13423. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name));
  13424. if (sizeof(struct soap_attribute) + l > l && (SOAP_MAXALLOCSIZE <= 0 || sizeof(struct soap_attribute) + l <= SOAP_MAXALLOCSIZE))
  13425. tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + l);
  13426. if (!tp)
  13427. return soap->error = SOAP_EOM;
  13428. tp->ns = NULL;
  13429. #ifndef WITH_LEAN
  13430. if ((soap->mode & SOAP_XML_CANONICAL))
  13431. {
  13432. struct soap_attribute **tpp = &soap->attributes;
  13433. const char *s = strchr(name, ':');
  13434. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name));
  13435. if (!strncmp(name, "xmlns", 5))
  13436. {
  13437. for (; *tpp; tpp = &(*tpp)->next)
  13438. if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0)
  13439. break;
  13440. }
  13441. else if (!s)
  13442. {
  13443. for (; *tpp; tpp = &(*tpp)->next)
  13444. if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0))
  13445. break;
  13446. }
  13447. else
  13448. {
  13449. struct soap_nlist *np = soap_lookup_ns(soap, name, s - name);
  13450. if (np)
  13451. {
  13452. tp->ns = np->ns;
  13453. }
  13454. else
  13455. {
  13456. struct soap_attribute *tq;
  13457. for (tq = soap->attributes; tq; tq = tq->next)
  13458. {
  13459. if (!strncmp(tq->name, "xmlns:", 6) && !strncmp(tq->name + 6, name, s - name) && !tq->name[6 + s - name])
  13460. {
  13461. tp->ns = tq->ns;
  13462. break;
  13463. }
  13464. }
  13465. }
  13466. for (; *tpp; tpp = &(*tpp)->next)
  13467. {
  13468. int k;
  13469. if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0)))
  13470. break;
  13471. }
  13472. }
  13473. tp->next = *tpp;
  13474. *tpp = tp;
  13475. }
  13476. else
  13477. #endif
  13478. if (tq)
  13479. {
  13480. tq->next = tp;
  13481. tp->next = NULL;
  13482. }
  13483. else
  13484. {
  13485. tp->next = soap->attributes;
  13486. soap->attributes = tp;
  13487. }
  13488. soap_strcpy((char*)tp->name, l + 1, name);
  13489. tp->value = NULL;
  13490. }
  13491. else if (tp->visible)
  13492. {
  13493. return SOAP_OK;
  13494. }
  13495. else if (value && tp->value && tp->size <= strlen(value))
  13496. {
  13497. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, (void*)tp->value));
  13498. SOAP_FREE(soap, tp->value);
  13499. tp->value = NULL;
  13500. tp->ns = NULL;
  13501. }
  13502. if (value)
  13503. {
  13504. if (!tp->value)
  13505. {
  13506. tp->size = strlen(value) + 1;
  13507. if (SOAP_MAXALLOCSIZE <= 0 || tp->size <= SOAP_MAXALLOCSIZE)
  13508. tp->value = (char*)SOAP_MALLOC(soap, tp->size);
  13509. if (!tp->value)
  13510. return soap->error = SOAP_EOM;
  13511. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value for %s (%p)\n", tp->name, (void*)tp->value));
  13512. }
  13513. soap_strcpy(tp->value, tp->size, value);
  13514. if (!strncmp(tp->name, "xmlns:", 6))
  13515. tp->ns = tp->value;
  13516. tp->visible = 2;
  13517. tp->flag = (short)flag;
  13518. #ifndef WITH_LEAN
  13519. if (!strcmp(name, "wsu:Id"))
  13520. {
  13521. soap->event = SOAP_SEC_BEGIN;
  13522. soap_strcpy(soap->id, sizeof(soap->id), value);
  13523. }
  13524. if ((soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_XML_CANONICAL_NA))
  13525. {
  13526. const char *s = strchr(name, ':');
  13527. if (s && strchr(value, ':'))
  13528. {
  13529. struct soap_nlist *np = soap_lookup_ns(soap, name, s - name);
  13530. if (np && np->ns && soap->local_namespaces)
  13531. {
  13532. if ((!strcmp(s + 1, "type") && !strcmp(np->ns, soap->local_namespaces[2].ns)) /* xsi:type QName */
  13533. || ((!strcmp(s + 1, "arrayType") || !strcmp(s + 1, "itemType")) && !strcmp(np->ns, soap->local_namespaces[1].ns))) /* SOAP-ENC:arrayType and SOAP-ENC:itemType QName */
  13534. soap_utilize_ns(soap, value, 1);
  13535. }
  13536. }
  13537. }
  13538. #endif
  13539. }
  13540. else
  13541. {
  13542. tp->visible = 1;
  13543. }
  13544. return SOAP_OK;
  13545. }
  13546. /******************************************************************************/
  13547. SOAP_FMAC1
  13548. void
  13549. SOAP_FMAC2
  13550. soap_clr_attr(struct soap *soap)
  13551. {
  13552. struct soap_attribute *tp;
  13553. #ifndef WITH_LEAN
  13554. if ((soap->mode & SOAP_XML_CANONICAL))
  13555. {
  13556. while (soap->attributes)
  13557. {
  13558. tp = soap->attributes->next;
  13559. if (soap->attributes->value)
  13560. SOAP_FREE(soap, soap->attributes->value);
  13561. SOAP_FREE(soap, soap->attributes);
  13562. soap->attributes = tp;
  13563. }
  13564. }
  13565. else
  13566. #endif
  13567. {
  13568. for (tp = soap->attributes; tp; tp = tp->next)
  13569. tp->visible = 0;
  13570. }
  13571. }
  13572. /******************************************************************************/
  13573. static int
  13574. soap_getattrval(struct soap *soap, char *s, size_t *n, soap_wchar d)
  13575. {
  13576. char buf[8];
  13577. size_t i;
  13578. size_t k = *n;
  13579. size_t m = 0;
  13580. char *t = buf;
  13581. for (i = 0; i < k; i++)
  13582. {
  13583. soap_wchar c;
  13584. if (m)
  13585. {
  13586. *s++ = *t++;
  13587. m--;
  13588. continue;
  13589. }
  13590. if ((soap->mode & SOAP_C_UTFSTRING))
  13591. {
  13592. c = soap_get(soap);
  13593. if ((c & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP)
  13594. {
  13595. t = buf;
  13596. c &= 0x7FFFFFFF;
  13597. if (c < 0x0800)
  13598. *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
  13599. else
  13600. {
  13601. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  13602. if (!((c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF)))
  13603. c = SOAP_UNKNOWN_UNICODE_CHAR;
  13604. #endif
  13605. if (c < 0x010000)
  13606. {
  13607. *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
  13608. }
  13609. else
  13610. {
  13611. if (c < 0x200000)
  13612. {
  13613. *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
  13614. }
  13615. else
  13616. {
  13617. if (c < 0x04000000)
  13618. {
  13619. *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
  13620. }
  13621. else
  13622. {
  13623. *t++ = (char)(0xFC | ((c >> 30) & 0x01));
  13624. *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
  13625. }
  13626. *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
  13627. }
  13628. *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
  13629. }
  13630. *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
  13631. }
  13632. *t++ = (char)(0x80 | (c & 0x3F));
  13633. m = t - buf - 1;
  13634. if (i + m >= k)
  13635. {
  13636. soap_unget(soap, c | 0x80000000);
  13637. *n = i;
  13638. return soap->error = SOAP_EOM;
  13639. }
  13640. t = buf;
  13641. *s++ = *t++;
  13642. continue;
  13643. }
  13644. }
  13645. else
  13646. {
  13647. c = soap_getutf8(soap);
  13648. }
  13649. switch (c)
  13650. {
  13651. case SOAP_TT:
  13652. *s++ = '<';
  13653. soap_unget(soap, '/');
  13654. break;
  13655. case SOAP_LT:
  13656. *s++ = '<';
  13657. break;
  13658. case SOAP_GT:
  13659. if (d == ' ')
  13660. {
  13661. soap_unget(soap, c);
  13662. *s = '\0';
  13663. *n = i + 1;
  13664. return SOAP_OK;
  13665. }
  13666. *s++ = '>';
  13667. break;
  13668. case SOAP_QT:
  13669. if (c == d)
  13670. {
  13671. *s = '\0';
  13672. *n = i + 1;
  13673. return SOAP_OK;
  13674. }
  13675. *s++ = '"';
  13676. break;
  13677. case SOAP_AP:
  13678. if (c == d)
  13679. {
  13680. *s = '\0';
  13681. *n = i + 1;
  13682. return SOAP_OK;
  13683. }
  13684. *s++ = '\'';
  13685. break;
  13686. case '\t':
  13687. case '\n':
  13688. case '\r':
  13689. case ' ':
  13690. case '/':
  13691. if (d == ' ')
  13692. {
  13693. soap_unget(soap, c);
  13694. *s = '\0';
  13695. *n = i + 1;
  13696. return SOAP_OK;
  13697. }
  13698. *s++ = (char)c;
  13699. break;
  13700. default:
  13701. if ((int)c == EOF)
  13702. {
  13703. *s = '\0';
  13704. *n = i + 1;
  13705. return soap->error = SOAP_CHK_EOF;
  13706. }
  13707. *s++ = (char)c;
  13708. }
  13709. }
  13710. return soap->error = SOAP_EOM;
  13711. }
  13712. /******************************************************************************/
  13713. #ifdef WITH_FAST
  13714. SOAP_FMAC1
  13715. int
  13716. SOAP_FMAC2
  13717. soap_store_lab(struct soap *soap, const char *s, size_t n)
  13718. {
  13719. soap->labidx = 0;
  13720. return soap_append_lab(soap, s, n);
  13721. }
  13722. #endif
  13723. /******************************************************************************/
  13724. #ifdef WITH_FAST
  13725. SOAP_FMAC1
  13726. int
  13727. SOAP_FMAC2
  13728. soap_append_lab(struct soap *soap, const char *s, size_t n)
  13729. {
  13730. if (soap->labidx + n < soap->labidx)
  13731. return soap->error = SOAP_EOM;
  13732. if (soap->labidx + n >= soap->lablen)
  13733. {
  13734. char *t = soap->labbuf;
  13735. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, size=%lu\n", (unsigned long)soap->lablen));
  13736. if (soap->lablen == 0)
  13737. soap->lablen = SOAP_LABLEN;
  13738. while (soap->labidx + n >= soap->lablen)
  13739. {
  13740. if (soap->lablen << 1 < soap->lablen)
  13741. return soap->error = SOAP_EOM;
  13742. soap->lablen <<= 1;
  13743. }
  13744. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New look-aside buffer size=%lu\n", (unsigned long)soap->lablen));
  13745. if (SOAP_MAXALLOCSIZE > 0 && soap->lablen > SOAP_MAXALLOCSIZE)
  13746. return soap->error = SOAP_EOM;
  13747. soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen);
  13748. if (!soap->labbuf)
  13749. {
  13750. if (t)
  13751. SOAP_FREE(soap, t);
  13752. return soap->error = SOAP_EOM;
  13753. }
  13754. if (t)
  13755. {
  13756. (void)soap_memcpy((void*)soap->labbuf, soap->lablen, (const void*)t, soap->labidx);
  13757. SOAP_FREE(soap, t);
  13758. }
  13759. }
  13760. if (s)
  13761. {
  13762. (void)soap_memcpy((void*)(soap->labbuf + soap->labidx), soap->lablen - soap->labidx, (const void*)s, n);
  13763. soap->labidx += n;
  13764. }
  13765. return SOAP_OK;
  13766. }
  13767. #endif
  13768. /******************************************************************************/
  13769. SOAP_FMAC1
  13770. int
  13771. SOAP_FMAC2
  13772. soap_peek_element(struct soap *soap)
  13773. {
  13774. #ifdef WITH_DOM
  13775. struct soap_dom_attribute **att = NULL;
  13776. char *lead = NULL;
  13777. #endif
  13778. struct soap_attribute *tp, *tq = NULL;
  13779. const char *t;
  13780. char *s;
  13781. soap_wchar c;
  13782. int i;
  13783. if (soap->peeked)
  13784. {
  13785. if (!*soap->tag)
  13786. return soap->error = SOAP_NO_TAG;
  13787. return SOAP_OK;
  13788. }
  13789. soap->peeked = 1;
  13790. soap->id[0] = '\0';
  13791. soap->href[0] = '\0';
  13792. soap->type[0] = '\0';
  13793. soap->arrayType[0] = '\0';
  13794. soap->arraySize[0] = '\0';
  13795. soap->arrayOffset[0] = '\0';
  13796. soap->other = 0;
  13797. soap->root = -1;
  13798. soap->position = 0;
  13799. soap->null = 0;
  13800. soap->mustUnderstand = 0;
  13801. /* UTF-8 BOM? */
  13802. c = soap_getchar(soap);
  13803. if (c == 0xEF && soap_get0(soap) == 0xBB)
  13804. {
  13805. soap_get1(soap);
  13806. c = soap_get1(soap);
  13807. if (c == 0xBF)
  13808. soap->mode &= ~SOAP_ENC_LATIN;
  13809. else
  13810. soap_unget(soap, (0x0F << 12) | (0xBB << 6) | (c & 0x3F)); /* UTF-8 */
  13811. }
  13812. else if ((c == 0xFE && soap_get0(soap) == 0xFF) /* UTF-16 BE */
  13813. || (c == 0xFF && soap_get0(soap) == 0xFE)) /* UTF-16 LE */
  13814. {
  13815. return soap->error = SOAP_UTF_ERROR;
  13816. }
  13817. else
  13818. {
  13819. soap_unget(soap, c);
  13820. }
  13821. c = soap_get(soap);
  13822. #ifdef WITH_DOM
  13823. /* whitespace leading up to the start tag is significant for DOM as-is (but comments and PIs are removed from this lead) */
  13824. if (soap_coblank(c))
  13825. {
  13826. soap->labidx = 0;
  13827. do
  13828. {
  13829. if (soap_append_lab(soap, NULL, 0))
  13830. return soap->error;
  13831. s = soap->labbuf + soap->labidx;
  13832. i = soap->lablen - soap->labidx;
  13833. soap->labidx = soap->lablen;
  13834. while (soap_coblank(c) && i-- > 0)
  13835. {
  13836. *s++ = c;
  13837. c = soap_get(soap);
  13838. }
  13839. } while (soap_coblank(c) || i == 0);
  13840. *s = '\0';
  13841. lead = soap->labbuf;
  13842. }
  13843. #else
  13844. /* skip space */
  13845. while (soap_coblank(c))
  13846. c = soap_get(soap);
  13847. #endif
  13848. if (c != SOAP_LT)
  13849. {
  13850. *soap->tag = '\0';
  13851. if ((int)c == EOF)
  13852. return soap->error = SOAP_CHK_EOF;
  13853. soap_unget(soap, c);
  13854. #ifdef WITH_DOM
  13855. /* whitespace leading up to the end tag is significant for DOM as-is */
  13856. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  13857. {
  13858. if (lead && *lead)
  13859. soap->dom->tail = soap_strdup(soap, lead);
  13860. else
  13861. soap->dom->tail = SOAP_STR_EOS; /* body with closing tag instead of <tag/> */
  13862. }
  13863. #endif
  13864. return soap->error = SOAP_NO_TAG;
  13865. }
  13866. do
  13867. {
  13868. c = soap_get1(soap);
  13869. } while (soap_coblank(c));
  13870. s = soap->tag;
  13871. i = sizeof(soap->tag);
  13872. while (c != '>' && c != '/' && c > 32 && (int)c != EOF)
  13873. {
  13874. if (i > 1)
  13875. {
  13876. *s++ = (char)c;
  13877. i--;
  13878. }
  13879. c = soap_get1(soap);
  13880. }
  13881. *s = '\0';
  13882. while (soap_coblank(c))
  13883. c = soap_get1(soap);
  13884. #ifdef WITH_DOM
  13885. if ((soap->mode & SOAP_XML_DOM))
  13886. {
  13887. struct soap_dom_element *elt;
  13888. elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
  13889. if (!elt)
  13890. return soap->error;
  13891. elt->next = NULL;
  13892. elt->prnt = soap->dom;
  13893. elt->elts = NULL;
  13894. elt->atts = NULL;
  13895. elt->nstr = NULL;
  13896. elt->name = soap_strdup(soap, soap->tag);
  13897. elt->text = NULL;
  13898. elt->code = NULL;
  13899. elt->tail = NULL;
  13900. elt->node = NULL;
  13901. elt->type = 0;
  13902. if (lead && *lead)
  13903. elt->lead = soap_strdup(soap, lead);
  13904. else
  13905. elt->lead = NULL;
  13906. elt->soap = soap;
  13907. if (soap->dom)
  13908. {
  13909. struct soap_dom_element *p = soap->dom->elts;
  13910. if (p)
  13911. {
  13912. while (p->next)
  13913. p = p->next;
  13914. p->next = elt;
  13915. }
  13916. else
  13917. {
  13918. soap->dom->elts = elt;
  13919. }
  13920. }
  13921. soap->dom = elt;
  13922. att = &elt->atts;
  13923. if (!elt->name)
  13924. return soap->error = SOAP_EOM;
  13925. }
  13926. #endif
  13927. soap_pop_namespace(soap);
  13928. for (tp = soap->attributes; tp; tp = tp->next)
  13929. tp->visible = 0;
  13930. while ((int)c != EOF && c != '>' && c != '/')
  13931. {
  13932. s = soap->tmpbuf;
  13933. i = sizeof(soap->tmpbuf);
  13934. while (c != '=' && c != '>' && c != '/' && c > 32 && (int)c != EOF)
  13935. {
  13936. if (i > 1)
  13937. {
  13938. *s++ = (char)c;
  13939. i--;
  13940. }
  13941. c = soap_get1(soap);
  13942. }
  13943. *s = '\0';
  13944. if (i == sizeof(soap->tmpbuf))
  13945. return soap->error = SOAP_SYNTAX_ERROR;
  13946. #ifdef WITH_DOM
  13947. /* add attribute name to dom */
  13948. if (att)
  13949. {
  13950. *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
  13951. if (!*att)
  13952. return soap->error;
  13953. (*att)->next = NULL;
  13954. (*att)->nstr = NULL;
  13955. (*att)->name = soap_strdup(soap, soap->tmpbuf);
  13956. (*att)->text = NULL;
  13957. (*att)->soap = soap;
  13958. if (!(*att)->name)
  13959. return soap->error = SOAP_EOM;
  13960. }
  13961. #endif
  13962. if (!strncmp(soap->tmpbuf, "xmlns", 5))
  13963. {
  13964. if (soap->tmpbuf[5] == ':')
  13965. t = soap->tmpbuf + 6;
  13966. else if (soap->tmpbuf[5])
  13967. t = NULL;
  13968. else
  13969. t = SOAP_STR_EOS;
  13970. }
  13971. else
  13972. {
  13973. t = NULL;
  13974. }
  13975. tq = NULL;
  13976. for (tp = soap->attributes; tp; tq = tp, tp = tp->next)
  13977. {
  13978. if (!SOAP_STRCMP(tp->name, soap->tmpbuf))
  13979. break;
  13980. }
  13981. if (!tp)
  13982. {
  13983. size_t l = strlen(soap->tmpbuf);
  13984. tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + l);
  13985. if (!tp)
  13986. return soap->error = SOAP_EOM;
  13987. (void)soap_memcpy((char*)tp->name, l + 1, soap->tmpbuf, l + 1);
  13988. tp->value = NULL;
  13989. tp->size = 0;
  13990. tp->ns = NULL;
  13991. tp->visible = 0;
  13992. /* append attribute to the end of the list */
  13993. if (tq)
  13994. {
  13995. tq->next = tp;
  13996. tp->next = NULL;
  13997. }
  13998. else
  13999. {
  14000. tp->next = soap->attributes;
  14001. soap->attributes = tp;
  14002. }
  14003. }
  14004. while (soap_coblank(c))
  14005. c = soap_get1(soap);
  14006. if (c == '=')
  14007. {
  14008. size_t k;
  14009. do
  14010. {
  14011. c = soap_getutf8(soap);
  14012. } while (soap_coblank(c));
  14013. if (c != SOAP_QT && c != SOAP_AP)
  14014. {
  14015. soap_unget(soap, c);
  14016. c = ' '; /* blank delimiter */
  14017. }
  14018. k = tp->size;
  14019. if (soap_getattrval(soap, tp->value, &k, c))
  14020. {
  14021. #ifdef WITH_FAST
  14022. if (soap->error != SOAP_EOM)
  14023. return soap->error;
  14024. soap->error = SOAP_OK;
  14025. if (soap_store_lab(soap, tp->value, k))
  14026. return soap->error;
  14027. if (tp->value)
  14028. SOAP_FREE(soap, tp->value);
  14029. tp->value = NULL;
  14030. for (;;)
  14031. {
  14032. k = soap->lablen - soap->labidx;
  14033. if (soap_getattrval(soap, soap->labbuf + soap->labidx, &k, c))
  14034. {
  14035. if (soap->error != SOAP_EOM)
  14036. return soap->error;
  14037. soap->error = SOAP_OK;
  14038. soap->labidx = soap->lablen;
  14039. if (soap_append_lab(soap, NULL, 0))
  14040. return soap->error;
  14041. }
  14042. else
  14043. {
  14044. break;
  14045. }
  14046. }
  14047. if (soap->labidx)
  14048. {
  14049. tp->size = soap->lablen;
  14050. }
  14051. else
  14052. {
  14053. tp->size = strlen(soap->labbuf) + 1;
  14054. if (tp->size < SOAP_LABLEN)
  14055. tp->size = SOAP_LABLEN;
  14056. }
  14057. tp->value = (char*)SOAP_MALLOC(soap, tp->size);
  14058. if (!tp->value)
  14059. return soap->error = SOAP_EOM;
  14060. soap_strcpy(tp->value, tp->size, soap->labbuf);
  14061. #else
  14062. tp->size = k;
  14063. if (soap->error != SOAP_EOM)
  14064. return soap->error;
  14065. soap->error = SOAP_OK;
  14066. if (soap_alloc_block(soap) == NULL)
  14067. return soap->error;
  14068. for (;;)
  14069. {
  14070. s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN);
  14071. if (!s)
  14072. return soap->error;
  14073. k = SOAP_BLKLEN;
  14074. if (soap_getattrval(soap, s, &k, c))
  14075. {
  14076. if (soap->error != SOAP_EOM)
  14077. return soap->error;
  14078. soap->error = SOAP_OK;
  14079. soap_size_block(soap, NULL, k);
  14080. }
  14081. else
  14082. {
  14083. break;
  14084. }
  14085. }
  14086. k = tp->size + soap->blist->size;
  14087. if (SOAP_MAXALLOCSIZE > 0 && k > SOAP_MAXALLOCSIZE)
  14088. return soap->error = SOAP_EOM;
  14089. s = (char*)SOAP_MALLOC(soap, k);
  14090. if (!s)
  14091. return soap->error = SOAP_EOM;
  14092. if (tp->value)
  14093. {
  14094. (void)soap_memcpy((void*)s, k, (const void*)tp->value, tp->size);
  14095. SOAP_FREE(soap, tp->value);
  14096. }
  14097. soap_save_block(soap, NULL, s + tp->size, 0);
  14098. tp->value = s;
  14099. tp->size = k;
  14100. #endif
  14101. }
  14102. if (tp->visible)
  14103. {
  14104. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Duplicate attribute in %s\n", soap->tag));
  14105. return soap->error = SOAP_SYNTAX_ERROR; /* redefined (duplicate) attribute */
  14106. }
  14107. tp->visible = 2; /* seen this attribute w/ value */
  14108. do
  14109. {
  14110. c = soap_get1(soap);
  14111. } while (soap_coblank(c));
  14112. #ifdef WITH_DOM
  14113. if (att && tp->value)
  14114. {
  14115. (*att)->text = soap_strdup(soap, tp->value);
  14116. if (!(*att)->text)
  14117. return soap->error = SOAP_EOM;
  14118. }
  14119. #endif
  14120. }
  14121. else
  14122. {
  14123. tp->visible = 1; /* seen this attribute w/o value */
  14124. }
  14125. #ifdef WITH_DOM
  14126. if (att)
  14127. att = &(*att)->next;
  14128. #endif
  14129. if (t && tp->value)
  14130. {
  14131. if (soap_push_namespace(soap, t, tp->value) == NULL)
  14132. return soap->error;
  14133. }
  14134. }
  14135. #ifdef WITH_DOM
  14136. if (att)
  14137. {
  14138. soap->dom->nstr = soap_current_namespace_tag(soap, soap->tag);
  14139. for (att = &soap->dom->atts; *att; att = &(*att)->next)
  14140. (*att)->nstr = soap_current_namespace_att(soap, (*att)->name);
  14141. }
  14142. #endif
  14143. if ((int)c == EOF)
  14144. return soap->error = SOAP_CHK_EOF;
  14145. soap->body = (c != '/');
  14146. if (!soap->body)
  14147. {
  14148. do
  14149. {
  14150. c = soap_get1(soap);
  14151. } while (soap_coblank(c));
  14152. }
  14153. #ifdef WITH_DOM
  14154. if ((soap->mode & SOAP_XML_DOM))
  14155. {
  14156. if (!soap->body && soap->dom->prnt)
  14157. soap->dom = soap->dom->prnt;
  14158. }
  14159. #endif
  14160. for (tp = soap->attributes; tp; tp = tp->next)
  14161. {
  14162. if (tp->visible && tp->value)
  14163. {
  14164. #ifndef WITH_NOIDREF
  14165. if (!strcmp(tp->name, "id"))
  14166. {
  14167. if ((soap->version > 0 && !(soap->imode & SOAP_XML_TREE))
  14168. || (soap->mode & SOAP_XML_GRAPH))
  14169. {
  14170. *soap->id = '#';
  14171. soap_strcpy(soap->id + 1, sizeof(soap->id) - 1, tp->value);
  14172. }
  14173. }
  14174. else if (!strcmp(tp->name, "href"))
  14175. {
  14176. if ((soap->version == 1 && !(soap->imode & SOAP_XML_TREE))
  14177. || (soap->mode & SOAP_XML_GRAPH)
  14178. || ((soap->mode & (SOAP_ENC_MTOM | SOAP_ENC_DIME)) && *tp->value != '#'))
  14179. soap_strcpy(soap->href, sizeof(soap->href), tp->value);
  14180. }
  14181. else if (!strcmp(tp->name, "ref"))
  14182. {
  14183. if ((soap->version == 2 && !(soap->imode & SOAP_XML_TREE))
  14184. || (soap->mode & SOAP_XML_GRAPH))
  14185. {
  14186. *soap->href = '#';
  14187. soap_strcpy(soap->href + (*tp->value != '#'), sizeof(soap->href) - 1, tp->value);
  14188. }
  14189. }
  14190. #else
  14191. if (!strcmp(tp->name, "href"))
  14192. {
  14193. if ((soap->mode & (SOAP_ENC_MTOM | SOAP_ENC_DIME)) && *tp->value != '#')
  14194. soap_strcpy(soap->href, sizeof(soap->href), tp->value);
  14195. }
  14196. #endif
  14197. else if (!soap_match_tag(soap, tp->name, "xsi:type"))
  14198. {
  14199. soap_strcpy(soap->type, sizeof(soap->type), tp->value);
  14200. }
  14201. else if ((!soap_match_tag(soap, tp->name, "xsi:null")
  14202. || !soap_match_tag(soap, tp->name, "xsi:nil"))
  14203. && (!strcmp(tp->value, "1")
  14204. || !strcmp(tp->value, "true")))
  14205. {
  14206. soap->null = 1;
  14207. }
  14208. else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:encodingStyle"))
  14209. {
  14210. if (!soap->encodingStyle)
  14211. soap->encodingStyle = SOAP_STR_EOS;
  14212. soap_version(soap);
  14213. }
  14214. else if (soap->version == 1)
  14215. {
  14216. if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType"))
  14217. {
  14218. s = soap_strrchr(tp->value, '[');
  14219. if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType))
  14220. {
  14221. (void)soap_strncpy(soap->arrayType, sizeof(soap->arrayType), tp->value, s - tp->value);
  14222. soap_strcpy(soap->arraySize, sizeof(soap->arraySize), s);
  14223. }
  14224. else
  14225. soap_strcpy(soap->arrayType, sizeof(soap->arrayType), tp->value);
  14226. }
  14227. else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:offset"))
  14228. {
  14229. soap_strcpy(soap->arrayOffset, sizeof(soap->arrayOffset), tp->value);
  14230. }
  14231. else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:position"))
  14232. {
  14233. soap->position = soap_getposition(tp->value, soap->positions);
  14234. }
  14235. else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:root"))
  14236. {
  14237. soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true")));
  14238. }
  14239. else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
  14240. && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
  14241. {
  14242. soap->mustUnderstand = 1;
  14243. }
  14244. else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor"))
  14245. {
  14246. if ((!soap->actor || strcmp(soap->actor, tp->value))
  14247. && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next"))
  14248. soap->other = 1;
  14249. }
  14250. }
  14251. else if (soap->version == 2)
  14252. {
  14253. #ifndef WITH_NOIDREF
  14254. if (!soap_match_tag(soap, tp->name, "SOAP-ENC:id"))
  14255. {
  14256. *soap->id = '#';
  14257. soap_strcpy(soap->id + 1, sizeof(soap->id) - 1, tp->value);
  14258. }
  14259. else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:ref"))
  14260. {
  14261. *soap->href = '#';
  14262. soap_strcpy(soap->href + (*tp->value != '#'), sizeof(soap->href) - 1, tp->value);
  14263. }
  14264. else
  14265. #endif
  14266. if (!soap_match_tag(soap, tp->name, "SOAP-ENC:itemType"))
  14267. {
  14268. soap_strcpy(soap->arrayType, sizeof(soap->arrayType), tp->value);
  14269. }
  14270. else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize"))
  14271. {
  14272. soap_strcpy(soap->arraySize, sizeof(soap->arraySize), tp->value);
  14273. }
  14274. else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
  14275. && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
  14276. {
  14277. soap->mustUnderstand = 1;
  14278. }
  14279. else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:role"))
  14280. {
  14281. if ((!soap->actor || strcmp(soap->actor, tp->value))
  14282. && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next"))
  14283. soap->other = 1;
  14284. }
  14285. }
  14286. else
  14287. {
  14288. if (!soap_match_tag(soap, tp->name, "wsdl:required") && !strcmp(tp->value, "true"))
  14289. soap->mustUnderstand = 1;
  14290. }
  14291. }
  14292. }
  14293. #ifdef WITH_DOM
  14294. if (soap->feltbegin)
  14295. return soap->error = soap->feltbegin(soap, soap->tag);
  14296. #endif
  14297. return soap->error = SOAP_OK;
  14298. }
  14299. /******************************************************************************/
  14300. SOAP_FMAC1
  14301. void
  14302. SOAP_FMAC2
  14303. soap_retry(struct soap *soap)
  14304. {
  14305. soap->error = SOAP_OK;
  14306. soap_revert(soap);
  14307. }
  14308. /******************************************************************************/
  14309. SOAP_FMAC1
  14310. void
  14311. SOAP_FMAC2
  14312. soap_revert(struct soap *soap)
  14313. {
  14314. if (!soap->peeked)
  14315. {
  14316. soap->peeked = 1;
  14317. if (soap->body)
  14318. soap->level--;
  14319. }
  14320. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting to last element '%s' (level=%u)\n", soap->tag, soap->level));
  14321. }
  14322. /******************************************************************************/
  14323. SOAP_FMAC1
  14324. int
  14325. SOAP_FMAC2
  14326. soap_ignore(struct soap *soap)
  14327. {
  14328. int n = 0;
  14329. soap_wchar c;
  14330. soap->level++;
  14331. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Ignoring XML content at level=%u\n", soap->level));
  14332. #ifdef WITH_DOM
  14333. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  14334. {
  14335. if (!soap_string_in(soap, -1, -1, -1, NULL))
  14336. return soap->error;
  14337. }
  14338. else
  14339. #endif
  14340. {
  14341. for (;;)
  14342. {
  14343. c = soap_get(soap);
  14344. switch (c)
  14345. {
  14346. case SOAP_TT:
  14347. if (n == 0)
  14348. goto end;
  14349. n--;
  14350. break;
  14351. case SOAP_LT:
  14352. n++;
  14353. break;
  14354. case '/':
  14355. if (n > 0)
  14356. {
  14357. c = soap_get0(soap);
  14358. if (c == '>')
  14359. n--;
  14360. }
  14361. break;
  14362. default:
  14363. if ((int)c == EOF)
  14364. return soap->error = SOAP_EOF;
  14365. }
  14366. }
  14367. end:
  14368. soap_unget(soap, c);
  14369. }
  14370. return soap_element_end_in(soap, NULL);
  14371. }
  14372. /******************************************************************************/
  14373. SOAP_FMAC1
  14374. int
  14375. SOAP_FMAC2
  14376. soap_string_out(struct soap *soap, const char *s, int flag)
  14377. {
  14378. const char *t;
  14379. soap_wchar c;
  14380. soap_wchar mask = (soap_wchar)0xFFFFFF80UL;
  14381. #ifdef WITH_DOM
  14382. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  14383. {
  14384. soap->dom->text = soap_strdup(soap, s);
  14385. if (!soap->dom->text)
  14386. return soap->error = SOAP_EOM;
  14387. return SOAP_OK;
  14388. }
  14389. #endif
  14390. if (flag == 2 || (soap->mode & SOAP_C_UTFSTRING))
  14391. mask = 0;
  14392. t = s;
  14393. while ((c = *t++))
  14394. {
  14395. switch (c)
  14396. {
  14397. case 0x09:
  14398. if (flag)
  14399. {
  14400. if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#x9;", 5))
  14401. return soap->error;
  14402. s = t;
  14403. }
  14404. break;
  14405. case 0x0A:
  14406. if (flag || !(soap->mode & SOAP_XML_CANONICAL))
  14407. {
  14408. if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#xA;", 5))
  14409. return soap->error;
  14410. s = t;
  14411. }
  14412. break;
  14413. case '&':
  14414. if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&amp;", 5))
  14415. return soap->error;
  14416. s = t;
  14417. break;
  14418. case '<':
  14419. if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&lt;", 4))
  14420. return soap->error;
  14421. s = t;
  14422. break;
  14423. case '>':
  14424. if (!flag)
  14425. {
  14426. if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&gt;", 4))
  14427. return soap->error;
  14428. s = t;
  14429. }
  14430. break;
  14431. case '"':
  14432. if (flag)
  14433. {
  14434. if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&quot;", 6))
  14435. return soap->error;
  14436. s = t;
  14437. }
  14438. break;
  14439. case 0x7F:
  14440. if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#x7F;", 6))
  14441. return soap->error;
  14442. s = t;
  14443. break;
  14444. default:
  14445. #ifndef WITH_LEANER
  14446. #ifdef HAVE_MBTOWC
  14447. if ((soap->mode & SOAP_C_MBSTRING))
  14448. {
  14449. wchar_t wc;
  14450. int m = mbtowc(&wc, t - 1, MB_CUR_MAX);
  14451. if (m > 0 && !((soap_wchar)wc == c && m == 1 && c < 0x80))
  14452. {
  14453. if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned long)wc))
  14454. return soap->error;
  14455. s = t += m - 1;
  14456. continue;
  14457. }
  14458. }
  14459. #endif
  14460. #endif
  14461. #ifndef WITH_NOSTRINGTOUTF8
  14462. if ((c & mask) || !(c & 0xFFFFFFE0UL))
  14463. {
  14464. if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c))
  14465. return soap->error;
  14466. s = t;
  14467. }
  14468. #endif
  14469. }
  14470. }
  14471. return soap_send_raw(soap, s, t - s - 1);
  14472. }
  14473. /******************************************************************************/
  14474. SOAP_FMAC1
  14475. char *
  14476. SOAP_FMAC2
  14477. soap_string_in(struct soap *soap, int flag, long minlen, long maxlen, const char *pattern)
  14478. {
  14479. char *s;
  14480. char *t = NULL;
  14481. size_t i;
  14482. ULONG64 l = 0;
  14483. int n = 0, f = 0, m = 0;
  14484. soap_wchar c;
  14485. #if !defined(WITH_LEANER) && defined(HAVE_WCTOMB)
  14486. char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8];
  14487. #else
  14488. char buf[8];
  14489. #endif
  14490. if (maxlen < 0 && soap->maxlength > 0)
  14491. maxlen = soap->maxlength;
  14492. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reading string content, flag=%d\n", flag));
  14493. if (flag <= 0 && soap->peeked && *soap->tag)
  14494. {
  14495. #ifndef WITH_LEAN
  14496. struct soap_attribute *tp;
  14497. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String content includes tag '%s' and attributes\n", soap->tag));
  14498. t = soap->tmpbuf;
  14499. *t = '<';
  14500. soap_strcpy(t + 1, sizeof(soap->tmpbuf) - 1, soap->tag);
  14501. t += strlen(t);
  14502. for (tp = soap->attributes; tp; tp = tp->next)
  14503. {
  14504. if (tp->visible)
  14505. {
  14506. size_t k = strlen(tp->name);
  14507. if (t + k + 1 >= soap->tmpbuf + sizeof(soap->tmpbuf))
  14508. break; /* too many or attribute values to large */
  14509. *t++ = ' ';
  14510. (void)soap_strncpy(t, sizeof(soap->tmpbuf) - (t - soap->tmpbuf), tp->name, k);
  14511. t += k;
  14512. if (tp->value)
  14513. {
  14514. k = strlen(tp->value);
  14515. if (t + k + 3 >= soap->tmpbuf + sizeof(soap->tmpbuf))
  14516. break; /* too many or attribute values to large */
  14517. *t++ = '=';
  14518. *t++ = '"';
  14519. (void)soap_strncpy(t, sizeof(soap->tmpbuf) - (t - soap->tmpbuf), tp->value, k);
  14520. t += k;
  14521. *t++ = '"';
  14522. }
  14523. }
  14524. }
  14525. if (!soap->body)
  14526. *t++ = '/';
  14527. *t++ = '>';
  14528. *t = '\0';
  14529. t = soap->tmpbuf;
  14530. m = (int)strlen(soap->tmpbuf);
  14531. #endif
  14532. if (soap->body)
  14533. n = 1;
  14534. f = 1;
  14535. soap->peeked = 0;
  14536. }
  14537. #ifdef WITH_CDATA
  14538. if (flag <= 0)
  14539. {
  14540. int state = 0;
  14541. #ifdef WITH_FAST
  14542. soap->labidx = 0; /* use look-aside buffer */
  14543. #else
  14544. if (soap_alloc_block(soap) == NULL)
  14545. return NULL;
  14546. #endif
  14547. for (;;)
  14548. {
  14549. #ifdef WITH_FAST
  14550. size_t k;
  14551. if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
  14552. return NULL;
  14553. s = soap->labbuf + soap->labidx; /* space to populate */
  14554. k = soap->lablen - soap->labidx; /* number of bytes available */
  14555. soap->labidx = soap->lablen; /* claim this space */
  14556. #else
  14557. size_t k = SOAP_BLKLEN;
  14558. s = (char*)soap_push_block(soap, NULL, k);
  14559. if (!s)
  14560. return NULL;
  14561. #endif
  14562. for (i = 0; i < k; i++)
  14563. {
  14564. if (m > 0)
  14565. {
  14566. *s++ = *t++; /* copy multibyte characters */
  14567. m--;
  14568. continue;
  14569. }
  14570. c = soap_getchar(soap);
  14571. if ((int)c == EOF)
  14572. goto end;
  14573. if ((c >= 0x80 || c < SOAP_AP) && state != 1 && !(soap->mode & SOAP_ENC_LATIN))
  14574. {
  14575. if ((c & 0x7FFFFFFF) >= 0x80)
  14576. {
  14577. soap_unget(soap, c);
  14578. c = soap_getutf8(soap);
  14579. }
  14580. if ((c & 0x7FFFFFFF) >= 0x80 && (flag <= 0 || (soap->mode & SOAP_C_UTFSTRING)))
  14581. {
  14582. c &= 0x7FFFFFFF;
  14583. t = buf;
  14584. if (c < 0x0800)
  14585. *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
  14586. else
  14587. {
  14588. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  14589. if (!((c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF)))
  14590. c = SOAP_UNKNOWN_UNICODE_CHAR;
  14591. #endif
  14592. if (c < 0x010000)
  14593. {
  14594. *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
  14595. }
  14596. else
  14597. {
  14598. if (c < 0x200000)
  14599. {
  14600. *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
  14601. }
  14602. else
  14603. {
  14604. if (c < 0x04000000)
  14605. {
  14606. *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
  14607. }
  14608. else
  14609. {
  14610. *t++ = (char)(0xFC | ((c >> 30) & 0x01));
  14611. *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
  14612. }
  14613. *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
  14614. }
  14615. *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
  14616. }
  14617. *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
  14618. }
  14619. *t++ = (char)(0x80 | (c & 0x3F));
  14620. m = (int)(t - buf) - 1;
  14621. t = buf;
  14622. *s++ = *t++;
  14623. continue;
  14624. }
  14625. }
  14626. switch (state)
  14627. {
  14628. case 1:
  14629. if (c == ']')
  14630. state = 4;
  14631. *s++ = (char)c;
  14632. continue;
  14633. case 2:
  14634. if (c == '-')
  14635. state = 6;
  14636. *s++ = (char)c;
  14637. continue;
  14638. case 3:
  14639. if (c == '?')
  14640. state = 8;
  14641. *s++ = (char)c;
  14642. continue;
  14643. /* CDATA */
  14644. case 4:
  14645. if (c == ']')
  14646. state = 5;
  14647. else
  14648. state = 1;
  14649. *s++ = (char)c;
  14650. continue;
  14651. case 5:
  14652. if (c == '>')
  14653. state = 0;
  14654. else if (c != ']')
  14655. state = 1;
  14656. *s++ = (char)c;
  14657. continue;
  14658. /* comment */
  14659. case 6:
  14660. if (c == '-')
  14661. state = 7;
  14662. else
  14663. state = 2;
  14664. *s++ = (char)c;
  14665. continue;
  14666. case 7:
  14667. if (c == '>')
  14668. state = 0;
  14669. else if (c != '-')
  14670. state = 2;
  14671. *s++ = (char)c;
  14672. continue;
  14673. /* PI */
  14674. case 8:
  14675. if (c == '>')
  14676. state = 0;
  14677. else if (c != '?')
  14678. state = 3;
  14679. *s++ = (char)c;
  14680. continue;
  14681. }
  14682. switch (c)
  14683. {
  14684. case SOAP_TT:
  14685. if (n == 0)
  14686. goto end;
  14687. n--;
  14688. *s++ = '<';
  14689. t = (char*)"/";
  14690. m = 1;
  14691. break;
  14692. case SOAP_LT:
  14693. if (flag == 3 || (f && n == 0))
  14694. goto end;
  14695. n++;
  14696. *s++ = '<';
  14697. break;
  14698. case SOAP_GT:
  14699. *s++ = '>';
  14700. break;
  14701. case SOAP_QT:
  14702. *s++ = '"';
  14703. break;
  14704. case SOAP_AP:
  14705. *s++ = '\'';
  14706. break;
  14707. case '/':
  14708. if (n > 0)
  14709. {
  14710. c = soap_getchar(soap);
  14711. if (c == '>')
  14712. n--;
  14713. soap_unget(soap, c);
  14714. }
  14715. *s++ = '/';
  14716. break;
  14717. case '<':
  14718. c = soap_getchar(soap);
  14719. if (c == '/')
  14720. {
  14721. if (n == 0)
  14722. {
  14723. c = SOAP_TT;
  14724. goto end;
  14725. }
  14726. n--;
  14727. }
  14728. else if (c == '!')
  14729. {
  14730. c = soap_getchar(soap);
  14731. if (c == '[')
  14732. {
  14733. do
  14734. {
  14735. c = soap_getchar(soap);
  14736. } while ((int)c != EOF && c != '[');
  14737. if ((int)c == EOF)
  14738. goto end;
  14739. t = (char*)"![CDATA[";
  14740. m = 8;
  14741. state = 1;
  14742. }
  14743. else if (c == '-')
  14744. {
  14745. c = soap_getchar(soap);
  14746. if (c == '-')
  14747. state = 2;
  14748. t = (char*)"!-";
  14749. m = 2;
  14750. soap_unget(soap, c);
  14751. }
  14752. else
  14753. {
  14754. t = (char*)"!";
  14755. m = 1;
  14756. soap_unget(soap, c);
  14757. }
  14758. *s++ = '<';
  14759. break;
  14760. }
  14761. else if (c == '?')
  14762. {
  14763. state = 3;
  14764. }
  14765. else if (flag == 3 || (f && n == 0))
  14766. {
  14767. soap_revget1(soap);
  14768. c = '<';
  14769. goto end;
  14770. }
  14771. else
  14772. n++;
  14773. soap_unget(soap, c);
  14774. *s++ = '<';
  14775. break;
  14776. case '>':
  14777. *s++ = '>';
  14778. break;
  14779. case '"':
  14780. *s++ = '"';
  14781. break;
  14782. default:
  14783. #ifndef WITH_LEANER
  14784. #ifdef HAVE_WCTOMB
  14785. if ((soap->mode & SOAP_C_MBSTRING))
  14786. {
  14787. #if defined(WIN32) && !defined(CYGWIN) && !defined(__MINGW32__) && !defined(__MINGW64__) && !defined(__BORLANDC__)
  14788. m = 0;
  14789. wctomb_s(&m, buf, sizeof(buf), (wchar_t)(c & 0x7FFFFFFF));
  14790. #else
  14791. m = wctomb(buf, (wchar_t)(c & 0x7FFFFFFF));
  14792. #endif
  14793. if (m >= 1 && m <= (int)MB_CUR_MAX)
  14794. {
  14795. t = buf;
  14796. *s++ = *t++;
  14797. m--;
  14798. }
  14799. else
  14800. {
  14801. *s++ = SOAP_UNKNOWN_CHAR;
  14802. m = 0;
  14803. }
  14804. }
  14805. else
  14806. #endif
  14807. #endif
  14808. *s++ = (char)(c & 0xFF);
  14809. }
  14810. l++;
  14811. if (maxlen >= 0 && l > (size_t)maxlen)
  14812. {
  14813. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
  14814. soap->error = SOAP_LENGTH;
  14815. return NULL;
  14816. }
  14817. }
  14818. }
  14819. }
  14820. #endif
  14821. #ifdef WITH_FAST
  14822. soap->labidx = 0; /* use look-aside buffer */
  14823. #else
  14824. if (soap_alloc_block(soap) == NULL)
  14825. return NULL;
  14826. #endif
  14827. for (;;)
  14828. {
  14829. #ifdef WITH_FAST
  14830. size_t k;
  14831. if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
  14832. return NULL;
  14833. s = soap->labbuf + soap->labidx; /* space to populate */
  14834. k = soap->lablen - soap->labidx; /* number of bytes available */
  14835. soap->labidx = soap->lablen; /* claim this space */
  14836. #else
  14837. size_t k = SOAP_BLKLEN;
  14838. s = (char*)soap_push_block(soap, NULL, k);
  14839. if (!s)
  14840. return NULL;
  14841. #endif
  14842. for (i = 0; i < k; i++)
  14843. {
  14844. if (m > 0)
  14845. {
  14846. *s++ = *t++; /* copy multibyte characters */
  14847. m--;
  14848. continue;
  14849. }
  14850. #ifndef WITH_CDATA
  14851. if (flag <= 0)
  14852. c = soap_getchar(soap);
  14853. else
  14854. #endif
  14855. {
  14856. c = soap_getutf8(soap);
  14857. if ((soap->mode & SOAP_C_UTFSTRING))
  14858. {
  14859. if (c >= 0x80 || (c < SOAP_AP && c >= -0x7FFFFF80))
  14860. {
  14861. c &= 0x7FFFFFFF;
  14862. t = buf;
  14863. if (c < 0x0800)
  14864. {
  14865. *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
  14866. }
  14867. else
  14868. {
  14869. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  14870. if (!((c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF)))
  14871. c = SOAP_UNKNOWN_UNICODE_CHAR;
  14872. #endif
  14873. if (c < 0x010000)
  14874. {
  14875. *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
  14876. }
  14877. else
  14878. {
  14879. if (c < 0x200000)
  14880. {
  14881. *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
  14882. }
  14883. else
  14884. {
  14885. if (c < 0x04000000)
  14886. {
  14887. *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
  14888. }
  14889. else
  14890. {
  14891. *t++ = (char)(0xFC | ((c >> 30) & 0x01));
  14892. *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
  14893. }
  14894. *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
  14895. }
  14896. *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
  14897. }
  14898. *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
  14899. }
  14900. *t++ = (char)(0x80 | (c & 0x3F));
  14901. m = (int)(t - buf) - 1;
  14902. t = buf;
  14903. *s++ = *t++;
  14904. l++;
  14905. if (maxlen >= 0 && l > (size_t)maxlen)
  14906. {
  14907. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
  14908. soap->error = SOAP_LENGTH;
  14909. return NULL;
  14910. }
  14911. continue;
  14912. }
  14913. }
  14914. }
  14915. switch (c)
  14916. {
  14917. case SOAP_TT:
  14918. if (n == 0)
  14919. goto end;
  14920. n--;
  14921. *s++ = '<';
  14922. t = (char*)"/";
  14923. m = 1;
  14924. break;
  14925. case SOAP_LT:
  14926. if (flag == 3 || (f && n == 0))
  14927. goto end;
  14928. n++;
  14929. *s++ = '<';
  14930. break;
  14931. case SOAP_GT:
  14932. *s++ = '>';
  14933. break;
  14934. case SOAP_QT:
  14935. *s++ = '"';
  14936. break;
  14937. case SOAP_AP:
  14938. *s++ = '\'';
  14939. break;
  14940. case '/':
  14941. if (n > 0)
  14942. {
  14943. if (flag > 0)
  14944. {
  14945. c = soap_get(soap);
  14946. if (c == SOAP_GT)
  14947. n--;
  14948. }
  14949. else
  14950. {
  14951. c = soap_getchar(soap);
  14952. if (c == '>')
  14953. n--;
  14954. }
  14955. soap_unget(soap, c);
  14956. }
  14957. *s++ = '/';
  14958. break;
  14959. case (soap_wchar)('<' | 0x80000000):
  14960. if (flag > 0)
  14961. {
  14962. *s++ = '<';
  14963. }
  14964. else
  14965. {
  14966. *s++ = '&';
  14967. t = (char*)"lt;";
  14968. m = 3;
  14969. }
  14970. break;
  14971. case (soap_wchar)('>' | 0x80000000):
  14972. if (flag > 0)
  14973. {
  14974. *s++ = '>';
  14975. }
  14976. else
  14977. {
  14978. *s++ = '&';
  14979. t = (char*)"gt;";
  14980. m = 3;
  14981. }
  14982. break;
  14983. case (soap_wchar)('&' | 0x80000000):
  14984. if (flag > 0)
  14985. {
  14986. *s++ = '&';
  14987. }
  14988. else
  14989. {
  14990. *s++ = '&';
  14991. t = (char*)"amp;";
  14992. m = 4;
  14993. }
  14994. break;
  14995. case (soap_wchar)('"' | 0x80000000):
  14996. if (flag > 0)
  14997. {
  14998. *s++ = '"';
  14999. }
  15000. else
  15001. {
  15002. *s++ = '&';
  15003. t = (char*)"quot;";
  15004. m = 5;
  15005. }
  15006. break;
  15007. case (soap_wchar)('\'' | 0x80000000):
  15008. if (flag > 0)
  15009. {
  15010. *s++ = '\'';
  15011. }
  15012. else
  15013. {
  15014. *s++ = '&';
  15015. t = (char*)"apos;";
  15016. m = 5;
  15017. }
  15018. break;
  15019. default:
  15020. if ((int)c == EOF)
  15021. goto end;
  15022. #ifndef WITH_CDATA
  15023. if (c == '<')
  15024. {
  15025. c = soap_getchar(soap);
  15026. soap_unget(soap, c);
  15027. if (c == '/')
  15028. {
  15029. c = SOAP_TT;
  15030. if (n == 0)
  15031. goto end;
  15032. n--;
  15033. }
  15034. else
  15035. {
  15036. n++;
  15037. }
  15038. *s++ = '<';
  15039. }
  15040. else
  15041. #endif
  15042. #ifndef WITH_LEANER
  15043. #ifdef HAVE_WCTOMB
  15044. if ((soap->mode & SOAP_C_MBSTRING))
  15045. {
  15046. #if defined(WIN32) && !defined(CYGWIN) && !defined(__MINGW32__) && !defined(__MINGW64__) && !defined(__BORLANDC__)
  15047. m = 0;
  15048. wctomb_s(&m, buf, sizeof(buf), (wchar_t)(c & 0x7FFFFFFF));
  15049. #else
  15050. m = wctomb(buf, (wchar_t)(c & 0x7FFFFFFF));
  15051. #endif
  15052. if (m >= 1 && m <= (int)MB_CUR_MAX)
  15053. {
  15054. t = buf;
  15055. *s++ = *t++;
  15056. m--;
  15057. }
  15058. else
  15059. {
  15060. *s++ = SOAP_UNKNOWN_CHAR;
  15061. m = 0;
  15062. }
  15063. }
  15064. else
  15065. #endif
  15066. #endif
  15067. *s++ = (char)(c & 0xFF);
  15068. }
  15069. l++;
  15070. if (maxlen >= 0 && l > (size_t)maxlen)
  15071. {
  15072. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
  15073. soap->error = SOAP_LENGTH;
  15074. return NULL;
  15075. }
  15076. }
  15077. }
  15078. end:
  15079. soap_unget(soap, c);
  15080. *s = '\0';
  15081. #ifdef WITH_FAST
  15082. t = soap_strdup(soap, soap->labbuf);
  15083. if (!t)
  15084. return NULL;
  15085. #else
  15086. soap_size_block(soap, NULL, i + 1);
  15087. t = soap_save_block(soap, NULL, NULL, 0);
  15088. #endif
  15089. if (minlen > 0 && l < (size_t)minlen)
  15090. {
  15091. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too short: %lu chars, minlen=%ld\n", (unsigned long)l, minlen));
  15092. soap->error = SOAP_LENGTH;
  15093. return NULL;
  15094. }
  15095. #ifdef WITH_DOM
  15096. if ((soap->mode & SOAP_XML_DOM) && soap->dom && *t)
  15097. {
  15098. if (flag > 0)
  15099. soap->dom->text = t;
  15100. else
  15101. soap->dom->code = t;
  15102. }
  15103. #endif
  15104. if (flag == 2)
  15105. {
  15106. if (soap_s2QName(soap, t, &t, minlen, maxlen, pattern))
  15107. return NULL;
  15108. }
  15109. else if (flag >= 4 && t)
  15110. {
  15111. t = soap_collapse(soap, t, flag, 1);
  15112. }
  15113. #ifndef WITH_LEANER
  15114. else if (pattern && soap->fsvalidate)
  15115. {
  15116. soap->error = soap->fsvalidate(soap, pattern, t);
  15117. if (soap->error)
  15118. return NULL;
  15119. }
  15120. #endif
  15121. return t;
  15122. }
  15123. /******************************************************************************/
  15124. #ifndef WITH_LEANER
  15125. SOAP_FMAC1
  15126. int
  15127. SOAP_FMAC2
  15128. soap_wstring_out(struct soap *soap, const wchar_t *s, int flag)
  15129. {
  15130. const char *t;
  15131. char tmp;
  15132. soap_wchar c;
  15133. #ifdef WITH_DOM
  15134. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  15135. {
  15136. soap->dom->text = soap_wchar2s(soap, s);
  15137. return SOAP_OK;
  15138. }
  15139. #endif
  15140. while ((c = *s++))
  15141. {
  15142. switch (c)
  15143. {
  15144. case 0x09:
  15145. if (flag)
  15146. t = "&#x9;";
  15147. else
  15148. t = "\t";
  15149. break;
  15150. case 0x0A:
  15151. if (flag || !(soap->mode & SOAP_XML_CANONICAL))
  15152. t = "&#xA;";
  15153. else
  15154. t = "\n";
  15155. break;
  15156. case 0x0D:
  15157. t = "&#xD;";
  15158. break;
  15159. case '&':
  15160. t = "&amp;";
  15161. break;
  15162. case '<':
  15163. t = "&lt;";
  15164. break;
  15165. case '>':
  15166. if (flag)
  15167. t = ">";
  15168. else
  15169. t = "&gt;";
  15170. break;
  15171. case '"':
  15172. if (flag)
  15173. t = "&quot;";
  15174. else
  15175. t = "\"";
  15176. break;
  15177. default:
  15178. if (c >= 0x20 && c < 0x80)
  15179. {
  15180. tmp = (char)c;
  15181. if (soap_send_raw(soap, &tmp, 1))
  15182. return soap->error;
  15183. }
  15184. else
  15185. {
  15186. /* check for UTF16 encoding when wchar_t is too small to hold UCS */
  15187. if (sizeof(wchar_t) < 4 && (c & 0xFC00) == 0xD800)
  15188. {
  15189. soap_wchar d = *s;
  15190. if ((d & 0xFC00) == 0xDC00)
  15191. {
  15192. c = ((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000;
  15193. s++;
  15194. }
  15195. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  15196. else
  15197. {
  15198. c = SOAP_UNKNOWN_UNICODE_CHAR; /* Malformed UTF-16 */
  15199. }
  15200. #endif
  15201. }
  15202. if (soap_pututf8(soap, (unsigned long)c))
  15203. return soap->error;
  15204. }
  15205. continue;
  15206. }
  15207. if (soap_send(soap, t))
  15208. return soap->error;
  15209. }
  15210. return SOAP_OK;
  15211. }
  15212. #endif
  15213. /******************************************************************************/
  15214. #ifndef WITH_LEANER
  15215. SOAP_FMAC1
  15216. wchar_t *
  15217. SOAP_FMAC2
  15218. soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen, const char *pattern)
  15219. {
  15220. wchar_t *s;
  15221. int i, n = 0, f = 0;
  15222. ULONG64 l = 0;
  15223. soap_wchar c;
  15224. char *t = NULL;
  15225. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reading wide string content\n"));
  15226. if (maxlen < 0 && soap->maxlength > 0)
  15227. maxlen = soap->maxlength;
  15228. if (flag <= 0 && soap->peeked && *soap->tag)
  15229. {
  15230. #ifndef WITH_LEAN
  15231. struct soap_attribute *tp;
  15232. t = soap->tmpbuf;
  15233. *t = '<';
  15234. soap_strcpy(t + 1, sizeof(soap->tmpbuf) - 1, soap->tag);
  15235. t += strlen(t);
  15236. for (tp = soap->attributes; tp; tp = tp->next)
  15237. {
  15238. if (tp->visible)
  15239. {
  15240. size_t k = strlen(tp->name);
  15241. if (t + k + 1 >= soap->tmpbuf + sizeof(soap->tmpbuf))
  15242. break;
  15243. *t++ = ' ';
  15244. (void)soap_strncpy(t, sizeof(soap->tmpbuf) - (t - soap->tmpbuf), tp->name, k);
  15245. t += k;
  15246. if (tp->value)
  15247. {
  15248. k = strlen(tp->value);
  15249. if (t + k + 3 >= soap->tmpbuf + sizeof(soap->tmpbuf))
  15250. break;
  15251. *t++ = '=';
  15252. *t++ = '"';
  15253. (void)soap_strncpy(t, sizeof(soap->tmpbuf) - (t - soap->tmpbuf), tp->value, k);
  15254. t += k;
  15255. *t++ = '"';
  15256. }
  15257. }
  15258. }
  15259. if (!soap->body)
  15260. *t++ = '/';
  15261. *t++ = '>';
  15262. *t = '\0';
  15263. t = soap->tmpbuf;
  15264. #endif
  15265. if (soap->body)
  15266. n = 1;
  15267. f = 1;
  15268. soap->peeked = 0;
  15269. }
  15270. if (soap_alloc_block(soap) == NULL)
  15271. return NULL;
  15272. for (;;)
  15273. {
  15274. s = (wchar_t*)soap_push_block(soap, NULL, sizeof(wchar_t)*SOAP_BLKLEN);
  15275. if (!s)
  15276. return NULL;
  15277. for (i = 0; i < SOAP_BLKLEN; i++)
  15278. {
  15279. if (t)
  15280. {
  15281. *s++ = (wchar_t)*t++;
  15282. if (!*t)
  15283. t = NULL;
  15284. continue;
  15285. }
  15286. c = soap_getutf8(soap);
  15287. switch (c)
  15288. {
  15289. case SOAP_TT:
  15290. if (n == 0)
  15291. goto end;
  15292. n--;
  15293. *s++ = L'<';
  15294. soap_unget(soap, '/');
  15295. break;
  15296. case SOAP_LT:
  15297. if (flag == 3 || (f && n == 0))
  15298. goto end;
  15299. n++;
  15300. *s++ = L'<';
  15301. break;
  15302. case SOAP_GT:
  15303. *s++ = L'>';
  15304. break;
  15305. case SOAP_QT:
  15306. *s++ = L'"';
  15307. break;
  15308. case SOAP_AP:
  15309. *s++ = L'\'';
  15310. break;
  15311. case '/':
  15312. if (n > 0)
  15313. {
  15314. c = soap_getutf8(soap);
  15315. if (c == SOAP_GT)
  15316. n--;
  15317. soap_unget(soap, c);
  15318. }
  15319. *s++ = L'/';
  15320. break;
  15321. case '<':
  15322. if (flag > 0)
  15323. {
  15324. *s++ = L'<';
  15325. }
  15326. else
  15327. {
  15328. *s++ = L'&';
  15329. t = (char*)"lt;";
  15330. }
  15331. break;
  15332. case '>':
  15333. if (flag > 0)
  15334. {
  15335. *s++ = L'>';
  15336. }
  15337. else
  15338. {
  15339. *s++ = (wchar_t)'&';
  15340. t = (char*)"gt;";
  15341. }
  15342. break;
  15343. case '"':
  15344. if (flag > 0)
  15345. {
  15346. *s++ = L'"';
  15347. }
  15348. else
  15349. {
  15350. *s++ = L'&';
  15351. t = (char*)"quot;";
  15352. }
  15353. break;
  15354. default:
  15355. if ((int)c == EOF)
  15356. goto end;
  15357. /* use UTF16 encoding when wchar_t is too small to hold UCS */
  15358. if (sizeof(wchar_t) < 4 && c > 0xFFFF)
  15359. {
  15360. soap_wchar c1, c2;
  15361. c1 = 0xD800 - (0x10000 >> 10) + (c >> 10);
  15362. c2 = 0xDC00 + (c & 0x3FF);
  15363. c = c1;
  15364. soap_unget(soap, c2);
  15365. }
  15366. *s++ = (wchar_t)(c & 0x7FFFFFFF);
  15367. }
  15368. l++;
  15369. if (maxlen >= 0 && l > (size_t)maxlen)
  15370. {
  15371. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
  15372. soap->error = SOAP_LENGTH;
  15373. return NULL;
  15374. }
  15375. }
  15376. }
  15377. end:
  15378. soap_unget(soap, c);
  15379. *s = L'\0';
  15380. soap_size_block(soap, NULL, sizeof(wchar_t) * (i + 1));
  15381. if (minlen > 0 && l < (size_t)minlen)
  15382. {
  15383. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too short: %lu chars, minlen=%ld\n", (unsigned long)l, minlen));
  15384. soap->error = SOAP_LENGTH;
  15385. return NULL;
  15386. }
  15387. s = (wchar_t*)soap_save_block(soap, NULL, NULL, 0);
  15388. #ifndef WITH_LEAN
  15389. if (flag >= 4 && s)
  15390. s = soap_wcollapse(soap, s, flag, 1);
  15391. #endif
  15392. #ifndef WITH_LEANER
  15393. if (pattern && soap->fwvalidate)
  15394. {
  15395. soap->error = soap->fwvalidate(soap, pattern, s);
  15396. if (soap->error)
  15397. return NULL;
  15398. }
  15399. #endif
  15400. #ifdef WITH_DOM
  15401. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  15402. soap->dom->text = soap_wchar2s(soap, s);
  15403. #endif
  15404. return s;
  15405. }
  15406. #endif
  15407. /******************************************************************************/
  15408. SOAP_FMAC1
  15409. const char*
  15410. SOAP_FMAC2
  15411. soap_int2s(struct soap *soap, int n)
  15412. {
  15413. return soap_long2s(soap, (long)n);
  15414. }
  15415. /******************************************************************************/
  15416. SOAP_FMAC1
  15417. int
  15418. SOAP_FMAC2
  15419. soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n)
  15420. {
  15421. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  15422. || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
  15423. return soap->error;
  15424. return soap_element_end_out(soap, tag);
  15425. }
  15426. /******************************************************************************/
  15427. SOAP_FMAC1
  15428. int
  15429. SOAP_FMAC2
  15430. soap_s2int(struct soap *soap, const char *s, int *p)
  15431. {
  15432. if (s)
  15433. {
  15434. long n;
  15435. char *r;
  15436. if (!*s)
  15437. return soap->error = SOAP_EMPTY;
  15438. #ifndef WITH_NOIO
  15439. #ifndef WITH_LEAN
  15440. soap_reset_errno;
  15441. #endif
  15442. #endif
  15443. n = soap_strtol(s, &r, 10);
  15444. if (s == r || *r
  15445. #ifndef WITH_LEAN
  15446. || n != (int)n
  15447. #endif
  15448. #ifndef WITH_NOIO
  15449. #ifndef WITH_LEAN
  15450. || soap_errno == SOAP_ERANGE
  15451. #endif
  15452. #endif
  15453. )
  15454. soap->error = SOAP_TYPE;
  15455. *p = (int)n;
  15456. }
  15457. return soap->error;
  15458. }
  15459. /******************************************************************************/
  15460. SOAP_FMAC1
  15461. int *
  15462. SOAP_FMAC2
  15463. soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t)
  15464. {
  15465. if (soap_element_begin_in(soap, tag, 0, NULL))
  15466. return NULL;
  15467. #ifndef WITH_LEAN
  15468. if (*soap->type
  15469. && soap_match_tag(soap, soap->type, type)
  15470. && soap_match_tag(soap, soap->type, ":int")
  15471. && soap_match_tag(soap, soap->type, ":short")
  15472. && soap_match_tag(soap, soap->type, ":byte"))
  15473. {
  15474. soap->error = SOAP_TYPE;
  15475. soap_revert(soap);
  15476. return NULL;
  15477. }
  15478. #else
  15479. (void)type;
  15480. #endif
  15481. p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), NULL, NULL, NULL, NULL);
  15482. if (!p)
  15483. return NULL;
  15484. if (*soap->href != '#')
  15485. {
  15486. int err = soap_s2int(soap, soap_value(soap), p);
  15487. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  15488. return NULL;
  15489. }
  15490. else
  15491. {
  15492. p = (int*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(int), 0, NULL, NULL);
  15493. if (soap->body && soap_element_end_in(soap, tag))
  15494. return NULL;
  15495. }
  15496. return p;
  15497. }
  15498. /******************************************************************************/
  15499. SOAP_FMAC1
  15500. const char*
  15501. SOAP_FMAC2
  15502. soap_long2s(struct soap *soap, long n)
  15503. {
  15504. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), "%ld", n);
  15505. return soap->tmpbuf;
  15506. }
  15507. /******************************************************************************/
  15508. SOAP_FMAC1
  15509. int
  15510. SOAP_FMAC2
  15511. soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n)
  15512. {
  15513. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  15514. || soap_string_out(soap, soap_long2s(soap, *p), 0))
  15515. return soap->error;
  15516. return soap_element_end_out(soap, tag);
  15517. }
  15518. /******************************************************************************/
  15519. SOAP_FMAC1
  15520. int
  15521. SOAP_FMAC2
  15522. soap_s2long(struct soap *soap, const char *s, long *p)
  15523. {
  15524. if (s)
  15525. {
  15526. char *r;
  15527. if (!*s)
  15528. return soap->error = SOAP_EMPTY;
  15529. #ifndef WITH_NOIO
  15530. #ifndef WITH_LEAN
  15531. soap_reset_errno;
  15532. #endif
  15533. #endif
  15534. *p = soap_strtol(s, &r, 10);
  15535. if (s == r || *r
  15536. #ifndef WITH_NOIO
  15537. #ifndef WITH_LEAN
  15538. || soap_errno == SOAP_ERANGE
  15539. #endif
  15540. #endif
  15541. )
  15542. soap->error = SOAP_TYPE;
  15543. }
  15544. return soap->error;
  15545. }
  15546. /******************************************************************************/
  15547. SOAP_FMAC1
  15548. long *
  15549. SOAP_FMAC2
  15550. soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t)
  15551. {
  15552. if (soap_element_begin_in(soap, tag, 0, NULL))
  15553. return NULL;
  15554. #ifndef WITH_LEAN
  15555. if (*soap->type
  15556. && soap_match_tag(soap, soap->type, type)
  15557. && soap_match_tag(soap, soap->type, ":int")
  15558. && soap_match_tag(soap, soap->type, ":short")
  15559. && soap_match_tag(soap, soap->type, ":byte"))
  15560. {
  15561. soap->error = SOAP_TYPE;
  15562. soap_revert(soap);
  15563. return NULL;
  15564. }
  15565. #else
  15566. (void)type;
  15567. #endif
  15568. p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), NULL, NULL, NULL, NULL);
  15569. if (!p)
  15570. return NULL;
  15571. if (*soap->href != '#')
  15572. {
  15573. int err = soap_s2long(soap, soap_value(soap), p);
  15574. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  15575. return NULL;
  15576. }
  15577. else
  15578. {
  15579. p = (long*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(long), 0, NULL, NULL);
  15580. if (soap->body && soap_element_end_in(soap, tag))
  15581. return NULL;
  15582. }
  15583. return p;
  15584. }
  15585. /******************************************************************************/
  15586. SOAP_FMAC1
  15587. const char*
  15588. SOAP_FMAC2
  15589. soap_LONG642s(struct soap *soap, LONG64 n)
  15590. {
  15591. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), SOAP_LONG_FORMAT, n);
  15592. return soap->tmpbuf;
  15593. }
  15594. /******************************************************************************/
  15595. SOAP_FMAC1
  15596. int
  15597. SOAP_FMAC2
  15598. soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n)
  15599. {
  15600. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  15601. || soap_string_out(soap, soap_LONG642s(soap, *p), 0))
  15602. return soap->error;
  15603. return soap_element_end_out(soap, tag);
  15604. }
  15605. /******************************************************************************/
  15606. SOAP_FMAC1
  15607. int
  15608. SOAP_FMAC2
  15609. soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p)
  15610. {
  15611. if (s)
  15612. {
  15613. char *r;
  15614. if (!*s)
  15615. return soap->error = SOAP_EMPTY;
  15616. #ifndef WITH_NOIO
  15617. #ifndef WITH_LEAN
  15618. soap_reset_errno;
  15619. #endif
  15620. #endif
  15621. *p = soap_strtoll(s, &r, 10);
  15622. if (s == r || *r
  15623. #ifndef WITH_NOIO
  15624. #ifndef WITH_LEAN
  15625. || soap_errno == SOAP_ERANGE
  15626. #endif
  15627. #endif
  15628. )
  15629. soap->error = SOAP_TYPE;
  15630. }
  15631. return soap->error;
  15632. }
  15633. /******************************************************************************/
  15634. SOAP_FMAC1
  15635. LONG64 *
  15636. SOAP_FMAC2
  15637. soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t)
  15638. {
  15639. if (soap_element_begin_in(soap, tag, 0, NULL))
  15640. return NULL;
  15641. #ifndef WITH_LEAN
  15642. if (*soap->type
  15643. && soap_match_tag(soap, soap->type, type)
  15644. && soap_match_tag(soap, soap->type, ":integer")
  15645. && soap_match_tag(soap, soap->type, ":positiveInteger")
  15646. && soap_match_tag(soap, soap->type, ":negativeInteger")
  15647. && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
  15648. && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
  15649. && soap_match_tag(soap, soap->type, ":long")
  15650. && soap_match_tag(soap, soap->type, ":int")
  15651. && soap_match_tag(soap, soap->type, ":short")
  15652. && soap_match_tag(soap, soap->type, ":byte"))
  15653. {
  15654. soap->error = SOAP_TYPE;
  15655. soap_revert(soap);
  15656. return NULL;
  15657. }
  15658. #else
  15659. (void)type;
  15660. #endif
  15661. p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), NULL, NULL, NULL, NULL);
  15662. if (!p)
  15663. return NULL;
  15664. if (*soap->href != '#')
  15665. {
  15666. int err = soap_s2LONG64(soap, soap_value(soap), p);
  15667. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  15668. return NULL;
  15669. }
  15670. else
  15671. {
  15672. p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(LONG64), 0, NULL, NULL);
  15673. if (soap->body && soap_element_end_in(soap, tag))
  15674. return NULL;
  15675. }
  15676. return p;
  15677. }
  15678. /******************************************************************************/
  15679. SOAP_FMAC1
  15680. const char*
  15681. SOAP_FMAC2
  15682. soap_byte2s(struct soap *soap, char n)
  15683. {
  15684. return soap_long2s(soap, (long)n);
  15685. }
  15686. /******************************************************************************/
  15687. SOAP_FMAC1
  15688. int
  15689. SOAP_FMAC2
  15690. soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n)
  15691. {
  15692. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  15693. || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
  15694. return soap->error;
  15695. return soap_element_end_out(soap, tag);
  15696. }
  15697. /******************************************************************************/
  15698. SOAP_FMAC1
  15699. int
  15700. SOAP_FMAC2
  15701. soap_s2byte(struct soap *soap, const char *s, char *p)
  15702. {
  15703. if (s)
  15704. {
  15705. long n;
  15706. char *r;
  15707. if (!*s)
  15708. return soap->error = SOAP_EMPTY;
  15709. n = soap_strtol(s, &r, 10);
  15710. if (s == r || *r || n < -128 || n > 127)
  15711. soap->error = SOAP_TYPE;
  15712. *p = (char)n;
  15713. }
  15714. return soap->error;
  15715. }
  15716. /******************************************************************************/
  15717. SOAP_FMAC1
  15718. char *
  15719. SOAP_FMAC2
  15720. soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t)
  15721. {
  15722. if (soap_element_begin_in(soap, tag, 0, NULL))
  15723. return NULL;
  15724. #ifndef WITH_LEAN
  15725. if (*soap->type
  15726. && soap_match_tag(soap, soap->type, type)
  15727. && soap_match_tag(soap, soap->type, ":byte"))
  15728. {
  15729. soap->error = SOAP_TYPE;
  15730. soap_revert(soap);
  15731. return NULL;
  15732. }
  15733. #else
  15734. (void)type;
  15735. #endif
  15736. p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), NULL, NULL, NULL, NULL);
  15737. if (!p)
  15738. return NULL;
  15739. if (*soap->href != '#')
  15740. {
  15741. int err = soap_s2byte(soap, soap_value(soap), p);
  15742. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  15743. return NULL;
  15744. }
  15745. else
  15746. {
  15747. p = (char*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(char), 0, NULL, NULL);
  15748. if (soap->body && soap_element_end_in(soap, tag))
  15749. return NULL;
  15750. }
  15751. return p;
  15752. }
  15753. /******************************************************************************/
  15754. SOAP_FMAC1
  15755. const char*
  15756. SOAP_FMAC2
  15757. soap_short2s(struct soap *soap, short n)
  15758. {
  15759. return soap_long2s(soap, (long)n);
  15760. }
  15761. /******************************************************************************/
  15762. SOAP_FMAC1
  15763. int
  15764. SOAP_FMAC2
  15765. soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n)
  15766. {
  15767. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  15768. || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
  15769. return soap->error;
  15770. return soap_element_end_out(soap, tag);
  15771. }
  15772. /******************************************************************************/
  15773. SOAP_FMAC1
  15774. int
  15775. SOAP_FMAC2
  15776. soap_s2short(struct soap *soap, const char *s, short *p)
  15777. {
  15778. if (s)
  15779. {
  15780. long n;
  15781. char *r;
  15782. if (!*s)
  15783. return soap->error = SOAP_EMPTY;
  15784. n = soap_strtol(s, &r, 10);
  15785. if (s == r || *r || n < -32768 || n > 32767)
  15786. soap->error = SOAP_TYPE;
  15787. *p = (short)n;
  15788. }
  15789. return soap->error;
  15790. }
  15791. /******************************************************************************/
  15792. SOAP_FMAC1
  15793. short *
  15794. SOAP_FMAC2
  15795. soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t)
  15796. {
  15797. if (soap_element_begin_in(soap, tag, 0, NULL))
  15798. return NULL;
  15799. #ifndef WITH_LEAN
  15800. if (*soap->type
  15801. && soap_match_tag(soap, soap->type, type)
  15802. && soap_match_tag(soap, soap->type, ":short")
  15803. && soap_match_tag(soap, soap->type, ":byte"))
  15804. {
  15805. soap->error = SOAP_TYPE;
  15806. soap_revert(soap);
  15807. return NULL;
  15808. }
  15809. #else
  15810. (void)type;
  15811. #endif
  15812. p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), NULL, NULL, NULL, NULL);
  15813. if (!p)
  15814. return NULL;
  15815. if (*soap->href != '#')
  15816. {
  15817. int err = soap_s2short(soap, soap_value(soap), p);
  15818. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  15819. return NULL;
  15820. }
  15821. else
  15822. {
  15823. p = (short*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(short), 0, NULL, NULL);
  15824. if (soap->body && soap_element_end_in(soap, tag))
  15825. return NULL;
  15826. }
  15827. return p;
  15828. }
  15829. /******************************************************************************/
  15830. SOAP_FMAC1
  15831. const char*
  15832. SOAP_FMAC2
  15833. soap_float2s(struct soap *soap, float n)
  15834. {
  15835. #if defined(WITH_C_LOCALE)
  15836. # if !defined(WIN32)
  15837. SOAP_LOCALE_T locale;
  15838. # endif
  15839. #else
  15840. char *s;
  15841. #endif
  15842. if (soap_isnan((double)n))
  15843. return "NaN";
  15844. if (soap_ispinff(n))
  15845. return "INF";
  15846. if (soap_isninff(n))
  15847. return "-INF";
  15848. #if defined(WITH_C_LOCALE)
  15849. # ifdef WIN32
  15850. _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->float_format, SOAP_LOCALE(soap), n);
  15851. # else
  15852. locale = uselocale(SOAP_LOCALE(soap));
  15853. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), soap->float_format, n);
  15854. uselocale(locale);
  15855. # endif
  15856. #else
  15857. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), soap->float_format, n);
  15858. s = strchr(soap->tmpbuf, ','); /* convert decimal comma to DP */
  15859. if (s)
  15860. *s = '.';
  15861. #endif
  15862. return soap->tmpbuf;
  15863. }
  15864. /******************************************************************************/
  15865. SOAP_FMAC1
  15866. int
  15867. SOAP_FMAC2
  15868. soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n)
  15869. {
  15870. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  15871. || soap_string_out(soap, soap_float2s(soap, *p), 0))
  15872. return soap->error;
  15873. return soap_element_end_out(soap, tag);
  15874. }
  15875. /******************************************************************************/
  15876. SOAP_FMAC1
  15877. int
  15878. SOAP_FMAC2
  15879. soap_s2float(struct soap *soap, const char *s, float *p)
  15880. {
  15881. if (s)
  15882. {
  15883. if (!*s)
  15884. return soap->error = SOAP_EMPTY;
  15885. if (!soap_tag_cmp(s, "INF"))
  15886. {
  15887. *p = FLT_PINFTY;
  15888. }
  15889. else if (!soap_tag_cmp(s, "+INF"))
  15890. {
  15891. *p = FLT_PINFTY;
  15892. }
  15893. else if (!soap_tag_cmp(s, "-INF"))
  15894. {
  15895. *p = FLT_NINFTY;
  15896. }
  15897. else if (!soap_tag_cmp(s, "NaN"))
  15898. {
  15899. *p = FLT_NAN;
  15900. }
  15901. else
  15902. {
  15903. /* On some systems strtof requires -std=c99 or does not even link: so we try strtod first */
  15904. #if defined(WITH_C_LOCALE)
  15905. # if defined(HAVE_STRTOD_L)
  15906. char *r;
  15907. # ifdef WIN32
  15908. *p = (float)_strtod_l(s, &r, SOAP_LOCALE(soap));
  15909. # else
  15910. *p = (float)strtod_l(s, &r, SOAP_LOCALE(soap));
  15911. # endif
  15912. if (*r)
  15913. soap->error = SOAP_TYPE;
  15914. # elif defined(HAVE_STRTOF_L)
  15915. char *r;
  15916. *p = strtof_l((char*)s, &r, SOAP_LOCALE(soap));
  15917. if (*r)
  15918. soap->error = SOAP_TYPE;
  15919. # elif defined(HAVE_SSCANF_L)
  15920. double n;
  15921. if (sscanf_l(s, SOAP_LOCALE(soap), "%lf", &n) != 1)
  15922. soap->error = SOAP_TYPE;
  15923. *p = (float)n;
  15924. # elif defined(HAVE_STRTOD)
  15925. char *r;
  15926. SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap));
  15927. *p = (float)strtod((char*)s, &r);
  15928. uselocale(locale);
  15929. if (*r)
  15930. soap->error = SOAP_TYPE;
  15931. # elif defined(HAVE_STRTOF)
  15932. char *r;
  15933. SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap));
  15934. *p = strtof((char*)s, &r);
  15935. uselocale(locale);
  15936. if (*r)
  15937. soap->error = SOAP_TYPE;
  15938. # elif defined(HAVE_SSCANF)
  15939. double n;
  15940. SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap));
  15941. if (sscanf(s, "%lf", &n) != 1)
  15942. soap->error = SOAP_TYPE;
  15943. uselocale(locale);
  15944. *p = (float)n;
  15945. # else
  15946. soap->error = SOAP_TYPE;
  15947. # endif
  15948. #elif defined(HAVE_STRTOD)
  15949. char *r;
  15950. *p = (float)strtod(s, &r);
  15951. if (*r)
  15952. soap->error = SOAP_TYPE;
  15953. #elif defined(HAVE_STRTOF)
  15954. char *r;
  15955. *p = strtof((char*)s, &r);
  15956. if (*r)
  15957. soap->error = SOAP_TYPE;
  15958. #elif defined(HAVE_SSCANF)
  15959. double n;
  15960. if (sscanf(s, "%lf", &n) != 1)
  15961. soap->error = SOAP_TYPE;
  15962. *p = (float)n;
  15963. #else
  15964. soap->error = SOAP_TYPE;
  15965. #endif
  15966. }
  15967. }
  15968. return soap->error;
  15969. }
  15970. /******************************************************************************/
  15971. #ifndef WITH_LEAN
  15972. static int soap_isnumeric(struct soap *soap, const char *type)
  15973. {
  15974. if (soap_match_tag(soap, soap->type, type)
  15975. && soap_match_tag(soap, soap->type, ":float")
  15976. && soap_match_tag(soap, soap->type, ":double")
  15977. && soap_match_tag(soap, soap->type, ":decimal")
  15978. && soap_match_tag(soap, soap->type, ":integer")
  15979. && soap_match_tag(soap, soap->type, ":positiveInteger")
  15980. && soap_match_tag(soap, soap->type, ":negativeInteger")
  15981. && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
  15982. && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
  15983. && soap_match_tag(soap, soap->type, ":long")
  15984. && soap_match_tag(soap, soap->type, ":int")
  15985. && soap_match_tag(soap, soap->type, ":short")
  15986. && soap_match_tag(soap, soap->type, ":byte")
  15987. && soap_match_tag(soap, soap->type, ":unsignedLong")
  15988. && soap_match_tag(soap, soap->type, ":unsignedInt")
  15989. && soap_match_tag(soap, soap->type, ":unsignedShort")
  15990. && soap_match_tag(soap, soap->type, ":unsignedByte"))
  15991. {
  15992. soap->error = SOAP_TYPE;
  15993. soap_revert(soap);
  15994. return SOAP_ERR;
  15995. }
  15996. return SOAP_OK;
  15997. }
  15998. #endif
  15999. /******************************************************************************/
  16000. SOAP_FMAC1
  16001. float *
  16002. SOAP_FMAC2
  16003. soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t)
  16004. {
  16005. if (soap_element_begin_in(soap, tag, 0, NULL))
  16006. return NULL;
  16007. #ifndef WITH_LEAN
  16008. if (*soap->type != '\0' && soap_isnumeric(soap, type))
  16009. return NULL;
  16010. #else
  16011. (void)type;
  16012. #endif
  16013. p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), NULL, NULL, NULL, NULL);
  16014. if (!p)
  16015. return NULL;
  16016. if (*soap->href != '#')
  16017. {
  16018. int err = soap_s2float(soap, soap_value(soap), p);
  16019. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  16020. return NULL;
  16021. }
  16022. else
  16023. {
  16024. p = (float*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(float), 0, NULL, NULL);
  16025. if (soap->body && soap_element_end_in(soap, tag))
  16026. return NULL;
  16027. }
  16028. return p;
  16029. }
  16030. /******************************************************************************/
  16031. SOAP_FMAC1
  16032. const char*
  16033. SOAP_FMAC2
  16034. soap_double2s(struct soap *soap, double n)
  16035. {
  16036. #if defined(WITH_C_LOCALE)
  16037. # if !defined(WIN32)
  16038. SOAP_LOCALE_T locale;
  16039. # endif
  16040. #else
  16041. char *s;
  16042. #endif
  16043. if (soap_isnan(n))
  16044. return "NaN";
  16045. if (soap_ispinfd(n))
  16046. return "INF";
  16047. if (soap_isninfd(n))
  16048. return "-INF";
  16049. #if defined(WITH_C_LOCALE)
  16050. # ifdef WIN32
  16051. _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->double_format, SOAP_LOCALE(soap), n);
  16052. # else
  16053. locale = uselocale(SOAP_LOCALE(soap));
  16054. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 40), soap->double_format, n);
  16055. uselocale(locale);
  16056. # endif
  16057. #else
  16058. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 40), soap->double_format, n);
  16059. s = strchr(soap->tmpbuf, ','); /* convert decimal comma to DP */
  16060. if (s)
  16061. *s = '.';
  16062. #endif
  16063. return soap->tmpbuf;
  16064. }
  16065. /******************************************************************************/
  16066. SOAP_FMAC1
  16067. int
  16068. SOAP_FMAC2
  16069. soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n)
  16070. {
  16071. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  16072. || soap_string_out(soap, soap_double2s(soap, *p), 0))
  16073. return soap->error;
  16074. return soap_element_end_out(soap, tag);
  16075. }
  16076. /******************************************************************************/
  16077. SOAP_FMAC1
  16078. int
  16079. SOAP_FMAC2
  16080. soap_s2double(struct soap *soap, const char *s, double *p)
  16081. {
  16082. if (s)
  16083. {
  16084. if (!*s)
  16085. return soap->error = SOAP_EMPTY;
  16086. if (!soap_tag_cmp(s, "INF"))
  16087. {
  16088. *p = DBL_PINFTY;
  16089. }
  16090. else if (!soap_tag_cmp(s, "+INF"))
  16091. {
  16092. *p = DBL_PINFTY;
  16093. }
  16094. else if (!soap_tag_cmp(s, "-INF"))
  16095. {
  16096. *p = DBL_NINFTY;
  16097. }
  16098. else if (!soap_tag_cmp(s, "NaN"))
  16099. {
  16100. *p = DBL_NAN;
  16101. }
  16102. else
  16103. {
  16104. #if defined(WITH_C_LOCALE)
  16105. # if defined(HAVE_STRTOD_L)
  16106. char *r;
  16107. # ifdef WIN32
  16108. *p = _strtod_l(s, &r, SOAP_LOCALE(soap));
  16109. # else
  16110. *p = strtod_l(s, &r, SOAP_LOCALE(soap));
  16111. # endif
  16112. if (*r)
  16113. soap->error = SOAP_TYPE;
  16114. # elif defined(HAVE_STRTOD)
  16115. char *r;
  16116. SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap));
  16117. *p = strtod(s, &r);
  16118. uselocale(locale);
  16119. if (*r)
  16120. soap->error = SOAP_TYPE;
  16121. # elif defined(HAVE_SSCANF_L)
  16122. SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap));
  16123. if (sscanf_l(s, SOAP_LOCALE(soap), "%lf", p) != 1)
  16124. soap->error = SOAP_TYPE;
  16125. uselocale(locale);
  16126. # else
  16127. soap->error = SOAP_TYPE;
  16128. # endif
  16129. #elif defined(HAVE_STRTOD)
  16130. char *r;
  16131. *p = strtod(s, &r);
  16132. if (*r)
  16133. soap->error = SOAP_TYPE;
  16134. #elif defined(HAVE_SSCANF)
  16135. if (sscanf(s, "%lf", p) != 1)
  16136. soap->error = SOAP_TYPE;
  16137. #else
  16138. soap->error = SOAP_TYPE;
  16139. #endif
  16140. }
  16141. }
  16142. return soap->error;
  16143. }
  16144. /******************************************************************************/
  16145. SOAP_FMAC1
  16146. double *
  16147. SOAP_FMAC2
  16148. soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t)
  16149. {
  16150. if (soap_element_begin_in(soap, tag, 0, NULL))
  16151. return NULL;
  16152. #ifndef WITH_LEAN
  16153. if (*soap->type != '\0' && soap_isnumeric(soap, type))
  16154. return NULL;
  16155. #else
  16156. (void)type;
  16157. #endif
  16158. p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), NULL, NULL, NULL, NULL);
  16159. if (!p)
  16160. return NULL;
  16161. if (*soap->href != '#')
  16162. {
  16163. int err = soap_s2double(soap, soap_value(soap), p);
  16164. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  16165. return NULL;
  16166. }
  16167. else
  16168. {
  16169. p = (double*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(double), 0, NULL, NULL);
  16170. if (soap->body && soap_element_end_in(soap, tag))
  16171. return NULL;
  16172. }
  16173. return p;
  16174. }
  16175. /******************************************************************************/
  16176. SOAP_FMAC1
  16177. const char*
  16178. SOAP_FMAC2
  16179. soap_unsignedByte2s(struct soap *soap, unsigned char n)
  16180. {
  16181. return soap_unsignedLong2s(soap, (unsigned long)n);
  16182. }
  16183. /******************************************************************************/
  16184. SOAP_FMAC1
  16185. int
  16186. SOAP_FMAC2
  16187. soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n)
  16188. {
  16189. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  16190. || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
  16191. return soap->error;
  16192. return soap_element_end_out(soap, tag);
  16193. }
  16194. /******************************************************************************/
  16195. SOAP_FMAC1
  16196. int
  16197. SOAP_FMAC2
  16198. soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p)
  16199. {
  16200. if (s)
  16201. {
  16202. long n;
  16203. char *r;
  16204. if (!*s)
  16205. return soap->error = SOAP_EMPTY;
  16206. n = soap_strtol(s, &r, 10);
  16207. if (s == r || *r || n < 0 || n > 255)
  16208. soap->error = SOAP_TYPE;
  16209. *p = (unsigned char)n;
  16210. }
  16211. return soap->error;
  16212. }
  16213. /******************************************************************************/
  16214. SOAP_FMAC1
  16215. unsigned char *
  16216. SOAP_FMAC2
  16217. soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t)
  16218. {
  16219. if (soap_element_begin_in(soap, tag, 0, NULL))
  16220. return NULL;
  16221. #ifndef WITH_LEAN
  16222. if (*soap->type
  16223. && soap_match_tag(soap, soap->type, type)
  16224. && soap_match_tag(soap, soap->type, ":unsignedByte"))
  16225. {
  16226. soap->error = SOAP_TYPE;
  16227. soap_revert(soap);
  16228. return NULL;
  16229. }
  16230. #else
  16231. (void)type;
  16232. #endif
  16233. p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), NULL, NULL, NULL, NULL);
  16234. if (!p)
  16235. return NULL;
  16236. if (*soap->href != '#')
  16237. {
  16238. int err = soap_s2unsignedByte(soap, soap_value(soap), p);
  16239. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  16240. return NULL;
  16241. }
  16242. else
  16243. {
  16244. p = (unsigned char*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(unsigned char), 0, NULL, NULL);
  16245. if (soap->body && soap_element_end_in(soap, tag))
  16246. return NULL;
  16247. }
  16248. return p;
  16249. }
  16250. /******************************************************************************/
  16251. SOAP_FMAC1
  16252. const char*
  16253. SOAP_FMAC2
  16254. soap_unsignedShort2s(struct soap *soap, unsigned short n)
  16255. {
  16256. return soap_unsignedLong2s(soap, (unsigned long)n);
  16257. }
  16258. /******************************************************************************/
  16259. SOAP_FMAC1
  16260. int
  16261. SOAP_FMAC2
  16262. soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n)
  16263. {
  16264. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  16265. || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
  16266. return soap->error;
  16267. return soap_element_end_out(soap, tag);
  16268. }
  16269. /******************************************************************************/
  16270. SOAP_FMAC1
  16271. int
  16272. SOAP_FMAC2
  16273. soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p)
  16274. {
  16275. if (s)
  16276. {
  16277. long n;
  16278. char *r;
  16279. if (!*s)
  16280. return soap->error = SOAP_EMPTY;
  16281. n = soap_strtol(s, &r, 10);
  16282. if (s == r || *r || n < 0 || n > 65535)
  16283. soap->error = SOAP_TYPE;
  16284. *p = (unsigned short)n;
  16285. }
  16286. return soap->error;
  16287. }
  16288. /******************************************************************************/
  16289. SOAP_FMAC1
  16290. unsigned short *
  16291. SOAP_FMAC2
  16292. soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t)
  16293. {
  16294. if (soap_element_begin_in(soap, tag, 0, NULL))
  16295. return NULL;
  16296. #ifndef WITH_LEAN
  16297. if (*soap->type
  16298. && soap_match_tag(soap, soap->type, type)
  16299. && soap_match_tag(soap, soap->type, ":unsignedShort")
  16300. && soap_match_tag(soap, soap->type, ":unsignedByte"))
  16301. {
  16302. soap->error = SOAP_TYPE;
  16303. soap_revert(soap);
  16304. return NULL;
  16305. }
  16306. #else
  16307. (void)type;
  16308. #endif
  16309. p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), NULL, NULL, NULL, NULL);
  16310. if (!p)
  16311. return NULL;
  16312. if (*soap->href != '#')
  16313. {
  16314. int err = soap_s2unsignedShort(soap, soap_value(soap), p);
  16315. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  16316. return NULL;
  16317. }
  16318. else
  16319. {
  16320. p = (unsigned short*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(unsigned short), 0, NULL, NULL);
  16321. if (soap->body && soap_element_end_in(soap, tag))
  16322. return NULL;
  16323. }
  16324. return p;
  16325. }
  16326. /******************************************************************************/
  16327. SOAP_FMAC1
  16328. const char*
  16329. SOAP_FMAC2
  16330. soap_unsignedInt2s(struct soap *soap, unsigned int n)
  16331. {
  16332. return soap_unsignedLong2s(soap, (unsigned long)n);
  16333. }
  16334. /******************************************************************************/
  16335. SOAP_FMAC1
  16336. int
  16337. SOAP_FMAC2
  16338. soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n)
  16339. {
  16340. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  16341. || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
  16342. return soap->error;
  16343. return soap_element_end_out(soap, tag);
  16344. }
  16345. /******************************************************************************/
  16346. SOAP_FMAC1
  16347. int
  16348. SOAP_FMAC2
  16349. soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p)
  16350. {
  16351. if (s)
  16352. {
  16353. char *r;
  16354. if (!*s)
  16355. return soap->error = SOAP_EMPTY;
  16356. #ifndef WITH_NOIO
  16357. #ifndef WITH_LEAN
  16358. soap_reset_errno;
  16359. #endif
  16360. #endif
  16361. *p = (unsigned int)soap_strtoul(s, &r, 10);
  16362. if (s == r || *r
  16363. #ifndef WITH_NOIO
  16364. #ifndef WITH_LEAN
  16365. || soap_errno == SOAP_ERANGE
  16366. #endif
  16367. #endif
  16368. )
  16369. soap->error = SOAP_TYPE;
  16370. #ifdef HAVE_STRTOUL
  16371. if (*p > 0 && strchr(s, '-'))
  16372. return soap->error = SOAP_TYPE;
  16373. #endif
  16374. }
  16375. return soap->error;
  16376. }
  16377. /******************************************************************************/
  16378. SOAP_FMAC1
  16379. unsigned int *
  16380. SOAP_FMAC2
  16381. soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t)
  16382. {
  16383. if (soap_element_begin_in(soap, tag, 0, NULL))
  16384. return NULL;
  16385. #ifndef WITH_LEAN
  16386. if (*soap->type
  16387. && soap_match_tag(soap, soap->type, type)
  16388. && soap_match_tag(soap, soap->type, ":unsignedInt")
  16389. && soap_match_tag(soap, soap->type, ":unsignedShort")
  16390. && soap_match_tag(soap, soap->type, ":unsignedByte"))
  16391. {
  16392. soap->error = SOAP_TYPE;
  16393. soap_revert(soap);
  16394. return NULL;
  16395. }
  16396. #else
  16397. (void)type;
  16398. #endif
  16399. p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), NULL, NULL, NULL, NULL);
  16400. if (!p)
  16401. return NULL;
  16402. if (*soap->href != '#')
  16403. {
  16404. int err = soap_s2unsignedInt(soap, soap_value(soap), p);
  16405. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  16406. return NULL;
  16407. }
  16408. else
  16409. {
  16410. p = (unsigned int*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(unsigned int), 0, NULL, NULL);
  16411. if (soap->body && soap_element_end_in(soap, tag))
  16412. return NULL;
  16413. }
  16414. return p;
  16415. }
  16416. /******************************************************************************/
  16417. SOAP_FMAC1
  16418. const char*
  16419. SOAP_FMAC2
  16420. soap_unsignedLong2s(struct soap *soap, unsigned long n)
  16421. {
  16422. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), "%lu", n);
  16423. return soap->tmpbuf;
  16424. }
  16425. /******************************************************************************/
  16426. SOAP_FMAC1
  16427. int
  16428. SOAP_FMAC2
  16429. soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n)
  16430. {
  16431. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  16432. || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0))
  16433. return soap->error;
  16434. return soap_element_end_out(soap, tag);
  16435. }
  16436. /******************************************************************************/
  16437. SOAP_FMAC1
  16438. int
  16439. SOAP_FMAC2
  16440. soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p)
  16441. {
  16442. if (s)
  16443. {
  16444. char *r;
  16445. if (!*s)
  16446. return soap->error = SOAP_EMPTY;
  16447. #ifndef WITH_NOIO
  16448. #ifndef WITH_LEAN
  16449. soap_reset_errno;
  16450. #endif
  16451. #endif
  16452. *p = soap_strtoul(s, &r, 10);
  16453. if (s == r || *r
  16454. #ifndef WITH_NOIO
  16455. #ifndef WITH_LEAN
  16456. || soap_errno == SOAP_ERANGE
  16457. #endif
  16458. #endif
  16459. )
  16460. soap->error = SOAP_TYPE;
  16461. #ifdef HAVE_STRTOUL
  16462. if (*p > 0 && strchr(s, '-'))
  16463. return soap->error = SOAP_TYPE;
  16464. #endif
  16465. }
  16466. return soap->error;
  16467. }
  16468. /******************************************************************************/
  16469. SOAP_FMAC1
  16470. unsigned long *
  16471. SOAP_FMAC2
  16472. soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t)
  16473. {
  16474. if (soap_element_begin_in(soap, tag, 0, NULL))
  16475. return NULL;
  16476. #ifndef WITH_LEAN
  16477. if (*soap->type
  16478. && soap_match_tag(soap, soap->type, type)
  16479. && soap_match_tag(soap, soap->type, ":unsignedInt")
  16480. && soap_match_tag(soap, soap->type, ":unsignedShort")
  16481. && soap_match_tag(soap, soap->type, ":unsignedByte"))
  16482. {
  16483. soap->error = SOAP_TYPE;
  16484. soap_revert(soap);
  16485. return NULL;
  16486. }
  16487. #else
  16488. (void)type;
  16489. #endif
  16490. p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), NULL, NULL, NULL, NULL);
  16491. if (!p)
  16492. return NULL;
  16493. if (*soap->href != '#')
  16494. {
  16495. int err = soap_s2unsignedLong(soap, soap_value(soap), p);
  16496. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  16497. return NULL;
  16498. }
  16499. else
  16500. {
  16501. p = (unsigned long*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(unsigned long), 0, NULL, NULL);
  16502. if (soap->body && soap_element_end_in(soap, tag))
  16503. return NULL;
  16504. }
  16505. return p;
  16506. }
  16507. /******************************************************************************/
  16508. SOAP_FMAC1
  16509. const char*
  16510. SOAP_FMAC2
  16511. soap_ULONG642s(struct soap *soap, ULONG64 n)
  16512. {
  16513. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), SOAP_ULONG_FORMAT, n);
  16514. return soap->tmpbuf;
  16515. }
  16516. /******************************************************************************/
  16517. SOAP_FMAC1
  16518. int
  16519. SOAP_FMAC2
  16520. soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n)
  16521. {
  16522. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  16523. || soap_string_out(soap, soap_ULONG642s(soap, *p), 0))
  16524. return soap->error;
  16525. return soap_element_end_out(soap, tag);
  16526. }
  16527. /******************************************************************************/
  16528. SOAP_FMAC1
  16529. int
  16530. SOAP_FMAC2
  16531. soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p)
  16532. {
  16533. if (s)
  16534. {
  16535. char *r;
  16536. if (!*s)
  16537. return soap->error = SOAP_EMPTY;
  16538. #ifndef WITH_NOIO
  16539. #ifndef WITH_LEAN
  16540. soap_reset_errno;
  16541. #endif
  16542. #endif
  16543. *p = soap_strtoull(s, &r, 10);
  16544. if (s == r || *r
  16545. #ifndef WITH_NOIO
  16546. #ifndef WITH_LEAN
  16547. || soap_errno == SOAP_ERANGE
  16548. #endif
  16549. #endif
  16550. )
  16551. soap->error = SOAP_TYPE;
  16552. if (*p > 0 && strchr(s, '-'))
  16553. return soap->error = SOAP_TYPE;
  16554. }
  16555. return soap->error;
  16556. }
  16557. /******************************************************************************/
  16558. SOAP_FMAC1
  16559. ULONG64 *
  16560. SOAP_FMAC2
  16561. soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t)
  16562. {
  16563. if (soap_element_begin_in(soap, tag, 0, NULL))
  16564. return NULL;
  16565. #ifndef WITH_LEAN
  16566. if (*soap->type
  16567. && soap_match_tag(soap, soap->type, type)
  16568. && soap_match_tag(soap, soap->type, ":positiveInteger")
  16569. && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
  16570. && soap_match_tag(soap, soap->type, ":unsignedLong")
  16571. && soap_match_tag(soap, soap->type, ":unsignedInt")
  16572. && soap_match_tag(soap, soap->type, ":unsignedShort")
  16573. && soap_match_tag(soap, soap->type, ":unsignedByte"))
  16574. {
  16575. soap->error = SOAP_TYPE;
  16576. soap_revert(soap);
  16577. return NULL;
  16578. }
  16579. #else
  16580. (void)type;
  16581. #endif
  16582. p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), NULL, NULL, NULL, NULL);
  16583. if (!p)
  16584. return NULL;
  16585. if (*soap->href != '#')
  16586. {
  16587. int err = soap_s2ULONG64(soap, soap_value(soap), p);
  16588. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  16589. return NULL;
  16590. }
  16591. else
  16592. {
  16593. p = (ULONG64*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(ULONG64), 0, NULL, NULL);
  16594. if (soap->body && soap_element_end_in(soap, tag))
  16595. return NULL;
  16596. }
  16597. return p;
  16598. }
  16599. /******************************************************************************/
  16600. SOAP_FMAC1
  16601. int
  16602. SOAP_FMAC2
  16603. soap_s2char(struct soap *soap, const char *s, char **t, int flag, long minlen, long maxlen, const char *pattern)
  16604. {
  16605. if (s)
  16606. {
  16607. const char *r = soap_string(soap, s, flag, minlen, maxlen, pattern);
  16608. if (r && (*t = soap_strdup(soap, r)) == NULL)
  16609. return soap->error = SOAP_EOM;
  16610. }
  16611. return soap->error;
  16612. }
  16613. /******************************************************************************/
  16614. #ifndef WITH_COMPAT
  16615. #ifdef __cplusplus
  16616. SOAP_FMAC1
  16617. int
  16618. SOAP_FMAC2
  16619. soap_s2stdchar(struct soap *soap, const char *s, std::string *t, int flag, long minlen, long maxlen, const char *pattern)
  16620. {
  16621. if (s)
  16622. {
  16623. const char *r = soap_string(soap, s, flag, minlen, maxlen, pattern);
  16624. if (r)
  16625. t->assign(r);
  16626. }
  16627. return soap->error;
  16628. }
  16629. #endif
  16630. #endif
  16631. /******************************************************************************/
  16632. static const char*
  16633. soap_string(struct soap *soap, const char *s, int flag, long minlen, long maxlen, const char *pattern)
  16634. {
  16635. if (s)
  16636. {
  16637. if (maxlen < 0 && soap->maxlength > 0)
  16638. maxlen = soap->maxlength;
  16639. if (minlen > 0 || maxlen >= 0)
  16640. {
  16641. size_t l;
  16642. if ((soap->mode & SOAP_C_UTFSTRING))
  16643. l = soap_utf8len(s);
  16644. else
  16645. l = strlen(s);
  16646. if ((maxlen >= 0 && l > (size_t)maxlen) || (minlen > 0 && l < (size_t)minlen))
  16647. {
  16648. soap->error = SOAP_LENGTH;
  16649. return NULL;
  16650. }
  16651. }
  16652. if (flag >= 4)
  16653. s = soap_collapse(soap, (char*)s, flag, 0);
  16654. #ifndef WITH_LEANER
  16655. if (pattern && soap->fsvalidate)
  16656. {
  16657. soap->error = soap->fsvalidate(soap, pattern, s);
  16658. if (soap->error)
  16659. return NULL;
  16660. }
  16661. #else
  16662. (void)pattern;
  16663. #endif
  16664. }
  16665. return s;
  16666. }
  16667. /******************************************************************************/
  16668. static char*
  16669. soap_collapse(struct soap *soap, char *s, int flag, int insitu)
  16670. {
  16671. /* flag 4=normalizedString (replace), 5=token (collapse) */
  16672. char *t;
  16673. size_t n;
  16674. if (!s)
  16675. return NULL;
  16676. if (flag == 4)
  16677. {
  16678. for (t = s; *t && (!soap_coblank((soap_wchar)*t) || *t == 32); t++)
  16679. continue;
  16680. if (*t)
  16681. {
  16682. /* replace white space and control chars by blanks */
  16683. if (!insitu)
  16684. s = soap_strdup(soap, s);
  16685. for (t = s; *t; t++)
  16686. if (soap_coblank((soap_wchar)*t))
  16687. *t = ' ';
  16688. }
  16689. return s;
  16690. }
  16691. /* collapse white space */
  16692. for (t = s; *t && soap_coblank((soap_wchar)*t); t++)
  16693. continue;
  16694. n = strlen(t);
  16695. if (insitu && s < t)
  16696. (void)soap_memmove(s, n + 1, t, n + 1);
  16697. else
  16698. s = t;
  16699. if (n > 0)
  16700. {
  16701. if (!soap_coblank((soap_wchar)s[n-1]))
  16702. {
  16703. for (t = s; (*t && !soap_coblank((soap_wchar)*t)) || (*t == 32 && (!t[1] || !soap_coblank((soap_wchar)t[1]))); t++)
  16704. continue;
  16705. if (!*t)
  16706. return s;
  16707. }
  16708. if (!insitu)
  16709. s = soap_strdup(soap, s);
  16710. for (t = s; *t; t++)
  16711. {
  16712. if (soap_coblank((soap_wchar)*t))
  16713. {
  16714. char *r;
  16715. *t = ' ';
  16716. for (r = t + 1; *r && soap_coblank((soap_wchar)*r); r++)
  16717. continue;
  16718. if (r > t + 1)
  16719. (void)soap_memmove(t + 1, n - (t-s), r, n - (r-s) + 1);
  16720. }
  16721. }
  16722. t--;
  16723. if (t >= s && *t == 32)
  16724. *t = '\0';
  16725. }
  16726. return s;
  16727. }
  16728. /******************************************************************************/
  16729. SOAP_FMAC1
  16730. int
  16731. SOAP_FMAC2
  16732. soap_s2QName(struct soap *soap, const char *s, char **t, long minlen, long maxlen, const char *pattern)
  16733. {
  16734. *t = NULL;
  16735. if (s)
  16736. {
  16737. const char *r = soap_QName(soap, s, minlen, maxlen, pattern);
  16738. if (r && (*t = soap_strdup(soap, r)) == NULL)
  16739. return soap->error = SOAP_EOM;
  16740. }
  16741. return soap->error;
  16742. }
  16743. /******************************************************************************/
  16744. #ifndef WITH_COMPAT
  16745. #ifdef __cplusplus
  16746. SOAP_FMAC1
  16747. int
  16748. SOAP_FMAC2
  16749. soap_s2stdQName(struct soap *soap, const char *s, std::string *t, long minlen, long maxlen, const char *pattern)
  16750. {
  16751. t->clear();
  16752. if (s)
  16753. {
  16754. const char *r = soap_QName(soap, s, minlen, maxlen, pattern);
  16755. if (r)
  16756. t->assign(r);
  16757. }
  16758. return soap->error;
  16759. }
  16760. #endif
  16761. #endif
  16762. /******************************************************************************/
  16763. static const char*
  16764. soap_QName(struct soap *soap, const char *s, long minlen, long maxlen, const char *pattern)
  16765. {
  16766. if (s)
  16767. {
  16768. char *b;
  16769. if (maxlen < 0 && soap->maxlength > 0)
  16770. maxlen = soap->maxlength;
  16771. if (minlen > 0 || maxlen >= 0)
  16772. {
  16773. size_t l;
  16774. if ((soap->mode & SOAP_C_UTFSTRING))
  16775. l = soap_utf8len(s);
  16776. else
  16777. l = strlen(s);
  16778. if ((maxlen >= 0 && l > (size_t)maxlen) || (minlen > 0 && l < (size_t)minlen))
  16779. {
  16780. soap->error = SOAP_LENGTH;
  16781. return NULL;
  16782. }
  16783. }
  16784. #ifdef WITH_FAST
  16785. soap->labidx = 0;
  16786. #else
  16787. if (soap_alloc_block(soap) == NULL)
  16788. return NULL;
  16789. #endif
  16790. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Normalized namespace(s) of QNames '%s'", s));
  16791. /* convert (by prefix normalize prefix) all QNames in s */
  16792. for (;;)
  16793. {
  16794. size_t n;
  16795. struct soap_nlist *np;
  16796. const char *p = NULL;
  16797. short flag = 0;
  16798. const char *r = NULL;
  16799. size_t m = 0;
  16800. #ifndef WITH_FAST
  16801. size_t k = 0;
  16802. #endif
  16803. /* skip blanks */
  16804. while (*s && soap_coblank((soap_wchar)*s))
  16805. s++;
  16806. if (!*s)
  16807. break;
  16808. /* find next QName */
  16809. n = 1;
  16810. while (s[n] && !soap_coblank((soap_wchar)s[n]))
  16811. n++;
  16812. np = soap->nlist;
  16813. /* if there is no namespace stack, or prefix is "#" or "xml" then copy string */
  16814. if (!np || *s == '#' || !strncmp(s, "xml:", 4))
  16815. {
  16816. r = s;
  16817. m = n;
  16818. }
  16819. else /* we normalize the QName by replacing its prefix */
  16820. {
  16821. const char *q;
  16822. for (p = s; *p && p < s + n; p++)
  16823. if (*p == ':')
  16824. break;
  16825. if (*p == ':')
  16826. {
  16827. size_t k = p - s;
  16828. while (np && (strncmp(np->id, s, k) || np->id[k]))
  16829. np = np->next;
  16830. p++;
  16831. }
  16832. else
  16833. {
  16834. while (np && *np->id)
  16835. np = np->next;
  16836. p = s;
  16837. }
  16838. /* replace prefix */
  16839. if (np)
  16840. {
  16841. if (np->index >= 0 && soap->local_namespaces && (q = soap->local_namespaces[np->index].id) != NULL)
  16842. {
  16843. size_t k = strlen(q);
  16844. if (q[k-1] != '_')
  16845. {
  16846. r = q;
  16847. m = k;
  16848. }
  16849. else
  16850. {
  16851. flag = 1;
  16852. r = soap->local_namespaces[np->index].ns;
  16853. m = strlen(r);
  16854. }
  16855. }
  16856. else if (np->ns)
  16857. {
  16858. flag = 1;
  16859. r = np->ns;
  16860. m = strlen(r);
  16861. }
  16862. else
  16863. {
  16864. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\nNamespace prefix of '%s' not defined (index=%d, URI='%s')\n", s, np->index, np->ns ? np->ns : SOAP_STR_EOS));
  16865. soap->error = SOAP_NAMESPACE;
  16866. return NULL;
  16867. }
  16868. }
  16869. else if (s[n]) /* no namespace, part of string */
  16870. {
  16871. r = s;
  16872. m = n;
  16873. }
  16874. else /* no namespace: assume "" namespace */
  16875. {
  16876. flag = 1;
  16877. }
  16878. }
  16879. #ifdef WITH_FAST
  16880. if ((flag && soap_append_lab(soap, "\"", 1))
  16881. || (m && soap_append_lab(soap, r, m))
  16882. || (flag && soap_append_lab(soap, "\"", 1))
  16883. || (p && (soap_append_lab(soap, ":", 1) || soap_append_lab(soap, p, n - (p-s)))))
  16884. return NULL;
  16885. #else
  16886. k = 2*flag + m + (p ? n - (p-s) + 1 : 0) + (s[n] != '\0');
  16887. b = (char*)soap_push_block(soap, NULL, k);
  16888. if (!b)
  16889. return NULL;
  16890. if (flag)
  16891. *b++ = '"';
  16892. if (m)
  16893. {
  16894. if (soap_memcpy((void*)b, k, (const void*)r, m))
  16895. {
  16896. soap->error = SOAP_EOM;
  16897. return NULL;
  16898. }
  16899. b += m;
  16900. }
  16901. if (flag)
  16902. *b++ = '"';
  16903. if (p)
  16904. {
  16905. *b++ = ':';
  16906. if (soap_memcpy((void*)b, k - m - flag - 1, (const void*)p, n - (p-s)))
  16907. {
  16908. soap->error = SOAP_EOM;
  16909. return NULL;
  16910. }
  16911. b += n - (p-s);
  16912. }
  16913. #endif
  16914. /* advance to next and add spacing */
  16915. s += n;
  16916. while (*s && soap_coblank(*s))
  16917. s++;
  16918. if (*s)
  16919. {
  16920. #ifdef WITH_FAST
  16921. if (soap_append_lab(soap, " ", 1))
  16922. return NULL;
  16923. #else
  16924. *b = ' ';
  16925. #endif
  16926. }
  16927. }
  16928. #ifdef WITH_FAST
  16929. if (soap_append_lab(soap, SOAP_STR_EOS, 1))
  16930. return NULL;
  16931. b = soap->labbuf;
  16932. #else
  16933. b = (char*)soap_push_block(soap, NULL, 1);
  16934. if (!b)
  16935. return NULL;
  16936. *b = '\0';
  16937. b = (char*)soap_save_block(soap, NULL, NULL, 0);
  16938. #endif
  16939. #ifndef WITH_LEANER
  16940. if (pattern && soap->fsvalidate)
  16941. {
  16942. soap->error = soap->fsvalidate(soap, pattern, b);
  16943. if (soap->error)
  16944. return NULL;
  16945. }
  16946. #else
  16947. (void)pattern;
  16948. #endif
  16949. return b;
  16950. }
  16951. return NULL;
  16952. }
  16953. /******************************************************************************/
  16954. SOAP_FMAC1
  16955. const char*
  16956. SOAP_FMAC2
  16957. soap_QName2s(struct soap *soap, const char *s)
  16958. {
  16959. const char *t = NULL;
  16960. if (s)
  16961. {
  16962. #ifdef WITH_FAST
  16963. soap_store_lab(soap, SOAP_STR_EOS, 1);
  16964. soap->labidx = 0;
  16965. #else
  16966. char *b = NULL;
  16967. if (soap_alloc_block(soap) == NULL)
  16968. return NULL;
  16969. #endif
  16970. for (;;)
  16971. {
  16972. size_t n;
  16973. const char *q = NULL;
  16974. const char *r = NULL;
  16975. size_t m = 0;
  16976. #ifndef WITH_FAST
  16977. size_t k = 0;
  16978. #endif
  16979. /* skip blanks */
  16980. while (*s && soap_coblank((soap_wchar)*s))
  16981. s++;
  16982. if (!*s)
  16983. {
  16984. #ifdef WITH_FAST
  16985. soap->labbuf[soap->labidx > 0 ? soap->labidx - 1 : 0] = '\0';
  16986. #else
  16987. if (!b)
  16988. return soap_strdup(soap, SOAP_STR_EOS);
  16989. --b;
  16990. *b = '\0';
  16991. #endif
  16992. break;
  16993. }
  16994. /* find next QName */
  16995. n = 0;
  16996. while (s[n] && !soap_coblank((soap_wchar)s[n]))
  16997. {
  16998. if (s[n] == ':')
  16999. r = s;
  17000. n++;
  17001. }
  17002. if (*s != '"') /* non-quoted: pass string as is */
  17003. {
  17004. #ifndef WITH_LEAN
  17005. if (r && (soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_XML_CANONICAL_NA))
  17006. soap_utilize_ns(soap, s, 1);
  17007. #endif
  17008. r = s;
  17009. m = n + 1;
  17010. }
  17011. else /* prefix quoted URI-based string */
  17012. {
  17013. q = strchr(s + 1, '"');
  17014. if (q)
  17015. {
  17016. struct Namespace *p = soap->local_namespaces;
  17017. if (p)
  17018. {
  17019. for (; p->id; p++)
  17020. {
  17021. if (p->ns)
  17022. if (!soap_tag_cmp(s + 1, p->ns))
  17023. break;
  17024. if (p->in)
  17025. if (!soap_tag_cmp(s + 1, p->in))
  17026. break;
  17027. }
  17028. }
  17029. q++;
  17030. /* URL is in the namespace table? */
  17031. if (p && p->id)
  17032. {
  17033. r = p->id;
  17034. m = strlen(r);
  17035. }
  17036. else /* not in namespace table: create xmlns binding */
  17037. {
  17038. char *x = soap_strdup(soap, s + 1);
  17039. if (!x)
  17040. return NULL;
  17041. x[q - s - 2] = '\0';
  17042. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 27), "xmlns:_%d", soap->idnum++);
  17043. soap_set_attr(soap, soap->tmpbuf, x, 1);
  17044. r = soap->tmpbuf + 6;
  17045. m = strlen(r);
  17046. }
  17047. }
  17048. }
  17049. /* copy normalized QName into buffer, including the ending blank or NUL */
  17050. #ifdef WITH_FAST
  17051. if ((m && soap_append_lab(soap, r, m))
  17052. || (q && soap_append_lab(soap, q, n - (q - s) + 1)))
  17053. return NULL;
  17054. #else
  17055. k = m + (q ? n - (q - s) + 1 : 0);
  17056. b = (char*)soap_push_block(soap, NULL, k);
  17057. if (!b)
  17058. {
  17059. soap->error = SOAP_EOM;
  17060. return NULL;
  17061. }
  17062. if (soap_memcpy((void*)b, k, (const void*)r, m))
  17063. {
  17064. soap->error = SOAP_EOM;
  17065. return NULL;
  17066. }
  17067. b += m;
  17068. if (q)
  17069. {
  17070. if (soap_memcpy((void*)b, k - m, (const void*)q, n - (q - s) + 1))
  17071. {
  17072. soap->error = SOAP_EOM;
  17073. return NULL;
  17074. }
  17075. b += n - (q - s) + 1;
  17076. }
  17077. #endif
  17078. /* advance to next */
  17079. s += n;
  17080. }
  17081. #ifdef WITH_FAST
  17082. t = soap_strdup(soap, soap->labbuf);
  17083. if (!t)
  17084. soap->error = SOAP_EOM;
  17085. #else
  17086. t = (char*)soap_save_block(soap, NULL, NULL, 0);
  17087. #endif
  17088. }
  17089. return t;
  17090. }
  17091. /******************************************************************************/
  17092. #ifndef WITH_LEAN
  17093. SOAP_FMAC1
  17094. int
  17095. SOAP_FMAC2
  17096. soap_s2wchar(struct soap *soap, const char *s, wchar_t **t, int flag, long minlen, long maxlen, const char *pattern)
  17097. {
  17098. if (s)
  17099. {
  17100. const wchar_t *r = soap_wstring(soap, s, flag, minlen, maxlen, pattern);
  17101. if (r && (*t = soap_wstrdup(soap, r)) == NULL)
  17102. return soap->error = SOAP_EOM;
  17103. }
  17104. return soap->error;
  17105. }
  17106. #endif
  17107. /******************************************************************************/
  17108. #ifndef WITH_COMPAT
  17109. #ifdef __cplusplus
  17110. #ifndef WITH_LEAN
  17111. SOAP_FMAC1
  17112. int
  17113. SOAP_FMAC2
  17114. soap_s2stdwchar(struct soap *soap, const char *s, std::wstring *t, int flag, long minlen, long maxlen, const char *pattern)
  17115. {
  17116. if (s)
  17117. {
  17118. const wchar_t *r = soap_wstring(soap, s, flag, minlen, maxlen, pattern);
  17119. if (r)
  17120. t->assign(r);
  17121. }
  17122. return soap->error;
  17123. }
  17124. #endif
  17125. #endif
  17126. #endif
  17127. /******************************************************************************/
  17128. #ifndef WITH_LEAN
  17129. static const wchar_t*
  17130. soap_wstring(struct soap *soap, const char *s, int flag, long minlen, long maxlen, const char *pattern)
  17131. {
  17132. if (s)
  17133. {
  17134. size_t l;
  17135. soap_wchar c;
  17136. wchar_t *t;
  17137. if (maxlen < 0 && soap->maxlength > 0)
  17138. maxlen = soap->maxlength;
  17139. soap->labidx = 0;
  17140. if ((soap->mode & SOAP_ENC_LATIN))
  17141. {
  17142. wchar_t *r;
  17143. if (soap_append_lab(soap, NULL, sizeof(wchar_t) * (strlen(s) + 1)))
  17144. return NULL;
  17145. r = (wchar_t*)soap->labbuf;
  17146. while (*s)
  17147. *r++ = (wchar_t)*s++;
  17148. }
  17149. else
  17150. {
  17151. /* Convert UTF8 to wchar_t */
  17152. while (*s)
  17153. {
  17154. c = (unsigned char)*s++;
  17155. if (c >= 0x80)
  17156. {
  17157. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  17158. soap_wchar c1, c2, c3;
  17159. c1 = (unsigned char)*s;
  17160. if (c <= 0xC1 || (c1 & 0xC0) != 0x80)
  17161. {
  17162. c = SOAP_UNKNOWN_UNICODE_CHAR;
  17163. }
  17164. else
  17165. {
  17166. ++s;
  17167. c1 &= 0x3F;
  17168. if (c < 0xE0)
  17169. {
  17170. c = (((c & 0x1F) << 6) | c1);
  17171. }
  17172. else
  17173. {
  17174. c2 = (unsigned char)*s;
  17175. if ((c == 0xE0 && c1 < 0x20) || (c2 & 0xC0) != 0x80)
  17176. {
  17177. c = SOAP_UNKNOWN_UNICODE_CHAR;
  17178. }
  17179. else
  17180. {
  17181. ++s;
  17182. c2 &= 0x3F;
  17183. if (c < 0xF0)
  17184. {
  17185. c = (((c & 0x0F) << 12) | (c1 << 6) | c2);
  17186. }
  17187. else
  17188. {
  17189. c3 = (unsigned char)*s;
  17190. if ((c == 0xF0 && c1 < 0x10) || (c == 0xF4 && c1 >= 0x10) || c >= 0xF5 || (c3 & 0xC0) != 0x80)
  17191. {
  17192. c = SOAP_UNKNOWN_UNICODE_CHAR;
  17193. }
  17194. else
  17195. {
  17196. ++s;
  17197. c = (((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | (c3 & 0x3F));
  17198. }
  17199. }
  17200. }
  17201. }
  17202. }
  17203. #else
  17204. soap_wchar c1, c2, c3, c4;
  17205. c1 = (unsigned char)*s;
  17206. if (c1)
  17207. {
  17208. s++;
  17209. c1 &= 0x3F;
  17210. if (c < 0xE0)
  17211. {
  17212. c = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1);
  17213. }
  17214. else
  17215. {
  17216. c2 = (unsigned char)*s;
  17217. if (c2)
  17218. {
  17219. s++;
  17220. c2 &= 0x3F;
  17221. if (c < 0xF0)
  17222. {
  17223. c = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2);
  17224. }
  17225. else
  17226. {
  17227. c3 = (unsigned char)*s;
  17228. if (c3)
  17229. {
  17230. s++;
  17231. c3 &= 0x3F;
  17232. if (c < 0xF8)
  17233. {
  17234. c = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3);
  17235. }
  17236. else
  17237. {
  17238. c4 = (unsigned char)*s;
  17239. if (c4)
  17240. {
  17241. s++;
  17242. c4 &= 0x3F;
  17243. if (c < 0xFC)
  17244. {
  17245. c = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4);
  17246. }
  17247. else
  17248. {
  17249. c = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (unsigned char)(*s & 0x3F));
  17250. if (*s)
  17251. s++;
  17252. }
  17253. }
  17254. }
  17255. }
  17256. }
  17257. }
  17258. }
  17259. }
  17260. #endif
  17261. }
  17262. /* use UTF16 encoding when wchar_t is too small to hold UCS */
  17263. if (sizeof(wchar_t) < 4 && c > 0xFFFF)
  17264. {
  17265. wchar_t c1, c2;
  17266. c1 = 0xD800 - (0x10000 >> 10) + (c >> 10);
  17267. c2 = 0xDC00 + (c & 0x3FF);
  17268. if (soap_append_lab(soap, (const char*)&c1, sizeof(wchar_t)) || soap_append_lab(soap, (const char*)&c2, sizeof(wchar_t)))
  17269. return NULL;
  17270. }
  17271. else if (soap_append_lab(soap, (const char*)&c, sizeof(wchar_t)))
  17272. {
  17273. return NULL;
  17274. }
  17275. }
  17276. }
  17277. l = soap->labidx / sizeof(wchar_t);
  17278. c = L'\0';
  17279. if (soap_append_lab(soap, (const char*)&c, sizeof(wchar_t)))
  17280. return NULL;
  17281. if ((maxlen >= 0 && l > (size_t)maxlen) || (minlen > 0 && l < (size_t)minlen))
  17282. {
  17283. soap->error = SOAP_LENGTH;
  17284. return NULL;
  17285. }
  17286. t = (wchar_t*)soap->labbuf;
  17287. #ifndef WITH_LEAN
  17288. if (flag >= 4 && t)
  17289. t = soap_wcollapse(soap, t, flag, 1);
  17290. #endif
  17291. #ifndef WITH_LEANER
  17292. if (pattern && soap->fwvalidate)
  17293. {
  17294. soap->error = soap->fwvalidate(soap, pattern, t);
  17295. if (soap->error)
  17296. return NULL;
  17297. }
  17298. #endif
  17299. return t;
  17300. }
  17301. return NULL;
  17302. }
  17303. #endif
  17304. /******************************************************************************/
  17305. #ifndef WITH_LEAN
  17306. static wchar_t*
  17307. soap_wcollapse(struct soap *soap, wchar_t *s, int flag, int insitu)
  17308. {
  17309. /* flag 4=normalizedString (replace), 5=token (collapse) */
  17310. wchar_t *t;
  17311. size_t n;
  17312. if (!s)
  17313. return NULL;
  17314. if (flag == 4)
  17315. {
  17316. for (t = s; *t && (!soap_coblank((soap_wchar)*t) || *t == 32); t++)
  17317. continue;
  17318. if (*t)
  17319. {
  17320. /* replace blanks and control char by space */
  17321. if (!insitu)
  17322. s = soap_wstrdup(soap, s);
  17323. if (s)
  17324. for (t = s; *t; t++)
  17325. if (soap_coblank((soap_wchar)*t))
  17326. *t = L' ';
  17327. }
  17328. return s;
  17329. }
  17330. /* collapse white space */
  17331. for (t = s; *t && soap_coblank((soap_wchar)*t); t++)
  17332. continue;
  17333. n = 0;
  17334. while (t[n])
  17335. n++;
  17336. if (insitu && s < t)
  17337. (void)soap_memmove(s, n + 1, t, n + 1);
  17338. else
  17339. s = t;
  17340. if (n > 0)
  17341. {
  17342. if (!soap_coblank((soap_wchar)s[n-1]))
  17343. {
  17344. for (t = s; (*t && !soap_coblank((soap_wchar)*t)) || (*t == 32 && (!t[1] || !soap_coblank((soap_wchar)t[1]))); t++)
  17345. continue;
  17346. if (!*t)
  17347. return s;
  17348. }
  17349. if (!insitu)
  17350. s = soap_wstrdup(soap, s);
  17351. if (s)
  17352. {
  17353. for (t = s; *t; t++)
  17354. {
  17355. if (soap_coblank((soap_wchar)*t))
  17356. {
  17357. wchar_t *r;
  17358. *t = L' ';
  17359. for (r = t + 1; *r && soap_coblank((soap_wchar)*r); r++)
  17360. continue;
  17361. if (r > t + 1)
  17362. (void)soap_memmove(t + 1, sizeof(wchar_t) * (n - (t-s)), r, sizeof(wchar_t) * (n - (r-s) + 1));
  17363. }
  17364. }
  17365. t--;
  17366. if (t >= s && *t == 32)
  17367. *t = L'\0';
  17368. }
  17369. }
  17370. return s;
  17371. }
  17372. #endif
  17373. /******************************************************************************/
  17374. #ifndef WITH_LEAN
  17375. SOAP_FMAC1
  17376. const char*
  17377. SOAP_FMAC2
  17378. soap_wchar2s(struct soap *soap, const wchar_t *s)
  17379. {
  17380. soap_wchar c;
  17381. char *r, *t;
  17382. const wchar_t *q = s;
  17383. size_t n = 0;
  17384. if (!s)
  17385. return NULL;
  17386. while ((c = *q++))
  17387. {
  17388. if (c > 0 && c < 0x80)
  17389. n++;
  17390. else
  17391. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  17392. n += 4;
  17393. #else
  17394. n += 6;
  17395. #endif
  17396. }
  17397. r = t = (char*)soap_malloc(soap, n + 1);
  17398. if (r)
  17399. {
  17400. /* Convert wchar to UTF8 (chars above U+10FFFF are silently converted, but should not be used) */
  17401. while ((c = *s++))
  17402. {
  17403. if (c > 0 && c < 0x80)
  17404. {
  17405. *t++ = (char)c;
  17406. }
  17407. else
  17408. {
  17409. /* check for UTF16 encoding when wchar_t is too small to hold UCS */
  17410. if (sizeof(wchar_t) < 4 && (c & 0xFC00) == 0xD800)
  17411. {
  17412. soap_wchar d = *s;
  17413. if ((d & 0xFC00) == 0xDC00)
  17414. {
  17415. c = ((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000;
  17416. s++;
  17417. }
  17418. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  17419. else
  17420. {
  17421. c = SOAP_UNKNOWN_UNICODE_CHAR; /* Malformed UTF-16 */
  17422. }
  17423. #endif
  17424. }
  17425. if (c < 0x0800)
  17426. {
  17427. *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
  17428. }
  17429. else
  17430. {
  17431. #ifdef WITH_REPLACE_ILLEGAL_UTF8
  17432. if (!((c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF)))
  17433. c = SOAP_UNKNOWN_UNICODE_CHAR;
  17434. #endif
  17435. if (c < 0x010000)
  17436. {
  17437. *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
  17438. }
  17439. else
  17440. {
  17441. if (c < 0x200000)
  17442. {
  17443. *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
  17444. }
  17445. else
  17446. {
  17447. if (c < 0x04000000)
  17448. {
  17449. *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
  17450. }
  17451. else
  17452. {
  17453. *t++ = (char)(0xFC | ((c >> 30) & 0x01));
  17454. *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
  17455. }
  17456. *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
  17457. }
  17458. *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
  17459. }
  17460. *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
  17461. }
  17462. *t++ = (char)(0x80 | (c & 0x3F));
  17463. }
  17464. }
  17465. *t = '\0';
  17466. }
  17467. return r;
  17468. }
  17469. #endif
  17470. /******************************************************************************/
  17471. SOAP_FMAC1
  17472. int
  17473. SOAP_FMAC2
  17474. soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n)
  17475. {
  17476. id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n, NULL);
  17477. if (id < 0)
  17478. return soap->error;
  17479. if (!**p && (soap->mode & SOAP_C_NILSTRING))
  17480. return soap_element_null(soap, tag, id, type);
  17481. if (soap_element_begin_out(soap, tag, id, type)
  17482. || soap_string_out(soap, *p, 0)
  17483. || soap_element_end_out(soap, tag))
  17484. return soap->error;
  17485. return SOAP_OK;
  17486. }
  17487. /******************************************************************************/
  17488. SOAP_FMAC1
  17489. char **
  17490. SOAP_FMAC2
  17491. soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen, const char *pattern)
  17492. {
  17493. (void)type;
  17494. if (soap_element_begin_in(soap, tag, 1, NULL))
  17495. {
  17496. if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
  17497. return NULL;
  17498. soap->error = SOAP_OK;
  17499. }
  17500. if (!p)
  17501. {
  17502. p = (char**)soap_malloc(soap, sizeof(char*));
  17503. if (!p)
  17504. return NULL;
  17505. }
  17506. if (soap->null)
  17507. {
  17508. *p = NULL;
  17509. }
  17510. else if (soap->body)
  17511. {
  17512. *p = soap_string_in(soap, flag, minlen, maxlen, pattern);
  17513. if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), NULL, NULL, NULL, NULL))
  17514. return NULL;
  17515. if (!**p && tag && *tag == '-')
  17516. {
  17517. soap->error = SOAP_NO_TAG;
  17518. return NULL;
  17519. }
  17520. }
  17521. else if (tag && *tag == '-')
  17522. {
  17523. soap->error = SOAP_NO_TAG;
  17524. return NULL;
  17525. }
  17526. else if (*soap->href != '#')
  17527. {
  17528. if (minlen > 0)
  17529. {
  17530. soap->error = SOAP_LENGTH;
  17531. return NULL;
  17532. }
  17533. *p = soap_strdup(soap, SOAP_STR_EOS);
  17534. if (!*p)
  17535. return NULL;
  17536. }
  17537. if (*soap->href == '#')
  17538. p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0, NULL);
  17539. if (soap->body && soap_element_end_in(soap, tag))
  17540. return NULL;
  17541. return p;
  17542. }
  17543. /******************************************************************************/
  17544. #ifndef WITH_LEANER
  17545. SOAP_FMAC1
  17546. int
  17547. SOAP_FMAC2
  17548. soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n)
  17549. {
  17550. id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n, NULL);
  17551. if (id < 0)
  17552. return soap->error;
  17553. if (!**p && (soap->mode & SOAP_C_NILSTRING))
  17554. return soap_element_null(soap, tag, id, type);
  17555. if (soap_element_begin_out(soap, tag, id, type)
  17556. || soap_wstring_out(soap, *p, 0)
  17557. || soap_element_end_out(soap, tag))
  17558. return soap->error;
  17559. return SOAP_OK;
  17560. }
  17561. #endif
  17562. /******************************************************************************/
  17563. #ifndef WITH_LEANER
  17564. SOAP_FMAC1
  17565. wchar_t **
  17566. SOAP_FMAC2
  17567. soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, int flag, long minlen, long maxlen, const char *pattern)
  17568. {
  17569. (void)type;
  17570. if (soap_element_begin_in(soap, tag, 1, NULL))
  17571. {
  17572. if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
  17573. return NULL;
  17574. soap->error = SOAP_OK;
  17575. }
  17576. if (!p)
  17577. {
  17578. p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*));
  17579. if (!p)
  17580. return NULL;
  17581. }
  17582. if (soap->null)
  17583. {
  17584. *p = NULL;
  17585. }
  17586. else if (soap->body)
  17587. {
  17588. *p = soap_wstring_in(soap, flag, minlen, maxlen, pattern);
  17589. if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), NULL, NULL, NULL, NULL))
  17590. return NULL;
  17591. if (!**p && tag && *tag == '-')
  17592. {
  17593. soap->error = SOAP_NO_TAG;
  17594. return NULL;
  17595. }
  17596. }
  17597. else if (tag && *tag == '-')
  17598. {
  17599. soap->error = SOAP_NO_TAG;
  17600. return NULL;
  17601. }
  17602. else if (*soap->href != '#')
  17603. {
  17604. if (minlen > 0)
  17605. {
  17606. soap->error = SOAP_LENGTH;
  17607. return NULL;
  17608. }
  17609. *p = soap_wstrdup(soap, L"");
  17610. }
  17611. if (*soap->href == '#')
  17612. p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0, NULL);
  17613. if (soap->body && soap_element_end_in(soap, tag))
  17614. return NULL;
  17615. return p;
  17616. }
  17617. #endif
  17618. /******************************************************************************/
  17619. #ifndef WITH_LEAN
  17620. #ifdef UNDER_CE
  17621. /* WinCE mktime (based on the mingw-runtime, public domain) */
  17622. #define __FILETIME_to_ll(f) ((long long)(f).dwHighDateTime << 32 | (long long)(f).dwLowDateTime)
  17623. static time_t
  17624. mktime(struct tm *pt)
  17625. {
  17626. SYSTEMTIME s, s1, s2;
  17627. FILETIME f, f1, f2;
  17628. long long diff;
  17629. GetSystemTime(&s1);
  17630. GetLocalTime(&s2);
  17631. SystemTimeToFileTime(&s1, &f1);
  17632. SystemTimeToFileTime(&s2, &f2);
  17633. diff = (__FILETIME_to_ll(f2) - __FILETIME_to_ll(f1)) / 10000000LL;
  17634. s.wYear = pt->tm_year + 1900;
  17635. s.wMonth = pt->tm_mon + 1;
  17636. s.wDayOfWeek = pt->tm_wday;
  17637. s.wDay = pt->tm_mday;
  17638. s.wHour = pt->tm_hour;
  17639. s.wMinute = pt->tm_min;
  17640. s.wSecond = pt->tm_sec;
  17641. s.wMilliseconds = 0;
  17642. SystemTimeToFileTime(&s, &f);
  17643. return (time_t)((__FILETIME_to_ll(f) - 116444736000000000LL) / 10000000LL) - (time_t)diff;
  17644. }
  17645. #endif
  17646. #endif
  17647. /******************************************************************************/
  17648. #ifndef WITH_LEAN
  17649. #ifdef UNDER_CE
  17650. /* WinCE gmtime_r (based on the mingw-runtime, public domain) */
  17651. #define HAVE_GMTIME_R
  17652. static struct tm*
  17653. gmtime_r(const time_t *t, struct tm *pt)
  17654. {
  17655. FILETIME f, f1, f2;
  17656. SYSTEMTIME s, s1 = {0};
  17657. long long time = (long long)(*t) * 10000000LL + 116444736000000000LL;
  17658. f.dwHighDateTime = (DWORD)((time >> 32) & 0x00000000FFFFFFFF);
  17659. f.dwLowDateTime = (DWORD)(time & 0x00000000FFFFFFFF);
  17660. FileTimeToSystemTime(&f, &s);
  17661. pt->tm_year = s.wYear - 1900;
  17662. pt->tm_mon = s.wMonth - 1;
  17663. pt->tm_wday = s.wDayOfWeek;
  17664. pt->tm_mday = s.wDay;
  17665. s1.wYear = s.wYear;
  17666. s1.wMonth = 1;
  17667. s1.wDayOfWeek = 1;
  17668. s1.wDay = 1;
  17669. SystemTimeToFileTime(&s1, &f1);
  17670. SystemTimeToFileTime(&s, &f2);
  17671. pt->tm_yday = (((__FILETIME_to_ll(f2) - __FILETIME_to_ll(f1)) / 10000000LL) / (60 * 60 * 24));
  17672. pt->tm_hour = s.wHour;
  17673. pt->tm_min = s.wMinute;
  17674. pt->tm_sec = s.wSecond;
  17675. pt->tm_isdst = 0;
  17676. return pt;
  17677. }
  17678. #endif
  17679. #endif
  17680. /******************************************************************************/
  17681. #ifndef WITH_LEAN
  17682. #ifdef UNDER_CE
  17683. /* WinCE very simple strftime for format "%Y-%m-%dT%H:%M:%SZ", note: %F and %T not supported by MS */
  17684. static size_t
  17685. strftime(char *buf, size_t len, const char *format, const struct tm *pT)
  17686. {
  17687. (void)len; (void)format;
  17688. #ifndef WITH_NOZONE
  17689. (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);
  17690. #else
  17691. (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);
  17692. #endif
  17693. return len;
  17694. }
  17695. #endif
  17696. #endif
  17697. /******************************************************************************/
  17698. #if !defined(WITH_LEAN) || defined(WITH_COOKIES)
  17699. SOAP_FMAC1
  17700. time_t
  17701. SOAP_FMAC2
  17702. soap_timegm(struct tm *T)
  17703. {
  17704. #if defined(HAVE_TIMEGM)
  17705. return timegm(T);
  17706. #else
  17707. time_t t, g, z;
  17708. struct tm tm;
  17709. #ifndef HAVE_GMTIME_R
  17710. struct tm *tp;
  17711. #endif
  17712. t = mktime(T);
  17713. if (t == (time_t)-1)
  17714. return (time_t)-1;
  17715. #ifdef HAVE_GMTIME_R
  17716. if (gmtime_r(&t, &tm) == SOAP_FUNC_R_ERR)
  17717. return (time_t)-1;
  17718. #else
  17719. tp = gmtime(&t);
  17720. if (!tp)
  17721. return (time_t)-1;
  17722. tm = *tp;
  17723. #endif
  17724. tm.tm_isdst = 0;
  17725. g = mktime(&tm);
  17726. if (g == (time_t)-1)
  17727. return (time_t)-1;
  17728. z = g - t;
  17729. return t - z;
  17730. #endif
  17731. }
  17732. #endif
  17733. /******************************************************************************/
  17734. #ifndef WITH_LEAN
  17735. SOAP_FMAC1
  17736. const char*
  17737. SOAP_FMAC2
  17738. soap_dateTime2s(struct soap *soap, time_t n)
  17739. {
  17740. struct tm T, *pT = &T;
  17741. size_t l = 0;
  17742. #if defined(HAVE_GMTIME_R) && !defined(WITH_NOZONE)
  17743. if (gmtime_r(&n, pT) != SOAP_FUNC_R_ERR)
  17744. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
  17745. #elif defined(HAVE_GMTIME) && !defined(WITH_NOZONE)
  17746. pT = gmtime(&n);
  17747. if (pT)
  17748. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
  17749. #elif (defined(HAVE_TM_GMTOFF) || defined(HAVE_STRUCT_TM_TM_GMTOFF) || defined(HAVE_STRUCT_TM___TM_GMTOFF)) && !defined(WITH_NOZONE)
  17750. #if defined(HAVE_LOCALTIME_R)
  17751. if (localtime_r(&n, pT) != SOAP_FUNC_R_ERR)
  17752. {
  17753. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT);
  17754. if (l)
  17755. {
  17756. (void)soap_memmove(soap->tmpbuf + 23, sizeof(soap->tmpbuf) - 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */
  17757. soap->tmpbuf[22] = ':'; /* 2000-03-01T02:00:00+03:00 */
  17758. }
  17759. }
  17760. #else
  17761. pT = localtime(&n);
  17762. if (pT)
  17763. {
  17764. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT);
  17765. if (l)
  17766. {
  17767. (void)soap_memmove(soap->tmpbuf + 23, sizeof(soap->tmpbuf) - 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */
  17768. soap->tmpbuf[22] = ':'; /* 2000-03-01T02:00:00+03:00 */
  17769. }
  17770. }
  17771. #endif
  17772. #elif defined(HAVE_GETTIMEOFDAY) && !defined(WITH_NOZONE)
  17773. #if defined(HAVE_LOCALTIME_R)
  17774. if (localtime_r(&n, pT) != SOAP_FUNC_R_ERR)
  17775. {
  17776. struct timeval tv;
  17777. struct timezone tz;
  17778. memset((void*)&tz, 0, sizeof(tz));
  17779. gettimeofday(&tv, &tz);
  17780. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
  17781. if (l)
  17782. (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);
  17783. }
  17784. #else
  17785. pT = localtime(&n);
  17786. if (pT)
  17787. {
  17788. struct timeval tv;
  17789. struct timezone tz;
  17790. memset((void*)&tz, 0, sizeof(tz));
  17791. gettimeofday(&tv, &tz);
  17792. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
  17793. if (l)
  17794. (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);
  17795. }
  17796. #endif
  17797. #elif defined(HAVE_FTIME) && !defined(WITH_NOZONE)
  17798. #if defined(HAVE_LOCALTIME_R)
  17799. if (localtime_r(&n, pT) != SOAP_FUNC_R_ERR)
  17800. {
  17801. struct timeb t;
  17802. memset((void*)&t, 0, sizeof(t));
  17803. #ifdef __BORLANDC__
  17804. ::ftime(&t);
  17805. #else
  17806. ftime(&t);
  17807. #endif
  17808. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
  17809. if (l)
  17810. (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, 7), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
  17811. }
  17812. #else
  17813. pT = localtime(&n);
  17814. if (pT)
  17815. {
  17816. struct timeb t;
  17817. memset((void*)&t, 0, sizeof(t));
  17818. #ifdef __BORLANDC__
  17819. ::ftime(&t);
  17820. #else
  17821. ftime(&t);
  17822. #endif
  17823. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
  17824. if (l)
  17825. (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, 7), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
  17826. }
  17827. #endif
  17828. #elif defined(HAVE_LOCALTIME_R)
  17829. if (localtime_r(&n, pT) != SOAP_FUNC_R_ERR)
  17830. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
  17831. #else
  17832. pT = localtime(&n);
  17833. if (pT)
  17834. l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
  17835. #endif
  17836. if (!l)
  17837. soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "1969-12-31T23:59:59Z");
  17838. return soap->tmpbuf;
  17839. }
  17840. #endif
  17841. /******************************************************************************/
  17842. #ifndef WITH_LEAN
  17843. SOAP_FMAC1
  17844. int
  17845. SOAP_FMAC2
  17846. soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n)
  17847. {
  17848. if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  17849. || soap_string_out(soap, soap_dateTime2s(soap, *p), 0))
  17850. return soap->error;
  17851. return soap_element_end_out(soap, tag);
  17852. }
  17853. #endif
  17854. /******************************************************************************/
  17855. #ifndef WITH_LEAN
  17856. SOAP_FMAC1
  17857. int
  17858. SOAP_FMAC2
  17859. soap_s2dateTime(struct soap *soap, const char *s, time_t *p)
  17860. {
  17861. *p = 0;
  17862. if (s)
  17863. {
  17864. char *t;
  17865. unsigned long d;
  17866. struct tm T;
  17867. if (!*s)
  17868. return soap->error = SOAP_EMPTY;
  17869. memset((void*)&T, 0, sizeof(T));
  17870. d = soap_strtoul(s, &t, 10);
  17871. if (*t == '-')
  17872. {
  17873. /* YYYY-MM-DD */
  17874. T.tm_year = (int)d;
  17875. T.tm_mon = (int)soap_strtoul(t + 1, &t, 10);
  17876. T.tm_mday = (int)soap_strtoul(t + 1, &t, 10);
  17877. }
  17878. else if (!(soap->mode & SOAP_XML_STRICT))
  17879. {
  17880. /* YYYYMMDD */
  17881. T.tm_year = (int)(d / 10000);
  17882. T.tm_mon = (int)(d / 100 % 100);
  17883. T.tm_mday = (int)(d % 100);
  17884. }
  17885. else
  17886. {
  17887. return soap->error = SOAP_TYPE;
  17888. }
  17889. if (*t == 'T' || ((*t == 't' || *t == ' ') && !(soap->mode & SOAP_XML_STRICT)))
  17890. {
  17891. d = soap_strtoul(t + 1, &t, 10);
  17892. if (*t == ':')
  17893. {
  17894. /* Thh:mm:ss */
  17895. T.tm_hour = (int)d;
  17896. T.tm_min = (int)soap_strtoul(t + 1, &t, 10);
  17897. T.tm_sec = (int)soap_strtoul(t + 1, &t, 10);
  17898. }
  17899. else if (!(soap->mode & SOAP_XML_STRICT))
  17900. {
  17901. /* Thhmmss */
  17902. T.tm_hour = (int)(d / 10000);
  17903. T.tm_min = (int)(d / 100 % 100);
  17904. T.tm_sec = (int)(d % 100);
  17905. }
  17906. else
  17907. {
  17908. return soap->error = SOAP_TYPE;
  17909. }
  17910. }
  17911. if (T.tm_year == 1)
  17912. T.tm_year = 70;
  17913. else
  17914. T.tm_year -= 1900;
  17915. T.tm_mon--;
  17916. if (*t == '.')
  17917. {
  17918. for (t++; *t; t++)
  17919. if (*t < '0' || *t > '9')
  17920. break;
  17921. }
  17922. if (*t == ' ' && !(soap->mode & SOAP_XML_STRICT))
  17923. t++;
  17924. if (*t)
  17925. {
  17926. #ifndef WITH_NOZONE
  17927. if (*t == '+' || *t == '-')
  17928. {
  17929. int h, m;
  17930. m = (int)soap_strtol(t, &t, 10);
  17931. if (*t == ':')
  17932. {
  17933. /* +hh:mm */
  17934. h = m;
  17935. m = (int)soap_strtol(t + 1, &t, 10);
  17936. if (h < 0)
  17937. m = -m;
  17938. }
  17939. else if (!(soap->mode & SOAP_XML_STRICT))
  17940. {
  17941. /* +hhmm */
  17942. h = m / 100;
  17943. m = m % 100;
  17944. }
  17945. else
  17946. {
  17947. /* +hh */
  17948. h = m;
  17949. m = 0;
  17950. }
  17951. if (*t)
  17952. return soap->error = SOAP_TYPE;
  17953. T.tm_min -= m;
  17954. T.tm_hour -= h;
  17955. /* put hour and min in range */
  17956. T.tm_hour += T.tm_min / 60;
  17957. T.tm_min %= 60;
  17958. if (T.tm_min < 0)
  17959. {
  17960. T.tm_min += 60;
  17961. T.tm_hour--;
  17962. }
  17963. T.tm_mday += T.tm_hour / 24;
  17964. T.tm_hour %= 24;
  17965. if (T.tm_hour < 0)
  17966. {
  17967. T.tm_hour += 24;
  17968. T.tm_mday--;
  17969. }
  17970. /* note: day of the month may be out of range, timegm() handles it */
  17971. }
  17972. else if (*t != 'Z')
  17973. {
  17974. return soap->error = SOAP_TYPE;
  17975. }
  17976. #endif
  17977. *p = soap_timegm(&T);
  17978. }
  17979. else /* no UTC or timezone, so assume we got a localtime */
  17980. {
  17981. T.tm_isdst = -1;
  17982. *p = mktime(&T);
  17983. }
  17984. }
  17985. return soap->error;
  17986. }
  17987. #endif
  17988. /******************************************************************************/
  17989. #ifndef WITH_LEAN
  17990. SOAP_FMAC1
  17991. time_t *
  17992. SOAP_FMAC2
  17993. soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t)
  17994. {
  17995. if (soap_element_begin_in(soap, tag, 0, NULL))
  17996. return NULL;
  17997. if (*soap->type
  17998. && soap_match_tag(soap, soap->type, type)
  17999. && soap_match_tag(soap, soap->type, ":dateTime"))
  18000. {
  18001. soap->error = SOAP_TYPE;
  18002. soap_revert(soap);
  18003. return NULL;
  18004. }
  18005. p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), NULL, NULL, NULL, NULL);
  18006. if (!p)
  18007. return NULL;
  18008. if (*soap->href != '#')
  18009. {
  18010. int err = soap_s2dateTime(soap, soap_value(soap), p);
  18011. if ((soap->body && soap_element_end_in(soap, tag)) || err)
  18012. return NULL;
  18013. }
  18014. else
  18015. {
  18016. p = (time_t*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(time_t), 0, NULL, NULL);
  18017. if (soap->body && soap_element_end_in(soap, tag))
  18018. return NULL;
  18019. }
  18020. return p;
  18021. }
  18022. #endif
  18023. /******************************************************************************/
  18024. SOAP_FMAC1
  18025. int
  18026. SOAP_FMAC2
  18027. soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *type)
  18028. {
  18029. if (tag && *tag != '-')
  18030. if (soap_element_begin_out(soap, tag, 0, type))
  18031. return soap->error;
  18032. if (p && *p)
  18033. if (soap_send(soap, *p)) /* send as-is */
  18034. return soap->error;
  18035. if (tag && *tag != '-')
  18036. return soap_element_end_out(soap, tag);
  18037. return SOAP_OK;
  18038. }
  18039. /******************************************************************************/
  18040. SOAP_FMAC1
  18041. char **
  18042. SOAP_FMAC2
  18043. soap_inliteral(struct soap *soap, const char *tag, char **p)
  18044. {
  18045. if (soap_element_begin_in(soap, tag, 1, NULL))
  18046. {
  18047. if (soap->error != SOAP_NO_TAG || soap_peek(soap) == SOAP_TT)
  18048. return NULL;
  18049. soap->error = SOAP_OK;
  18050. }
  18051. if (!p)
  18052. {
  18053. p = (char**)soap_malloc(soap, sizeof(char*));
  18054. if (!p)
  18055. return NULL;
  18056. }
  18057. if (soap->body || (tag && *tag == '-'))
  18058. {
  18059. if (tag && *tag != '-')
  18060. *p = soap_string_in(soap, -1, -1, -1, NULL);
  18061. else
  18062. *p = soap_string_in(soap, 0, -1, -1, NULL);
  18063. if (!*p)
  18064. return NULL;
  18065. if (!**p && tag && *tag == '-')
  18066. {
  18067. soap->error = SOAP_NO_TAG;
  18068. return NULL;
  18069. }
  18070. }
  18071. else if (soap->null)
  18072. {
  18073. *p = NULL;
  18074. }
  18075. else
  18076. {
  18077. *p = soap_strdup(soap, SOAP_STR_EOS);
  18078. }
  18079. if (soap->body && soap_element_end_in(soap, tag))
  18080. return NULL;
  18081. return p;
  18082. }
  18083. /******************************************************************************/
  18084. #ifndef WITH_LEANER
  18085. SOAP_FMAC1
  18086. int
  18087. SOAP_FMAC2
  18088. soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const char *type)
  18089. {
  18090. if (tag && *tag != '-')
  18091. if (soap_element_begin_out(soap, tag, 0, type))
  18092. return soap->error;
  18093. if (p)
  18094. {
  18095. wchar_t c;
  18096. const wchar_t *s = *p;
  18097. while ((c = *s++))
  18098. {
  18099. if (soap_pututf8(soap, (unsigned long)c)) /* send as-is in UTF8 */
  18100. return soap->error;
  18101. }
  18102. }
  18103. if (tag && *tag != '-')
  18104. return soap_element_end_out(soap, tag);
  18105. return SOAP_OK;
  18106. }
  18107. #endif
  18108. /******************************************************************************/
  18109. #ifndef WITH_LEANER
  18110. SOAP_FMAC1
  18111. wchar_t **
  18112. SOAP_FMAC2
  18113. soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p)
  18114. {
  18115. if (soap_element_begin_in(soap, tag, 1, NULL))
  18116. {
  18117. if (soap->error != SOAP_NO_TAG || soap_peek(soap) == SOAP_TT)
  18118. return NULL;
  18119. soap->error = SOAP_OK;
  18120. }
  18121. if (!p)
  18122. {
  18123. p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*));
  18124. if (!p)
  18125. return NULL;
  18126. }
  18127. if (soap->body)
  18128. {
  18129. if (tag && *tag != '-')
  18130. *p = soap_wstring_in(soap, -1, -1, -1, NULL);
  18131. else
  18132. *p = soap_wstring_in(soap, 0, -1, -1, NULL);
  18133. if (!*p)
  18134. return NULL;
  18135. if (!**p && tag && *tag == '-')
  18136. {
  18137. soap->error = SOAP_NO_TAG;
  18138. return NULL;
  18139. }
  18140. }
  18141. else if (tag && *tag == '-')
  18142. {
  18143. soap->error = SOAP_NO_TAG;
  18144. return NULL;
  18145. }
  18146. else if (soap->null)
  18147. {
  18148. *p = NULL;
  18149. }
  18150. else
  18151. {
  18152. *p = soap_wstrdup(soap, L"");
  18153. }
  18154. if (soap->body && soap_element_end_in(soap, tag))
  18155. return NULL;
  18156. return p;
  18157. }
  18158. #endif
  18159. /******************************************************************************/
  18160. SOAP_FMAC1
  18161. const char *
  18162. SOAP_FMAC2
  18163. soap_value(struct soap *soap)
  18164. {
  18165. size_t i;
  18166. soap_wchar c = 0;
  18167. char *s = soap->tmpbuf;
  18168. if (!soap->body)
  18169. return SOAP_STR_EOS;
  18170. do
  18171. {
  18172. c = soap_get(soap);
  18173. } while (soap_coblank(c));
  18174. for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++)
  18175. {
  18176. if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF)
  18177. break;
  18178. *s++ = (char)c;
  18179. c = soap_get(soap);
  18180. }
  18181. for (s--; i > 0; i--, s--)
  18182. {
  18183. if (!soap_coblank((soap_wchar)*s))
  18184. break;
  18185. }
  18186. s[1] = '\0';
  18187. soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0'; /* appease */
  18188. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf));
  18189. if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF)
  18190. {
  18191. soap_unget(soap, c);
  18192. }
  18193. else
  18194. {
  18195. soap->error = SOAP_LENGTH;
  18196. return NULL;
  18197. }
  18198. #ifdef WITH_DOM
  18199. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  18200. {
  18201. soap->dom->text = soap_strdup(soap, soap->tmpbuf);
  18202. if (!soap->dom->text)
  18203. return NULL;
  18204. }
  18205. #endif
  18206. return soap->tmpbuf; /* return non-null pointer */
  18207. }
  18208. /******************************************************************************/
  18209. #if !defined(WITH_LEANER) || !defined(WITH_NOHTTP)
  18210. SOAP_FMAC1
  18211. int
  18212. SOAP_FMAC2
  18213. soap_getline(struct soap *soap, char *buf, int len)
  18214. {
  18215. char *s = buf;
  18216. int i = len;
  18217. soap_wchar c = 0;
  18218. for (;;)
  18219. {
  18220. while (i > 1)
  18221. {
  18222. c = soap_getchar(soap);
  18223. if (c == '\r' || c == '\n')
  18224. break;
  18225. if ((int)c == EOF)
  18226. return soap->error = SOAP_CHK_EOF;
  18227. *s++ = (char)c;
  18228. i--;
  18229. }
  18230. *s = '\0';
  18231. if (c != '\n')
  18232. c = soap_getchar(soap); /* got \r or something else, now get \n */
  18233. if (c == '\n')
  18234. {
  18235. if (i == len) /* empty line: end of HTTP/MIME header */
  18236. break;
  18237. c = soap_get0(soap);
  18238. if (c != ' ' && c != '\t') /* HTTP line continuation? */
  18239. break;
  18240. }
  18241. else if ((int)c == EOF)
  18242. {
  18243. return soap->error = SOAP_CHK_EOF;
  18244. }
  18245. else if (i <= 1)
  18246. {
  18247. return soap->error = SOAP_HDR;
  18248. }
  18249. }
  18250. return SOAP_OK;
  18251. }
  18252. #endif
  18253. /******************************************************************************/
  18254. static ULONG64
  18255. soap_count_attachments(struct soap *soap)
  18256. {
  18257. #ifndef WITH_LEANER
  18258. struct soap_multipart *content;
  18259. ULONG64 count = soap->count;
  18260. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=" SOAP_ULONG_FORMAT "\n", count));
  18261. if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
  18262. {
  18263. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n"));
  18264. for (content = soap->dime.first; content; content = content->next)
  18265. {
  18266. count += 12 + ((content->size+3)&(~3));
  18267. if (content->id)
  18268. count += ((strlen(content->id)+3)&(~3));
  18269. if (content->type)
  18270. count += ((strlen(content->type)+3)&(~3));
  18271. if (content->options)
  18272. count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3);
  18273. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size));
  18274. }
  18275. }
  18276. if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary)
  18277. {
  18278. size_t n = strlen(soap->mime.boundary);
  18279. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n"));
  18280. for (content = soap->mime.first; content; content = content->next)
  18281. {
  18282. const char *s;
  18283. /* count \r\n--boundary\r\n */
  18284. count += 6 + n;
  18285. /* count Content-Type: ...\r\n */
  18286. if (content->type)
  18287. count += 16 + strlen(content->type);
  18288. /* count Content-Transfer-Encoding: ...\r\n */
  18289. s = soap_code_str(mime_codes, content->encoding);
  18290. if (s)
  18291. count += 29 + strlen(s);
  18292. /* count Content-ID: ...\r\n */
  18293. if (content->id)
  18294. count += 14 + strlen(content->id);
  18295. /* count Content-Location: ...\r\n */
  18296. if (content->location)
  18297. count += 20 + strlen(content->location);
  18298. /* count Content-Description: ...\r\n */
  18299. if (content->description)
  18300. count += 23 + strlen(content->description);
  18301. /* count \r\n...content */
  18302. count += 2 + content->size;
  18303. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size));
  18304. }
  18305. /* count \r\n--boundary-- */
  18306. count += 6 + n;
  18307. }
  18308. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count=" SOAP_ULONG_FORMAT "\n", count));
  18309. return count;
  18310. #else
  18311. return soap->count;
  18312. #endif
  18313. }
  18314. /******************************************************************************/
  18315. #ifndef WITH_LEANER
  18316. static int
  18317. soap_putdimefield(struct soap *soap, const char *s, size_t n)
  18318. {
  18319. if (soap_send_raw(soap, s, n))
  18320. return soap->error;
  18321. return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3);
  18322. }
  18323. #endif
  18324. /******************************************************************************/
  18325. #ifndef WITH_LEANER
  18326. SOAP_FMAC1
  18327. char *
  18328. SOAP_FMAC2
  18329. soap_dime_option(struct soap *soap, unsigned short optype, const char *option)
  18330. {
  18331. size_t n;
  18332. char *s = NULL;
  18333. if (option)
  18334. {
  18335. n = strlen(option);
  18336. s = (char*)soap_malloc(soap, n + 5);
  18337. if (s)
  18338. {
  18339. s[0] = (char)(optype >> 8);
  18340. s[1] = (char)(optype & 0xFF);
  18341. s[2] = (char)(n >> 8);
  18342. s[3] = (char)(n & 0xFF);
  18343. soap_strcpy(s + 4, n + 1, option);
  18344. }
  18345. }
  18346. return s;
  18347. }
  18348. #endif
  18349. /******************************************************************************/
  18350. #ifndef WITH_LEANER
  18351. SOAP_FMAC1
  18352. int
  18353. SOAP_FMAC2
  18354. soap_putdimehdr(struct soap *soap)
  18355. {
  18356. unsigned char tmp[12];
  18357. size_t optlen = 0, idlen = 0, typelen = 0;
  18358. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id ? soap->dime.id : SOAP_STR_EOS));
  18359. if (soap->dime.options)
  18360. optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4;
  18361. if (soap->dime.id)
  18362. {
  18363. idlen = strlen(soap->dime.id);
  18364. if (idlen > 0x0000FFFF)
  18365. idlen = 0x0000FFFF;
  18366. }
  18367. if (soap->dime.type)
  18368. {
  18369. typelen = strlen(soap->dime.type);
  18370. if (typelen > 0x0000FFFF)
  18371. typelen = 0x0000FFFF;
  18372. }
  18373. tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7);
  18374. tmp[1] = soap->dime.flags & 0xF0;
  18375. tmp[2] = (char)(optlen >> 8);
  18376. tmp[3] = (char)(optlen & 0xFF);
  18377. tmp[4] = (char)(idlen >> 8);
  18378. tmp[5] = (char)(idlen & 0xFF);
  18379. tmp[6] = (char)(typelen >> 8);
  18380. tmp[7] = (char)(typelen & 0xFF);
  18381. tmp[8] = (char)(soap->dime.size >> 24);
  18382. tmp[9] = (char)((soap->dime.size >> 16) & 0xFF);
  18383. tmp[10] = (char)((soap->dime.size >> 8) & 0xFF);
  18384. tmp[11] = (char)(soap->dime.size & 0xFF);
  18385. if (soap_send_raw(soap, (char*)tmp, 12)
  18386. || soap_putdimefield(soap, soap->dime.options, optlen)
  18387. || soap_putdimefield(soap, soap->dime.id, idlen)
  18388. || soap_putdimefield(soap, soap->dime.type, typelen))
  18389. return soap->error;
  18390. return SOAP_OK;
  18391. }
  18392. #endif
  18393. /******************************************************************************/
  18394. #ifndef WITH_LEANER
  18395. SOAP_FMAC1
  18396. int
  18397. SOAP_FMAC2
  18398. soap_putdime(struct soap *soap)
  18399. {
  18400. struct soap_multipart *content;
  18401. if (!(soap->mode & SOAP_ENC_DIME))
  18402. return SOAP_OK;
  18403. for (content = soap->dime.first; content; content = content->next)
  18404. {
  18405. void *handle;
  18406. soap->dime.size = content->size;
  18407. soap->dime.id = content->id;
  18408. soap->dime.type = content->type;
  18409. soap->dime.options = content->options;
  18410. soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA;
  18411. if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) != NULL || soap->error))
  18412. {
  18413. size_t size = content->size;
  18414. if (!handle)
  18415. {
  18416. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n"));
  18417. return soap->error;
  18418. }
  18419. if (!size && ((soap->mode & SOAP_ENC_PLAIN) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE))
  18420. {
  18421. size_t chunksize = sizeof(soap->tmpbuf);
  18422. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n"));
  18423. do
  18424. {
  18425. size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize);
  18426. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size));
  18427. if (size < chunksize)
  18428. {
  18429. soap->dime.flags &= ~SOAP_DIME_CF;
  18430. if (!content->next)
  18431. soap->dime.flags |= SOAP_DIME_ME;
  18432. }
  18433. else
  18434. {
  18435. soap->dime.flags |= SOAP_DIME_CF;
  18436. }
  18437. soap->dime.size = size;
  18438. if (soap_putdimehdr(soap)
  18439. || soap_putdimefield(soap, soap->tmpbuf, size))
  18440. break;
  18441. if (soap->dime.id)
  18442. {
  18443. soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA);
  18444. soap->dime.id = NULL;
  18445. soap->dime.type = NULL;
  18446. soap->dime.options = NULL;
  18447. }
  18448. } while (size >= chunksize);
  18449. }
  18450. else
  18451. {
  18452. if (!content->next)
  18453. soap->dime.flags |= SOAP_DIME_ME;
  18454. if (soap_putdimehdr(soap))
  18455. return soap->error;
  18456. do
  18457. {
  18458. size_t bufsize;
  18459. if (size < sizeof(soap->tmpbuf))
  18460. bufsize = size;
  18461. else
  18462. bufsize = sizeof(soap->tmpbuf);
  18463. bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize);
  18464. if (!bufsize)
  18465. {
  18466. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
  18467. soap->error = SOAP_CHK_EOF;
  18468. break;
  18469. }
  18470. if (soap_send_raw(soap, soap->tmpbuf, bufsize))
  18471. break;
  18472. size -= bufsize;
  18473. } while (size);
  18474. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
  18475. if (soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3))
  18476. return soap->error;
  18477. }
  18478. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
  18479. if (soap->fdimereadclose)
  18480. soap->fdimereadclose(soap, handle);
  18481. }
  18482. else
  18483. {
  18484. if (!content->next)
  18485. soap->dime.flags |= SOAP_DIME_ME;
  18486. if (soap_putdimehdr(soap)
  18487. || soap_putdimefield(soap, (char*)content->ptr, content->size))
  18488. return soap->error;
  18489. }
  18490. }
  18491. return SOAP_OK;
  18492. }
  18493. #endif
  18494. /******************************************************************************/
  18495. #ifndef WITH_LEANER
  18496. static char *
  18497. soap_getdimefield(struct soap *soap, size_t n)
  18498. {
  18499. char *p = NULL;
  18500. if (n > 0)
  18501. {
  18502. p = (char*)soap_malloc(soap, n + 1 > n ? n + 1 : n);
  18503. if (p)
  18504. {
  18505. char *s = p;
  18506. size_t i;
  18507. for (i = n; i > 0; i--)
  18508. {
  18509. soap_wchar c = soap_get1(soap);
  18510. if ((int)c == EOF)
  18511. {
  18512. soap->error = SOAP_CHK_EOF;
  18513. return NULL;
  18514. }
  18515. *s++ = (char)c;
  18516. }
  18517. if (n + 1 > n)
  18518. *s = '\0'; /* force NUL terminated */
  18519. soap->error = soap_move(soap, (size_t)(-(long)n&3));
  18520. if (soap->error)
  18521. return NULL;
  18522. }
  18523. else
  18524. {
  18525. soap->error = SOAP_EOM;
  18526. }
  18527. }
  18528. return p;
  18529. }
  18530. #endif
  18531. /******************************************************************************/
  18532. #ifndef WITH_LEANER
  18533. SOAP_FMAC1
  18534. int
  18535. SOAP_FMAC2
  18536. soap_getdimehdr(struct soap *soap)
  18537. {
  18538. soap_wchar c;
  18539. char *s;
  18540. int i;
  18541. unsigned char tmp[12];
  18542. size_t optlen, idlen, typelen;
  18543. if (!(soap->mode & SOAP_ENC_DIME))
  18544. return soap->error = SOAP_DIME_END;
  18545. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n"));
  18546. s = (char*)tmp;
  18547. for (i = 12; i > 0; i--)
  18548. {
  18549. c = soap_getchar(soap);
  18550. if ((int)c == EOF)
  18551. return soap->error = SOAP_CHK_EOF;
  18552. *s++ = (char)c;
  18553. }
  18554. if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION)
  18555. return soap->error = SOAP_DIME_MISMATCH;
  18556. soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0);
  18557. optlen = (tmp[2] << 8) | tmp[3];
  18558. idlen = (tmp[4] << 8) | tmp[5];
  18559. typelen = (tmp[6] << 8) | tmp[7];
  18560. soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
  18561. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags));
  18562. soap->dime.options = soap_getdimefield(soap, optlen);
  18563. if (!soap->dime.options && soap->error)
  18564. return soap->error;
  18565. soap->dime.id = soap_getdimefield(soap, idlen);
  18566. if (!soap->dime.id && soap->error)
  18567. return soap->error;
  18568. soap->dime.type = soap_getdimefield(soap, typelen);
  18569. if (!soap->dime.type && soap->error)
  18570. return soap->error;
  18571. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME flags=%x id='%s', type='%s', options='%s'\n", soap->dime.flags, soap->dime.id ? soap->dime.id : SOAP_STR_EOS, soap->dime.type ? soap->dime.type : "", soap->dime.options ? soap->dime.options+4 : SOAP_STR_EOS));
  18572. if ((soap->dime.flags & SOAP_DIME_ME))
  18573. soap->mode &= ~SOAP_ENC_DIME;
  18574. return SOAP_OK;
  18575. }
  18576. #endif
  18577. /******************************************************************************/
  18578. #ifndef WITH_LEANER
  18579. SOAP_FMAC1
  18580. int
  18581. SOAP_FMAC2
  18582. soap_getdime(struct soap *soap)
  18583. {
  18584. if (soap->dime.buflen || soap->dime.chunksize)
  18585. {
  18586. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip remainder of SOAP in DIME (%u bytes or %u bytes in chunk left)\n", (unsigned int)soap->dime.buflen, (unsigned int)soap->dime.chunksize));
  18587. do
  18588. if (soap_get1(soap) == (int)EOF)
  18589. return soap->error = SOAP_CHK_EOF;
  18590. while (soap->dime.buflen || soap->dime.chunksize);
  18591. if (soap_move(soap, (size_t)(-(long)soap->dime.size&3)))
  18592. return soap->error = SOAP_CHK_EOF;
  18593. if (!(soap->mode & SOAP_ENC_DIME))
  18594. return SOAP_OK;
  18595. }
  18596. else
  18597. {
  18598. if (soap_move(soap, (size_t)(((soap->dime.size+3)&(~3)) - soap_tell(soap))))
  18599. return soap->error = SOAP_CHK_EOF;
  18600. }
  18601. for (;;)
  18602. {
  18603. struct soap_multipart *content;
  18604. if (soap_getdimehdr(soap))
  18605. break;
  18606. if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) != NULL || soap->error))
  18607. {
  18608. const char *id, *type, *options;
  18609. size_t size, n;
  18610. if (!soap->dime.ptr)
  18611. return soap->error;
  18612. id = soap->dime.id;
  18613. type = soap->dime.type;
  18614. options = soap->dime.options;
  18615. for (;;)
  18616. {
  18617. size = soap->dime.size;
  18618. for (;;)
  18619. {
  18620. n = soap->buflen - soap->bufidx;
  18621. if (size < n)
  18622. n = size;
  18623. soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n);
  18624. if (soap->error)
  18625. break;
  18626. size -= n;
  18627. if (!size)
  18628. {
  18629. soap->bufidx += n;
  18630. break;
  18631. }
  18632. if (soap_recv(soap))
  18633. {
  18634. soap->error = SOAP_EOF;
  18635. goto end;
  18636. }
  18637. }
  18638. if (soap_move(soap, (size_t)(-(long)soap->dime.size&3)))
  18639. {
  18640. soap->error = SOAP_EOF;
  18641. break;
  18642. }
  18643. if (!(soap->dime.flags & SOAP_DIME_CF))
  18644. break;
  18645. if (soap_getdimehdr(soap))
  18646. break;
  18647. }
  18648. end:
  18649. if (soap->fdimewriteclose)
  18650. soap->fdimewriteclose(soap, (void*)soap->dime.ptr);
  18651. soap->dime.size = 0;
  18652. soap->dime.id = id;
  18653. soap->dime.type = type;
  18654. soap->dime.options = options;
  18655. }
  18656. else if ((soap->dime.flags & SOAP_DIME_CF))
  18657. {
  18658. const char *id, *type, *options;
  18659. id = soap->dime.id;
  18660. type = soap->dime.type;
  18661. options = soap->dime.options;
  18662. if (soap_alloc_block(soap) == NULL)
  18663. return soap->error = SOAP_EOM;
  18664. for (;;)
  18665. {
  18666. soap_wchar c;
  18667. size_t i;
  18668. char *s;
  18669. if (soap->dime.size > SOAP_MAXDIMESIZE)
  18670. {
  18671. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu exceeds SOAP_MAXDIMESIZE=%lu\n", (unsigned long)soap->dime.size, (unsigned long)SOAP_MAXDIMESIZE));
  18672. return soap->error = SOAP_DIME_ERROR;
  18673. }
  18674. s = (char*)soap_push_block(soap, NULL, soap->dime.size);
  18675. if (!s)
  18676. return soap->error = SOAP_EOM;
  18677. for (i = soap->dime.size; i > 0; i--)
  18678. {
  18679. c = soap_get1(soap);
  18680. if ((int)c == EOF)
  18681. return soap->error = SOAP_EOF;
  18682. *s++ = (char)c;
  18683. }
  18684. if (soap_move(soap, (size_t)(-(long)soap->dime.size&3)))
  18685. return soap->error = SOAP_EOF;
  18686. if (!(soap->dime.flags & SOAP_DIME_CF))
  18687. break;
  18688. if (soap_getdimehdr(soap))
  18689. return soap->error;
  18690. }
  18691. soap->dime.size = soap->blist->size;
  18692. if (soap->dime.size + 1 > soap->dime.size)
  18693. soap->blist->size++; /* allocate one more byte in blist for the terminating '\0' */
  18694. soap->dime.ptr = soap_save_block(soap, NULL, NULL, 0);
  18695. if (!soap->dime.ptr)
  18696. return soap->error;
  18697. if (soap->dime.size + 1 > soap->dime.size)
  18698. soap->dime.ptr[soap->dime.size] = '\0'; /* make 0-terminated, just in case even though this is binary data */
  18699. soap->dime.id = id;
  18700. soap->dime.type = type;
  18701. soap->dime.options = options;
  18702. }
  18703. else
  18704. {
  18705. soap->dime.ptr = soap_getdimefield(soap, soap->dime.size);
  18706. }
  18707. content = soap_alloc_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size);
  18708. if (!content)
  18709. return soap->error = SOAP_EOM;
  18710. content->id = soap->dime.id;
  18711. content->type = soap->dime.type;
  18712. content->options = soap->dime.options;
  18713. if (soap->error)
  18714. return soap->error;
  18715. soap_resolve_attachment(soap, content);
  18716. }
  18717. if (soap->error != SOAP_DIME_END)
  18718. return soap->error;
  18719. return soap->error = SOAP_OK;
  18720. }
  18721. #endif
  18722. /******************************************************************************/
  18723. #ifndef WITH_LEANER
  18724. SOAP_FMAC1
  18725. int
  18726. SOAP_FMAC2
  18727. soap_getmimehdr(struct soap *soap)
  18728. {
  18729. struct soap_multipart *content;
  18730. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get MIME header\n"));
  18731. do
  18732. {
  18733. if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
  18734. return soap->error;
  18735. } while (!*soap->msgbuf);
  18736. if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-')
  18737. {
  18738. char *s = soap->msgbuf + strlen(soap->msgbuf) - 1;
  18739. /* remove white space */
  18740. while (soap_coblank((soap_wchar)*s))
  18741. s--;
  18742. s[1] = '\0';
  18743. if (soap->mime.boundary)
  18744. {
  18745. if (strcmp(soap->msgbuf + 2, soap->mime.boundary))
  18746. return soap->error = SOAP_MIME_ERROR;
  18747. }
  18748. else
  18749. {
  18750. soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2);
  18751. if (!soap->mime.boundary)
  18752. return soap->error = SOAP_EOM;
  18753. }
  18754. if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
  18755. return soap->error;
  18756. }
  18757. if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL))
  18758. return soap->error = SOAP_EOM;
  18759. content = soap->mime.last;
  18760. for (;;)
  18761. {
  18762. char *key = soap->msgbuf;
  18763. char *val;
  18764. if (!*key)
  18765. break;
  18766. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME header: %s\n", key));
  18767. val = strchr(soap->msgbuf, ':');
  18768. if (val)
  18769. {
  18770. *val = '\0';
  18771. do
  18772. {
  18773. val++;
  18774. } while (*val && *val <= 32);
  18775. if (!soap_tag_cmp(key, "Content-ID"))
  18776. content->id = soap_strdup(soap, val);
  18777. else if (!soap_tag_cmp(key, "Content-Location"))
  18778. content->location = soap_strdup(soap, val);
  18779. else if (!content->id && !soap_tag_cmp(key, "Content-Disposition"))
  18780. content->id = soap_strdup(soap, soap_http_header_attribute(soap, val, "name"));
  18781. else if (!soap_tag_cmp(key, "Content-Type"))
  18782. content->type = soap_strdup(soap, val);
  18783. else if (!soap_tag_cmp(key, "Content-Description"))
  18784. content->description = soap_strdup(soap, val);
  18785. else if (!soap_tag_cmp(key, "Content-Transfer-Encoding"))
  18786. content->encoding = (enum soap_mime_encoding)soap_code_int(mime_codes, val, (LONG64)SOAP_MIME_NONE);
  18787. }
  18788. if (soap_getline(soap, key, sizeof(soap->msgbuf)))
  18789. return soap->error;
  18790. }
  18791. return SOAP_OK;
  18792. }
  18793. #endif
  18794. /******************************************************************************/
  18795. #ifndef WITH_LEANER
  18796. SOAP_FMAC1
  18797. int
  18798. SOAP_FMAC2
  18799. soap_getmime(struct soap *soap)
  18800. {
  18801. while (soap_recv_mime_attachment(soap, NULL))
  18802. continue;
  18803. return soap->error;
  18804. }
  18805. #endif
  18806. /******************************************************************************/
  18807. #ifndef WITH_LEANER
  18808. SOAP_FMAC1
  18809. void
  18810. SOAP_FMAC2
  18811. soap_post_check_mime_attachments(struct soap *soap)
  18812. {
  18813. soap->imode |= SOAP_MIME_POSTCHECK;
  18814. }
  18815. #endif
  18816. /******************************************************************************/
  18817. #ifndef WITH_LEANER
  18818. SOAP_FMAC1
  18819. int
  18820. SOAP_FMAC2
  18821. soap_check_mime_attachments(struct soap *soap)
  18822. {
  18823. if ((soap->mode & SOAP_MIME_POSTCHECK))
  18824. return soap_recv_mime_attachment(soap, NULL) != NULL;
  18825. return SOAP_OK;
  18826. }
  18827. #endif
  18828. /******************************************************************************/
  18829. #ifndef WITH_LEANER
  18830. SOAP_FMAC1
  18831. struct soap_multipart *
  18832. SOAP_FMAC2
  18833. soap_recv_mime_attachment(struct soap *soap, void *handle)
  18834. {
  18835. soap_wchar c = 0;
  18836. size_t i, m = 0;
  18837. char *s, *t = NULL;
  18838. struct soap_multipart *content;
  18839. short flag = 0;
  18840. if (!(soap->mode & SOAP_ENC_MIME))
  18841. return NULL;
  18842. content = soap->mime.last;
  18843. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get MIME (%p)\n", (void*)content));
  18844. if (!content)
  18845. {
  18846. if (soap_getmimehdr(soap))
  18847. return NULL;
  18848. content = soap->mime.last;
  18849. }
  18850. else if (content != soap->mime.first)
  18851. {
  18852. if (soap->fmimewriteopen && ((content->ptr = (char*)soap->fmimewriteopen(soap, (void*)handle, content->id, content->type, content->description, content->encoding)) != NULL || soap->error))
  18853. {
  18854. if (!content->ptr)
  18855. return NULL;
  18856. }
  18857. }
  18858. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id='%s' type='%s'\n", content->id ? content->id : SOAP_STR_EOS, content->type ? content->type : SOAP_STR_EOS));
  18859. if (!content->ptr && soap_alloc_block(soap) == NULL)
  18860. {
  18861. soap->error = SOAP_EOM;
  18862. return NULL;
  18863. }
  18864. for (;;)
  18865. {
  18866. if (content->ptr)
  18867. {
  18868. s = soap->tmpbuf;
  18869. }
  18870. else
  18871. {
  18872. s = (char*)soap_push_block(soap, NULL, sizeof(soap->tmpbuf));
  18873. if (!s)
  18874. {
  18875. soap->error = SOAP_EOM;
  18876. return NULL;
  18877. }
  18878. }
  18879. for (i = 0; i < sizeof(soap->tmpbuf); i++)
  18880. {
  18881. if (m > 0)
  18882. {
  18883. *s++ = *t++;
  18884. m--;
  18885. }
  18886. else
  18887. {
  18888. if (!flag)
  18889. {
  18890. c = soap_getchar(soap);
  18891. if ((int)c == EOF)
  18892. {
  18893. if (content->ptr && soap->fmimewriteclose)
  18894. soap->fmimewriteclose(soap, (void*)content->ptr);
  18895. soap->error = SOAP_CHK_EOF;
  18896. return NULL;
  18897. }
  18898. }
  18899. if (flag || c == '\r')
  18900. {
  18901. memset((void*)soap->msgbuf, 0, sizeof(soap->msgbuf));
  18902. soap_strcpy(soap->msgbuf, sizeof(soap->msgbuf), "\n--");
  18903. if (soap->mime.boundary)
  18904. {
  18905. if (soap_strncat(soap->msgbuf, sizeof(soap->msgbuf), soap->mime.boundary, sizeof(soap->msgbuf) - 4))
  18906. {
  18907. soap->error = SOAP_MIME_ERROR;
  18908. return NULL;
  18909. }
  18910. }
  18911. t = soap->msgbuf;
  18912. do
  18913. {
  18914. c = soap_getchar(soap);
  18915. } while (c == *t++);
  18916. if ((int)c == EOF)
  18917. {
  18918. if (content->ptr && soap->fmimewriteclose)
  18919. soap->fmimewriteclose(soap, (void*)content->ptr);
  18920. soap->error = SOAP_CHK_EOF;
  18921. return NULL;
  18922. }
  18923. if (!*--t)
  18924. goto end;
  18925. *t = (char)c;
  18926. flag = (c == '\r');
  18927. m = t - soap->msgbuf + 1 - flag;
  18928. t = soap->msgbuf;
  18929. c = '\r';
  18930. }
  18931. *s++ = (char)c;
  18932. }
  18933. }
  18934. if (content->ptr && soap->fmimewrite)
  18935. {
  18936. soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i);
  18937. if (soap->error)
  18938. break;
  18939. }
  18940. }
  18941. end:
  18942. if (content->ptr)
  18943. {
  18944. if (!soap->error && soap->fmimewrite)
  18945. soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i);
  18946. if (soap->fmimewriteclose)
  18947. soap->fmimewriteclose(soap, (void*)content->ptr);
  18948. if (soap->error)
  18949. return NULL;
  18950. }
  18951. else
  18952. {
  18953. *s = '\0'; /* make 0-terminated, just in case even though this is binary data */
  18954. content->size = soap_size_block(soap, NULL, i + 1) - 1; /* last block with '\0' */
  18955. content->ptr = soap_save_block(soap, NULL, NULL, 0);
  18956. }
  18957. soap_resolve_attachment(soap, content);
  18958. if (c == '-' && soap_getchar(soap) == '-')
  18959. {
  18960. soap->mode &= ~SOAP_ENC_MIME;
  18961. if ((soap->mode & SOAP_MIME_POSTCHECK) && soap_end_recv(soap))
  18962. {
  18963. if (soap->keep_alive == -2) /* special case to keep alive */
  18964. soap->keep_alive = 0;
  18965. soap_closesock(soap);
  18966. return NULL;
  18967. }
  18968. }
  18969. else
  18970. {
  18971. while (c != '\r' && (int)c != EOF && soap_coblank(c))
  18972. c = soap_getchar(soap);
  18973. if (c != '\r' || soap_getchar(soap) != '\n')
  18974. {
  18975. soap->error = SOAP_MIME_ERROR;
  18976. return NULL;
  18977. }
  18978. if (soap_getmimehdr(soap))
  18979. return NULL;
  18980. }
  18981. return content;
  18982. }
  18983. #endif
  18984. /******************************************************************************/
  18985. #ifndef WITH_LEANER
  18986. SOAP_FMAC1
  18987. int
  18988. SOAP_FMAC2
  18989. soap_match_cid(struct soap *soap, const char *s, const char *t)
  18990. {
  18991. size_t n;
  18992. if (!s)
  18993. return 1;
  18994. if (!strcmp(s, t))
  18995. return 0;
  18996. if (!strncmp(s, "cid:", 4))
  18997. s += 4;
  18998. n = strlen(t);
  18999. if (*t == '<')
  19000. {
  19001. t++;
  19002. n -= 2;
  19003. }
  19004. if (!strncmp(s, t, n) && !s[n])
  19005. return 0;
  19006. (void)soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS);
  19007. if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n])
  19008. return 0;
  19009. return 1;
  19010. }
  19011. #endif
  19012. /******************************************************************************/
  19013. /* return UUID "<prefix>xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx" in a temporary buffer */
  19014. SOAP_FMAC1
  19015. const char*
  19016. SOAP_FMAC2
  19017. soap_rand_uuid(struct soap *soap, const char *prefix)
  19018. {
  19019. int r1, r2, r3, r4;
  19020. #ifdef WITH_OPENSSL
  19021. r1 = soap_random;
  19022. r2 = soap_random;
  19023. #else
  19024. size_t i;
  19025. static int k = 0xFACEB00C;
  19026. int lo = k % 127773;
  19027. int hi = k / 127773;
  19028. # if defined(HAVE_GETTIMEOFDAY)
  19029. struct timeval tv;
  19030. gettimeofday(&tv, NULL);
  19031. r1 = 10000000 * tv.tv_sec + tv.tv_usec;
  19032. # elif defined(UNDER_CE)
  19033. r1 = (int)Random();
  19034. # elif !defined(WITH_LEAN)
  19035. r1 = (int)time(NULL);
  19036. # else
  19037. r1 = k;
  19038. # endif
  19039. k = 16807 * lo - 2836 * hi;
  19040. if (k <= 0)
  19041. k += 0x7FFFFFFF;
  19042. r2 = k;
  19043. /* k &= 0x8FFFFFFF; */
  19044. for (i = 0; i < (sizeof(soap->buf) < 16UL ? sizeof(soap->buf) : 16UL); i++)
  19045. r2 += soap->buf[i];
  19046. #endif
  19047. r3 = soap_random;
  19048. r4 = soap_random;
  19049. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), prefix ? strlen(prefix) + 37 : 37), "%s%8.8x-%4.4hx-4%3.3hx-%4.4hx-%4.4hx%8.8x", prefix ? prefix : SOAP_STR_EOS, r1, (short)(r2 >> 16), (short)(((short)r2 >> 4) & 0x0FFF), (short)(((short)(r3 >> 16) & 0x3FFF) | 0x8000), (short)r3, r4);
  19050. return soap->tmpbuf;
  19051. }
  19052. /******************************************************************************/
  19053. #ifndef WITH_LEANER
  19054. static void
  19055. soap_resolve_attachment(struct soap *soap, struct soap_multipart *content)
  19056. {
  19057. if (content->id)
  19058. {
  19059. struct soap_xlist **xp = &soap->xlist;
  19060. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id='%s'\n", content->id));
  19061. while (*xp)
  19062. {
  19063. struct soap_xlist *xq = *xp;
  19064. if (!soap_match_cid(soap, xq->id, content->id))
  19065. {
  19066. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment id='%s' for content id='%s'\n", xq->id, content->id));
  19067. *xp = xq->next;
  19068. *xq->ptr = (unsigned char*)content->ptr;
  19069. *xq->size = (int)content->size;
  19070. *xq->type = (char*)content->type;
  19071. if (content->options)
  19072. *xq->options = (char*)content->options;
  19073. else
  19074. *xq->options = (char*)content->description;
  19075. SOAP_FREE(soap, xq);
  19076. }
  19077. else
  19078. {
  19079. xp = &(*xp)->next;
  19080. }
  19081. }
  19082. }
  19083. }
  19084. #endif
  19085. /******************************************************************************/
  19086. #ifndef WITH_LEANER
  19087. SOAP_FMAC1
  19088. int
  19089. SOAP_FMAC2
  19090. soap_putmimehdr(struct soap *soap, struct soap_multipart *content)
  19091. {
  19092. const char *s;
  19093. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type='%s'\n", content->type ? content->type : SOAP_STR_EOS));
  19094. if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n"))
  19095. return soap->error;
  19096. if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n"))
  19097. return soap->error;
  19098. s = soap_code_str(mime_codes, content->encoding);
  19099. if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n"))
  19100. return soap->error;
  19101. if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n"))
  19102. return soap->error;
  19103. if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n"))
  19104. return soap->error;
  19105. if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n"))
  19106. return soap->error;
  19107. return soap_send_raw(soap, "\r\n", 2);
  19108. }
  19109. #endif
  19110. /******************************************************************************/
  19111. #ifndef WITH_LEANER
  19112. SOAP_FMAC1
  19113. int
  19114. SOAP_FMAC2
  19115. soap_putmime(struct soap *soap)
  19116. {
  19117. struct soap_multipart *content;
  19118. if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary)
  19119. return SOAP_OK;
  19120. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n"));
  19121. for (content = soap->mime.first; content; content = content->next)
  19122. {
  19123. void *handle;
  19124. if (soap->fmimereadopen && ((handle = soap->fmimereadopen(soap, (void*)content->ptr, content->id, content->type, content->description)) != NULL || soap->error))
  19125. {
  19126. size_t size = content->size;
  19127. if (!handle)
  19128. {
  19129. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n"));
  19130. return soap->error;
  19131. }
  19132. if (soap_putmimehdr(soap, content))
  19133. return soap->error;
  19134. if (!size)
  19135. {
  19136. if ((soap->mode & SOAP_ENC_PLAIN) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)
  19137. {
  19138. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n"));
  19139. do
  19140. {
  19141. size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf));
  19142. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long)size));
  19143. if (soap_send_raw(soap, soap->tmpbuf, size))
  19144. break;
  19145. } while (size);
  19146. }
  19147. else
  19148. {
  19149. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n"));
  19150. }
  19151. }
  19152. else
  19153. {
  19154. do
  19155. {
  19156. size_t bufsize;
  19157. if (size < sizeof(soap->tmpbuf))
  19158. bufsize = size;
  19159. else
  19160. bufsize = sizeof(soap->tmpbuf);
  19161. bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize);
  19162. if (!bufsize)
  19163. {
  19164. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
  19165. soap->error = SOAP_EOF;
  19166. break;
  19167. }
  19168. if (soap_send_raw(soap, soap->tmpbuf, bufsize))
  19169. break;
  19170. size -= bufsize;
  19171. } while (size);
  19172. }
  19173. if (soap->fmimereadclose)
  19174. soap->fmimereadclose(soap, handle);
  19175. }
  19176. else
  19177. {
  19178. if (soap_putmimehdr(soap, content)
  19179. || soap_send_raw(soap, content->ptr, content->size))
  19180. return soap->error;
  19181. }
  19182. }
  19183. return soap_send3(soap, "\r\n--", soap->mime.boundary, "--");
  19184. }
  19185. #endif
  19186. /******************************************************************************/
  19187. #ifndef WITH_LEANER
  19188. SOAP_FMAC1
  19189. void
  19190. SOAP_FMAC2
  19191. soap_set_dime(struct soap *soap)
  19192. {
  19193. soap->omode |= SOAP_ENC_DIME;
  19194. soap->dime.first = NULL;
  19195. soap->dime.last = NULL;
  19196. }
  19197. #endif
  19198. /******************************************************************************/
  19199. #ifndef WITH_LEANER
  19200. SOAP_FMAC1
  19201. void
  19202. SOAP_FMAC2
  19203. soap_set_mime(struct soap *soap, const char *boundary, const char *start)
  19204. {
  19205. soap->omode |= SOAP_ENC_MIME;
  19206. soap->mime.first = NULL;
  19207. soap->mime.last = NULL;
  19208. soap->mime.boundary = soap_strdup(soap, boundary);
  19209. soap->mime.start = soap_strdup(soap, start);
  19210. }
  19211. #endif
  19212. /******************************************************************************/
  19213. #ifndef WITH_LEANER
  19214. SOAP_FMAC1
  19215. void
  19216. SOAP_FMAC2
  19217. soap_clr_dime(struct soap *soap)
  19218. {
  19219. soap->omode &= ~SOAP_ENC_DIME;
  19220. soap->dime.first = NULL;
  19221. soap->dime.last = NULL;
  19222. }
  19223. #endif
  19224. /******************************************************************************/
  19225. #ifndef WITH_LEANER
  19226. SOAP_FMAC1
  19227. void
  19228. SOAP_FMAC2
  19229. soap_clr_mime(struct soap *soap)
  19230. {
  19231. soap->omode &= ~SOAP_ENC_MIME;
  19232. soap->mime.first = NULL;
  19233. soap->mime.last = NULL;
  19234. soap->mime.boundary = NULL;
  19235. soap->mime.start = NULL;
  19236. }
  19237. #endif
  19238. /******************************************************************************/
  19239. #ifndef WITH_LEANER
  19240. static int
  19241. soap_begin_attachments(struct soap *soap)
  19242. {
  19243. if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start)
  19244. {
  19245. const char *s;
  19246. if (strlen(soap->mime.boundary) + strlen(soap->mime.start) + 140 > sizeof(soap->tmpbuf))
  19247. return soap->error = SOAP_EOM;
  19248. if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
  19249. {
  19250. s = "application/dime";
  19251. }
  19252. else if (soap->version == 2)
  19253. {
  19254. if ((soap->mode & SOAP_ENC_MTOM))
  19255. s = "application/xop+xml; charset=utf-8; type=\"application/soap+xml\"";
  19256. else
  19257. s = "application/soap+xml; charset=utf-8";
  19258. }
  19259. else if ((soap->mode & SOAP_ENC_MTOM))
  19260. {
  19261. s = "application/xop+xml; charset=utf-8; type=\"text/xml\"";
  19262. }
  19263. else
  19264. {
  19265. s = "text/xml; charset=utf-8";
  19266. }
  19267. (SOAP_SNPRINTF_SAFE(soap->tmpbuf, sizeof(soap->tmpbuf)), "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start);
  19268. if (soap_send(soap, soap->tmpbuf))
  19269. return soap->error;
  19270. }
  19271. if ((soap->mode & SOAP_IO_LENGTH))
  19272. soap->dime.size = (size_t)soap->count; /* DIME in MIME correction, soap->count is small */
  19273. if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME))
  19274. {
  19275. if (soap_putdimehdr(soap))
  19276. return soap->error;
  19277. }
  19278. return SOAP_OK;
  19279. }
  19280. #endif
  19281. /******************************************************************************/
  19282. #ifndef WITH_LEANER
  19283. static int
  19284. soap_end_attachments(struct soap *soap)
  19285. {
  19286. if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
  19287. {
  19288. if (soap->count > 0xFFFFFFFF)
  19289. return soap->error = SOAP_DIME_ERROR;
  19290. soap->dime.size = (size_t)soap->count - soap->dime.size; /* DIME in MIME correction */
  19291. (SOAP_SNPRINTF(soap->id, sizeof(soap->id), strlen(soap->dime_id_format) + 20), soap->dime_id_format, 0);
  19292. soap->dime.id = soap->id;
  19293. if (soap->local_namespaces && soap->local_namespaces[0].id)
  19294. {
  19295. if (soap->local_namespaces[0].out)
  19296. soap->dime.type = (char*)soap->local_namespaces[0].out;
  19297. else
  19298. soap->dime.type = (char*)soap->local_namespaces[0].ns;
  19299. }
  19300. soap->dime.options = NULL;
  19301. soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI;
  19302. if (!soap->dime.first)
  19303. soap->dime.flags |= SOAP_DIME_ME;
  19304. soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + (soap->dime.type ? ((strlen(soap->dime.type)+3)&(~3)) : 0);
  19305. }
  19306. if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
  19307. return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
  19308. return SOAP_OK;
  19309. }
  19310. #endif
  19311. /******************************************************************************/
  19312. #ifndef WITH_LEANER
  19313. static struct soap_multipart*
  19314. soap_alloc_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, const char *ptr, size_t size)
  19315. {
  19316. struct soap_multipart *content;
  19317. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New DIME/MIME attachment %p (%lu)\n", (void*)ptr, (unsigned long)size));
  19318. content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart));
  19319. if (content)
  19320. {
  19321. content->next = NULL;
  19322. content->ptr = ptr;
  19323. content->size = size;
  19324. content->id = NULL;
  19325. content->type = NULL;
  19326. content->options = NULL;
  19327. content->encoding = SOAP_MIME_NONE;
  19328. content->location = NULL;
  19329. content->description = NULL;
  19330. if (!*first)
  19331. *first = content;
  19332. if (*last)
  19333. (*last)->next = content;
  19334. *last = content;
  19335. }
  19336. return content;
  19337. }
  19338. #endif
  19339. /******************************************************************************/
  19340. #ifndef WITH_LEANER
  19341. SOAP_FMAC1
  19342. int
  19343. SOAP_FMAC2
  19344. soap_set_dime_attachment(struct soap *soap, const char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option)
  19345. {
  19346. struct soap_multipart *content = soap_alloc_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size);
  19347. if (!content)
  19348. return SOAP_EOM;
  19349. content->id = soap_strdup(soap, id);
  19350. content->type = soap_strdup(soap, type);
  19351. content->options = soap_dime_option(soap, optype, option);
  19352. return SOAP_OK;
  19353. }
  19354. #endif
  19355. /******************************************************************************/
  19356. #ifndef WITH_LEANER
  19357. SOAP_FMAC1
  19358. int
  19359. SOAP_FMAC2
  19360. soap_set_mime_attachment(struct soap *soap, const char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description)
  19361. {
  19362. struct soap_multipart *content = soap_alloc_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size);
  19363. if (!content)
  19364. return SOAP_EOM;
  19365. content->id = soap_strdup(soap, id);
  19366. content->type = soap_strdup(soap, type);
  19367. content->encoding = encoding;
  19368. content->location = soap_strdup(soap, location);
  19369. content->description = soap_strdup(soap, description);
  19370. return SOAP_OK;
  19371. }
  19372. #endif
  19373. /******************************************************************************/
  19374. #ifndef WITH_LEANER
  19375. SOAP_FMAC1
  19376. struct soap_multipart*
  19377. SOAP_FMAC2
  19378. soap_next_multipart(struct soap_multipart *content)
  19379. {
  19380. if (content)
  19381. return content->next;
  19382. return NULL;
  19383. }
  19384. #endif
  19385. /******************************************************************************/
  19386. #ifndef WITH_LEANER
  19387. static void
  19388. soap_select_mime_boundary(struct soap *soap)
  19389. {
  19390. while (!soap->mime.boundary || soap_valid_mime_boundary(soap))
  19391. {
  19392. char *s = soap->mime.boundary;
  19393. size_t n = 0;
  19394. if (s)
  19395. n = strlen(s);
  19396. if (n < 16)
  19397. {
  19398. n = 64;
  19399. s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1);
  19400. if (!s)
  19401. return;
  19402. }
  19403. *s++ = '=';
  19404. *s++ = '=';
  19405. n -= 4;
  19406. while (n)
  19407. {
  19408. *s++ = soap_base64o[soap_random & 0x3F];
  19409. n--;
  19410. }
  19411. *s++ = '=';
  19412. *s++ = '=';
  19413. *s = '\0';
  19414. }
  19415. if (!soap->mime.start)
  19416. soap->mime.start = "<SOAP-ENV:Envelope>";
  19417. }
  19418. #endif
  19419. /******************************************************************************/
  19420. #ifndef WITH_LEANER
  19421. static int
  19422. soap_valid_mime_boundary(struct soap *soap)
  19423. {
  19424. struct soap_multipart *content;
  19425. size_t k;
  19426. if (soap->fmimeread)
  19427. return SOAP_OK;
  19428. k = strlen(soap->mime.boundary);
  19429. for (content = soap->mime.first; content; content = content->next)
  19430. {
  19431. if (content->ptr && content->size >= k)
  19432. {
  19433. const char *p = (const char*)content->ptr;
  19434. size_t i;
  19435. for (i = 0; i < content->size - k; i++, p++)
  19436. {
  19437. if (!strncmp(p, soap->mime.boundary, k))
  19438. return SOAP_ERR;
  19439. }
  19440. }
  19441. }
  19442. return SOAP_OK;
  19443. }
  19444. #endif
  19445. /******************************************************************************/
  19446. #ifdef WITH_GZIP
  19447. static int
  19448. soap_getgziphdr(struct soap *soap)
  19449. {
  19450. int i;
  19451. soap_wchar c = 0, f = 0;
  19452. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n"));
  19453. for (i = 0; i < 9; i++)
  19454. {
  19455. c = soap_get1(soap);
  19456. if (i == 1 && c == 8)
  19457. soap->z_dict = 0;
  19458. if (i == 2)
  19459. f = c;
  19460. }
  19461. if (f & 0x04) /* FEXTRA */
  19462. {
  19463. i = soap_get1(soap);
  19464. i |= soap_get1(soap) << 8;
  19465. while (i-- > 0)
  19466. {
  19467. if ((int)soap_get1(soap) == EOF)
  19468. return soap->error = SOAP_ZLIB_ERROR;
  19469. }
  19470. }
  19471. if (f & 0x08) /* skip FNAME */
  19472. {
  19473. do
  19474. {
  19475. c = soap_get1(soap);
  19476. } while (c && (int)c != EOF);
  19477. }
  19478. if ((int)c != EOF && (f & 0x10)) /* skip FCOMMENT */
  19479. {
  19480. do
  19481. {
  19482. c = soap_get1(soap);
  19483. } while (c && (int)c != EOF);
  19484. }
  19485. if ((int)c != EOF && (f & 0x02)) /* skip FHCRC (CRC32 is used) */
  19486. {
  19487. c = soap_get1(soap);
  19488. if ((int)c != EOF)
  19489. c = soap_get1(soap);
  19490. }
  19491. if ((int)c == EOF)
  19492. return soap->error = SOAP_ZLIB_ERROR;
  19493. return SOAP_OK;
  19494. }
  19495. #endif
  19496. /******************************************************************************/
  19497. SOAP_FMAC1
  19498. int
  19499. SOAP_FMAC2
  19500. soap_begin_serve(struct soap *soap)
  19501. {
  19502. #ifdef WITH_FASTCGI
  19503. if (FCGI_Accept() < 0)
  19504. {
  19505. soap->error = SOAP_EOF;
  19506. return soap_send_fault(soap);
  19507. }
  19508. #endif
  19509. soap_begin(soap);
  19510. if (soap_begin_recv(soap)
  19511. || soap_envelope_begin_in(soap)
  19512. || soap_recv_header(soap)
  19513. || soap_body_begin_in(soap))
  19514. {
  19515. if (soap->error < SOAP_STOP)
  19516. {
  19517. #ifdef WITH_FASTCGI
  19518. (void)soap_send_fault(soap);
  19519. #else
  19520. return soap_send_fault(soap);
  19521. #endif
  19522. }
  19523. return soap_closesock(soap);
  19524. }
  19525. return SOAP_OK;
  19526. }
  19527. /******************************************************************************/
  19528. SOAP_FMAC1
  19529. int
  19530. SOAP_FMAC2
  19531. soap_begin_recv(struct soap *soap)
  19532. {
  19533. // std::cerr<<"Recieved data Sassan2: "<<soap->buf<<std::endl;
  19534. soap_wchar c;
  19535. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for input from socket=%d/fd=%d\n", (int)soap->socket, soap->recvfd));
  19536. soap->error = SOAP_OK;
  19537. #ifndef WITH_LEANER
  19538. soap->recverror = SOAP_OK;
  19539. #endif
  19540. soap_free_temp(soap);
  19541. soap_set_local_namespaces(soap);
  19542. soap->version = 0; /* don't assume we're parsing SOAP content by default */
  19543. #ifndef WITH_NOIDREF
  19544. soap_free_iht(soap);
  19545. #endif
  19546. if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
  19547. {
  19548. soap->imode &= ~SOAP_IO;
  19549. soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_CHUNK;
  19550. }
  19551. soap->imode &= ~(SOAP_ENC_DIME | SOAP_ENC_MIME | SOAP_ENC_MTOM | SOAP_ENC_ZLIB);
  19552. soap->mode = soap->imode;
  19553. if (!(soap->mode & SOAP_IO_KEEPALIVE))
  19554. soap->keep_alive = 0;
  19555. if (!soap->keep_alive)
  19556. soap->buflen = soap->bufidx = 0;
  19557. soap->null = 0;
  19558. soap->position = 0;
  19559. soap->mustUnderstand = 0;
  19560. soap->shaky = 0;
  19561. soap->ahead = 0;
  19562. soap->peeked = 0;
  19563. soap->level = 0;
  19564. soap->part = SOAP_BEGIN_RECV;
  19565. soap->count = 0;
  19566. soap->length = 0;
  19567. soap->cdata = 0;
  19568. *soap->endpoint = '\0';
  19569. soap->action = NULL;
  19570. soap->header = NULL;
  19571. soap->fault = NULL;
  19572. soap->status = 0;
  19573. soap->fform = NULL;
  19574. soap->body = 1;
  19575. #ifndef WITH_LEANER
  19576. soap->dom = NULL;
  19577. soap->dime.count = 0;
  19578. soap->dime.chunksize = 0;
  19579. soap->dime.buflen = 0;
  19580. soap->dime.list = NULL;
  19581. soap->dime.first = NULL;
  19582. soap->dime.last = NULL;
  19583. soap->mime.list = NULL;
  19584. soap->mime.first = NULL;
  19585. soap->mime.last = NULL;
  19586. soap->mime.boundary = NULL;
  19587. soap->mime.start = NULL;
  19588. #endif
  19589. #ifdef WIN32
  19590. #ifndef UNDER_CE
  19591. #ifndef WITH_FASTCGI
  19592. if (!soap_valid_socket(soap->socket) && !soap->is && soap->recvfd >= 0) /* Set win32 stdin or soap->recvfd to BINARY, e.g. to support DIME */
  19593. #ifdef __BORLANDC__
  19594. setmode(soap->recvfd, _O_BINARY);
  19595. #else
  19596. _setmode(soap->recvfd, _O_BINARY);
  19597. #endif
  19598. #endif
  19599. #endif
  19600. #endif
  19601. #ifdef WITH_ZLIB
  19602. soap->zlib_in = SOAP_ZLIB_NONE;
  19603. soap->zlib_out = SOAP_ZLIB_NONE;
  19604. if (!soap->d_stream)
  19605. {
  19606. soap->d_stream = (z_stream*)SOAP_MALLOC(soap, sizeof(z_stream));
  19607. if (!soap->d_stream)
  19608. return soap->error = SOAP_EOM;
  19609. soap->d_stream->zalloc = Z_NULL;
  19610. soap->d_stream->zfree = Z_NULL;
  19611. soap->d_stream->opaque = Z_NULL;
  19612. soap->d_stream->next_in = Z_NULL;
  19613. soap->d_stream->msg = Z_NULL;
  19614. }
  19615. soap->d_stream->avail_in = 0;
  19616. soap->d_stream->next_out = (Byte*)soap->buf;
  19617. soap->d_stream->avail_out = sizeof(soap->buf);
  19618. soap->z_ratio_in = 1.0;
  19619. #endif
  19620. #ifdef WITH_OPENSSL
  19621. if (soap->ssl)
  19622. ERR_clear_error();
  19623. #endif
  19624. #ifndef WITH_LEAN
  19625. soap->start = (ULONG64)time(NULL);
  19626. #endif
  19627. #ifndef WITH_LEANER
  19628. if (soap->fprepareinitrecv && (soap->error = soap->fprepareinitrecv(soap)) != SOAP_OK)
  19629. return soap->error;
  19630. #endif
  19631. c = soap_getchar(soap);
  19632. #ifdef WITH_GZIP
  19633. if (c == 0x1F)
  19634. {
  19635. if (soap_getgziphdr(soap))
  19636. return soap->error;
  19637. if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK)
  19638. return soap->error = SOAP_ZLIB_ERROR;
  19639. if (soap->z_dict)
  19640. {
  19641. if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
  19642. return soap->error = SOAP_ZLIB_ERROR;
  19643. }
  19644. soap->zlib_state = SOAP_ZLIB_INFLATE;
  19645. soap->mode |= SOAP_ENC_ZLIB;
  19646. soap->zlib_in = SOAP_ZLIB_GZIP;
  19647. soap->z_crc = crc32(0L, NULL, 0);
  19648. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
  19649. if (!soap->z_buf)
  19650. soap->z_buf = (char*)SOAP_MALLOC(soap, sizeof(soap->buf));
  19651. (void)soap_memcpy((void*)soap->z_buf, sizeof(soap->buf), (const void*)soap->buf, sizeof(soap->buf));
  19652. /* should not chunk over plain transport, so why bother to check? */
  19653. /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */
  19654. /* soap->z_buflen = soap->bufidx; */
  19655. /* else */
  19656. soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
  19657. soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx);
  19658. soap->z_buflen = soap->buflen;
  19659. soap->buflen = soap->bufidx;
  19660. c = ' ';
  19661. }
  19662. #endif
  19663. while (soap_coblank(c))
  19664. c = soap_getchar(soap);
  19665. #ifndef WITH_LEANER
  19666. if (c == '-' && soap_get0(soap) == '-')
  19667. {
  19668. soap->mode |= SOAP_ENC_MIME;
  19669. }
  19670. else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20)
  19671. {
  19672. soap->mode |= SOAP_ENC_DIME;
  19673. }
  19674. else
  19675. #endif
  19676. {
  19677. /* skip BOM */
  19678. if (c == 0xEF && soap_get0(soap) == 0xBB)
  19679. {
  19680. soap_get1(soap);
  19681. c = soap_get1(soap);
  19682. if (c == 0xBF)
  19683. {
  19684. soap->mode &= ~SOAP_ENC_LATIN;
  19685. c = soap_getchar(soap);
  19686. }
  19687. else
  19688. {
  19689. c = (0x0F << 12) | (0xBB << 6) | (c & 0x3F); /* UTF-8 */
  19690. }
  19691. }
  19692. else if ((c == 0xFE && soap_get0(soap) == 0xFF) /* UTF-16 BE */
  19693. || (c == 0xFF && soap_get0(soap) == 0xFE)) /* UTF-16 LE */
  19694. {
  19695. return soap->error = SOAP_UTF_ERROR;
  19696. }
  19697. /* skip space */
  19698. while (soap_coblank(c))
  19699. c = soap_getchar(soap);
  19700. }
  19701. if ((int)c == EOF)
  19702. return soap->error = SOAP_CHK_EOF;
  19703. soap_unget(soap, c);
  19704. #ifndef WITH_NOHTTP
  19705. /* if not XML/MIME/DIME/ZLIB, assume HTTP method or status line */
  19706. if (((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB | SOAP_ENC_PLAIN)))
  19707. {
  19708. soap_mode m = soap->imode;
  19709. soap->error = soap->fparse(soap);
  19710. soap->mode = soap->imode; /* if imode is changed, effectuate */
  19711. soap->imode = m; /* restore imode */
  19712. if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
  19713. {
  19714. soap->chunkbuflen = soap->buflen;
  19715. soap->buflen = soap->bufidx;
  19716. soap->chunksize = 0;
  19717. }
  19718. #ifdef WITH_ZLIB
  19719. soap->mode &= ~SOAP_ENC_ZLIB;
  19720. if (soap->zlib_in != SOAP_ZLIB_NONE)
  19721. {
  19722. #ifdef WITH_GZIP
  19723. if (soap->zlib_in != SOAP_ZLIB_DEFLATE)
  19724. {
  19725. c = soap_get1(soap);
  19726. if (c == (int)EOF)
  19727. return soap->error = SOAP_EOF;
  19728. if (c == 0x1F)
  19729. {
  19730. if (soap_getgziphdr(soap))
  19731. return soap->error;
  19732. if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK)
  19733. return soap->error = SOAP_ZLIB_ERROR;
  19734. soap->z_crc = crc32(0L, NULL, 0);
  19735. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
  19736. }
  19737. else
  19738. {
  19739. soap_revget1(soap);
  19740. if (inflateInit(soap->d_stream) != Z_OK)
  19741. return soap->error = SOAP_ZLIB_ERROR;
  19742. soap->zlib_in = SOAP_ZLIB_DEFLATE;
  19743. }
  19744. }
  19745. else
  19746. #endif
  19747. if (inflateInit(soap->d_stream) != Z_OK)
  19748. return soap->error = SOAP_ZLIB_ERROR;
  19749. if (soap->z_dict)
  19750. {
  19751. if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
  19752. return soap->error = SOAP_ZLIB_ERROR;
  19753. }
  19754. soap->zlib_state = SOAP_ZLIB_INFLATE;
  19755. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n"));
  19756. soap->mode |= SOAP_ENC_ZLIB;
  19757. if (!soap->z_buf)
  19758. soap->z_buf = (char*)SOAP_MALLOC(soap, sizeof(soap->buf));
  19759. (void)soap_memcpy((void*)soap->z_buf, sizeof(soap->buf), (const void*)soap->buf, sizeof(soap->buf));
  19760. soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
  19761. soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx);
  19762. soap->z_buflen = soap->buflen;
  19763. soap->buflen = soap->bufidx;
  19764. }
  19765. #endif
  19766. #ifndef WITH_LEANER
  19767. if (soap->fpreparerecv && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK && soap->buflen > soap->bufidx)
  19768. {
  19769. int r;
  19770. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Invoking fpreparerecv\n"));
  19771. r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx);
  19772. if (r)
  19773. return soap->error = r;
  19774. }
  19775. #endif
  19776. if (soap->error && soap->error < SOAP_STOP)
  19777. {
  19778. if (soap->status >= 200 && soap->status < 600)
  19779. {
  19780. const char *s = soap_http_get_body(soap, NULL);
  19781. (void)soap_end_recv(soap);
  19782. if (soap->status >= 300)
  19783. soap->keep_alive = 0; /* to force close */
  19784. return soap_set_receiver_error(soap, "HTTP Error", s, soap->status);
  19785. }
  19786. return soap->error;
  19787. }
  19788. if (!soap->body && soap->status >= 200 && soap->status < 600)
  19789. return soap->error = soap->status; /* client side received HTTP status code */
  19790. if (soap->status > SOAP_POST)
  19791. {
  19792. soap->fform = NULL;
  19793. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Invoking http method handler\n"));
  19794. switch (soap->status)
  19795. {
  19796. case SOAP_GET:
  19797. if (soap_http_skip_body(soap) || soap_end_recv(soap))
  19798. return soap->error;
  19799. soap->error = soap->fget(soap);
  19800. break;
  19801. case SOAP_PUT:
  19802. soap->error = soap->fput(soap);
  19803. break;
  19804. case SOAP_PATCH:
  19805. soap->error = soap->fpatch(soap);
  19806. break;
  19807. case SOAP_DEL:
  19808. if (soap_http_skip_body(soap) || soap_end_recv(soap))
  19809. return soap->error;
  19810. soap->error = soap->fdel(soap);
  19811. break;
  19812. case SOAP_HEAD:
  19813. if (soap_http_skip_body(soap) || soap_end_recv(soap))
  19814. return soap->error;
  19815. soap->error = soap->fhead(soap);
  19816. break;
  19817. case SOAP_OPTIONS:
  19818. if (soap_http_skip_body(soap) || soap_end_recv(soap))
  19819. return soap->error;
  19820. soap->error = soap->fopt(soap);
  19821. break;
  19822. default:
  19823. if (soap_http_skip_body(soap) || soap_end_recv(soap))
  19824. return soap->error;
  19825. return 405;
  19826. }
  19827. if (soap->error == SOAP_OK)
  19828. return soap->error = SOAP_STOP; /* prevents further processing */
  19829. if (soap->error != SOAP_FORM || !soap->fform) /* continue if handler returned SOAP_FORM */
  19830. return soap->error;
  19831. soap->error = SOAP_OK;
  19832. }
  19833. if (soap->fform)
  19834. {
  19835. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Invoking http form handler\n"));
  19836. soap->error = soap->fform(soap);
  19837. if (soap->error == SOAP_OK)
  19838. return soap->error = SOAP_STOP; /* prevents further processing */
  19839. if (soap->status != SOAP_POST || soap->error != 404) /* continue with POST if handler returned HTTP not found */
  19840. return soap->error;
  19841. soap->error = SOAP_OK;
  19842. }
  19843. if (!soap->body)
  19844. return soap->error = SOAP_NO_DATA;
  19845. }
  19846. #endif
  19847. #ifndef WITH_LEANER
  19848. if ((soap->mode & SOAP_ENC_MIME))
  19849. {
  19850. do /* skip preamble */
  19851. {
  19852. c = soap_getchar(soap);
  19853. if ((int)c == EOF)
  19854. return soap->error = SOAP_CHK_EOF;
  19855. } while (c != '-' || soap_get0(soap) != '-');
  19856. soap_unget(soap, c);
  19857. if (soap_getmimehdr(soap))
  19858. return soap->error;
  19859. if (soap->mime.start)
  19860. {
  19861. do
  19862. {
  19863. if (!soap->mime.last->id)
  19864. break;
  19865. if (!soap_match_cid(soap, soap->mime.start, soap->mime.last->id))
  19866. break;
  19867. } while (soap_recv_mime_attachment(soap, NULL));
  19868. }
  19869. if (soap_http_header_attribute(soap, soap->mime.first->type, "application/dime"))
  19870. soap->mode |= SOAP_ENC_DIME;
  19871. }
  19872. if ((soap->mode & SOAP_ENC_DIME))
  19873. {
  19874. if (soap_getdimehdr(soap))
  19875. return soap->error;
  19876. if ((soap->dime.flags & SOAP_DIME_CF))
  19877. {
  19878. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME message\n"));
  19879. soap->dime.chunksize = soap->dime.size;
  19880. if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
  19881. {
  19882. soap->dime.buflen = soap->buflen;
  19883. soap->buflen = soap->bufidx + soap->dime.chunksize;
  19884. }
  19885. else
  19886. {
  19887. soap->dime.chunksize -= soap->buflen - soap->bufidx;
  19888. }
  19889. }
  19890. soap->count = soap->buflen - soap->bufidx;
  19891. if (soap->recv_maxlength && soap->count > soap->recv_maxlength)
  19892. return soap->error = SOAP_EOF;
  19893. }
  19894. #endif
  19895. return SOAP_OK;
  19896. }
  19897. /******************************************************************************/
  19898. SOAP_FMAC1
  19899. int
  19900. SOAP_FMAC2
  19901. soap_envelope_begin_out(struct soap *soap)
  19902. {
  19903. if (soap->version == 0)
  19904. return SOAP_OK;
  19905. soap->part = SOAP_IN_ENVELOPE;
  19906. return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL);
  19907. }
  19908. /******************************************************************************/
  19909. SOAP_FMAC1
  19910. int
  19911. SOAP_FMAC2
  19912. soap_envelope_end_out(struct soap *soap)
  19913. {
  19914. if (soap->version == 0)
  19915. return SOAP_OK;
  19916. if (soap_element_end_out(soap, "SOAP-ENV:Envelope")
  19917. || soap_send_raw(soap, "\r\n", 2)) /* 2.8: always emit \r\n */
  19918. return soap->error;
  19919. soap->part = SOAP_END_ENVELOPE;
  19920. return SOAP_OK;
  19921. }
  19922. /******************************************************************************/
  19923. SOAP_FMAC1
  19924. int
  19925. SOAP_FMAC2
  19926. soap_http_has_body(struct soap *soap)
  19927. {
  19928. return soap->length || (soap->mode & SOAP_ENC_ZLIB) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK;
  19929. }
  19930. /******************************************************************************/
  19931. SOAP_FMAC1
  19932. int
  19933. SOAP_FMAC2
  19934. soap_http_skip_body(struct soap *soap)
  19935. {
  19936. ULONG64 k = soap->length;
  19937. /* check HTTP body, return "" if none */
  19938. if (!k && !(soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK)
  19939. return SOAP_OK;
  19940. /* do not consume DIME or MIME attachments, leave this to soap_end_recv */
  19941. if ((soap->mode & SOAP_ENC_DIME) || (soap->mode & SOAP_ENC_MIME))
  19942. return SOAP_OK;
  19943. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skipping HTTP body (mode=0x%x)\n", soap->mode));
  19944. if (k && !(soap->mode & SOAP_ENC_ZLIB))
  19945. {
  19946. size_t i;
  19947. soap->length = 0;
  19948. for (i = 0; i < k; i++)
  19949. {
  19950. soap_wchar c = soap_get1(soap);
  19951. if ((int)c == EOF)
  19952. break;
  19953. }
  19954. }
  19955. else
  19956. {
  19957. for (;;)
  19958. {
  19959. soap_wchar c = soap_get1(soap);
  19960. if ((int)c == EOF)
  19961. break;
  19962. }
  19963. }
  19964. return SOAP_OK;
  19965. }
  19966. /******************************************************************************/
  19967. SOAP_FMAC1
  19968. char *
  19969. SOAP_FMAC2
  19970. soap_http_get_body(struct soap *soap, size_t *len)
  19971. {
  19972. return soap_http_get_body_prefix(soap, len, NULL);
  19973. }
  19974. /******************************************************************************/
  19975. SOAP_FMAC1
  19976. char *
  19977. SOAP_FMAC2
  19978. soap_http_get_form(struct soap *soap)
  19979. {
  19980. return soap_http_get_body_prefix(soap, NULL, "?");
  19981. }
  19982. /******************************************************************************/
  19983. SOAP_FMAC1
  19984. char *
  19985. SOAP_FMAC2
  19986. soap_http_get_body_prefix(struct soap *soap, size_t *len, const char *prefix)
  19987. {
  19988. char *s;
  19989. ULONG64 k = soap->length;
  19990. size_t n = 0;
  19991. if (!prefix)
  19992. prefix = SOAP_STR_EOS;
  19993. else
  19994. n = strlen(prefix);
  19995. if (len)
  19996. *len = 0;
  19997. /* check HTTP body, return "" if none */
  19998. if (!k && !(soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK)
  19999. return soap_strdup(soap, prefix);
  20000. /* do not consume DIME or MIME attachments, leave this to soap_end_recv */
  20001. if ((soap->mode & SOAP_ENC_DIME) || (soap->mode & SOAP_ENC_MIME))
  20002. return soap_strdup(soap, prefix);
  20003. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing HTTP body, prefixed with '%s' (mode=0x%x)\n", prefix, soap->mode));
  20004. if (k && !(soap->mode & SOAP_ENC_ZLIB))
  20005. {
  20006. char *t;
  20007. soap->length = 0;
  20008. /* http content length != 0 and uncompressed body */
  20009. if ((SOAP_MAXALLOCSIZE != 0 && n + k > SOAP_MAXALLOCSIZE) || n + k > (ULONG64)((size_t)-2))
  20010. {
  20011. soap->error = SOAP_EOM;
  20012. return NULL;
  20013. }
  20014. s = t = (char*)soap_malloc(soap, (size_t)k + n + 1);
  20015. if (s)
  20016. {
  20017. size_t i;
  20018. soap_strcpy(t, n + 1, prefix);
  20019. t += n;
  20020. for (i = 0; i < k; i++)
  20021. {
  20022. soap_wchar c = soap_get1(soap);
  20023. if ((int)c == EOF)
  20024. break;
  20025. *t++ = (char)(c & 0xFF);
  20026. }
  20027. *t = '\0';
  20028. if (len)
  20029. *len = n + i;
  20030. }
  20031. else
  20032. {
  20033. soap->error = SOAP_EOM;
  20034. return NULL;
  20035. }
  20036. }
  20037. else
  20038. {
  20039. size_t i, l = 0;
  20040. if (soap_alloc_block(soap) == NULL)
  20041. return NULL;
  20042. if (n)
  20043. {
  20044. s = (char*)soap_push_block(soap, NULL, n);
  20045. if (!s)
  20046. return NULL;
  20047. soap_strcpy(s, n + 1, prefix);
  20048. l += n;
  20049. }
  20050. for (;;)
  20051. {
  20052. size_t k = SOAP_BLKLEN;
  20053. s = (char*)soap_push_block(soap, NULL, k);
  20054. if (!s)
  20055. return NULL;
  20056. for (i = 0; i < k; i++)
  20057. {
  20058. soap_wchar c;
  20059. l++;
  20060. if (l == 0)
  20061. {
  20062. soap->error = SOAP_EOM;
  20063. return NULL;
  20064. }
  20065. c = soap_get1(soap);
  20066. if ((int)c == EOF)
  20067. goto end;
  20068. *s++ = (char)(c & 0xFF);
  20069. }
  20070. }
  20071. end:
  20072. *s = '\0';
  20073. if (len)
  20074. *len = l - 1;
  20075. soap_size_block(soap, NULL, i + 1);
  20076. s = soap_save_block(soap, NULL, NULL, 0);
  20077. }
  20078. return s;
  20079. }
  20080. /******************************************************************************/
  20081. SOAP_FMAC1
  20082. int
  20083. SOAP_FMAC2
  20084. soap_envelope_begin_in(struct soap *soap)
  20085. {
  20086. soap->part = SOAP_IN_ENVELOPE;
  20087. if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL))
  20088. {
  20089. if (soap->error == SOAP_TAG_MISMATCH)
  20090. {
  20091. if (!soap_element_begin_in(soap, "Envelope", 0, NULL))
  20092. soap->error = SOAP_VERSIONMISMATCH;
  20093. else if (soap->status == 0
  20094. || (soap->status >= 200 && soap->status <= 299)
  20095. || soap->status == 400
  20096. || soap->status == 500)
  20097. return SOAP_OK; /* allow non-SOAP (REST) XML content to be captured */
  20098. soap->error = soap->status;
  20099. }
  20100. else if (soap->status)
  20101. {
  20102. soap->error = soap->status;
  20103. }
  20104. return soap->error;
  20105. }
  20106. soap_version(soap);
  20107. return SOAP_OK;
  20108. }
  20109. /******************************************************************************/
  20110. SOAP_FMAC1
  20111. int
  20112. SOAP_FMAC2
  20113. soap_envelope_end_in(struct soap *soap)
  20114. {
  20115. if (soap->version == 0)
  20116. return SOAP_OK;
  20117. soap->part = SOAP_END_ENVELOPE;
  20118. return soap_element_end_in(soap, "SOAP-ENV:Envelope");
  20119. }
  20120. /******************************************************************************/
  20121. SOAP_FMAC1
  20122. int
  20123. SOAP_FMAC2
  20124. soap_body_begin_out(struct soap *soap)
  20125. {
  20126. if (soap->version == 1)
  20127. soap->encoding = 1;
  20128. #ifndef WITH_LEAN
  20129. if ((soap->mode & SOAP_SEC_WSUID) && soap_set_attr(soap, "wsu:Id", "Body", 1))
  20130. return soap->error;
  20131. #endif
  20132. if (soap->version == 0)
  20133. return SOAP_OK;
  20134. soap->part = SOAP_IN_BODY;
  20135. return soap_element_begin_out(soap, "SOAP-ENV:Body", 0, NULL);
  20136. }
  20137. /******************************************************************************/
  20138. SOAP_FMAC1
  20139. int
  20140. SOAP_FMAC2
  20141. soap_body_end_out(struct soap *soap)
  20142. {
  20143. if (soap->version == 0)
  20144. return SOAP_OK;
  20145. if (soap_element_end_out(soap, "SOAP-ENV:Body"))
  20146. return soap->error;
  20147. soap->part = SOAP_END_BODY;
  20148. return SOAP_OK;
  20149. }
  20150. /******************************************************************************/
  20151. SOAP_FMAC1
  20152. int
  20153. SOAP_FMAC2
  20154. soap_body_begin_in(struct soap *soap)
  20155. {
  20156. if (soap->version == 0)
  20157. return SOAP_OK;
  20158. soap->part = SOAP_IN_BODY;
  20159. if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0, NULL))
  20160. return soap->error;
  20161. if (!soap->body)
  20162. soap->part = SOAP_NO_BODY;
  20163. return SOAP_OK;
  20164. }
  20165. /******************************************************************************/
  20166. SOAP_FMAC1
  20167. int
  20168. SOAP_FMAC2
  20169. soap_body_end_in(struct soap *soap)
  20170. {
  20171. if (soap->version == 0)
  20172. return SOAP_OK;
  20173. if (soap->part == SOAP_NO_BODY)
  20174. return soap->error = SOAP_OK;
  20175. soap->part = SOAP_END_BODY;
  20176. return soap_element_end_in(soap, "SOAP-ENV:Body");
  20177. }
  20178. /******************************************************************************/
  20179. SOAP_FMAC1
  20180. int
  20181. SOAP_FMAC2
  20182. soap_recv_header(struct soap *soap)
  20183. {
  20184. if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH)
  20185. soap->error = SOAP_OK;
  20186. if (soap->error == SOAP_OK && soap->fheader)
  20187. soap->error = soap->fheader(soap);
  20188. return soap->error;
  20189. }
  20190. /******************************************************************************/
  20191. SOAP_FMAC1
  20192. void
  20193. SOAP_FMAC2
  20194. soap_set_endpoint(struct soap *soap, const char *endpoint)
  20195. {
  20196. const char *s, *t;
  20197. size_t i, n;
  20198. soap->endpoint[0] = '\0';
  20199. soap->host[0] = '\0';
  20200. soap->path[0] = '/';
  20201. soap->path[1] = '\0';
  20202. soap->port = 80;
  20203. if (!endpoint || !*endpoint)
  20204. return;
  20205. #ifdef WITH_OPENSSL
  20206. if (!soap_tag_cmp(endpoint, "https:*"))
  20207. soap->port = 443;
  20208. #endif
  20209. soap_strcpy(soap->endpoint, sizeof(soap->endpoint), endpoint);
  20210. s = strchr(endpoint, ':');
  20211. if (s && s[1] == '/' && s[2] == '/')
  20212. s += 3;
  20213. else
  20214. s = endpoint;
  20215. #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
  20216. t = strchr(s, '@');
  20217. if (t && *s != ':' && *s != '@')
  20218. {
  20219. size_t l = t - s + 1;
  20220. char *r = (char*)soap_malloc(soap, l);
  20221. n = s - endpoint;
  20222. if (r)
  20223. {
  20224. s = soap_decode(r, l, s, ":@");
  20225. soap->userid = r;
  20226. soap->passwd = SOAP_STR_EOS;
  20227. if (*s == ':')
  20228. {
  20229. s++;
  20230. if (*s != '@')
  20231. {
  20232. l = t - s + 1;
  20233. r = r + strlen(r) + 1;
  20234. s = soap_decode(r, l, s, "@");
  20235. soap->passwd = r;
  20236. }
  20237. }
  20238. }
  20239. s++;
  20240. soap_strcpy(soap->endpoint + n, sizeof(soap->endpoint) - n, s);
  20241. }
  20242. #endif
  20243. n = strlen(s);
  20244. if (n >= sizeof(soap->host))
  20245. n = sizeof(soap->host) - 1;
  20246. #ifdef WITH_IPV6
  20247. if (s[0] == '[')
  20248. {
  20249. s++;
  20250. for (i = 0; i < n; i++)
  20251. {
  20252. if (s[i] == ']')
  20253. {
  20254. s++;
  20255. --n;
  20256. break;
  20257. }
  20258. soap->host[i] = s[i];
  20259. }
  20260. }
  20261. else
  20262. {
  20263. for (i = 0; i < n; i++)
  20264. {
  20265. soap->host[i] = s[i];
  20266. if (s[i] == '/' || s[i] == ':' || s[i] == '?')
  20267. break;
  20268. }
  20269. }
  20270. #else
  20271. for (i = 0; i < n; i++)
  20272. {
  20273. soap->host[i] = s[i];
  20274. if (s[i] == '/' || s[i] == ':' || s[i] == '?')
  20275. break;
  20276. }
  20277. #endif
  20278. soap->host[i] = '\0';
  20279. if (s[i] == ':')
  20280. {
  20281. soap->port = (int)soap_strtol(s + i + 1, NULL, 10);
  20282. for (i++; i < n; i++)
  20283. if (s[i] == '/')
  20284. break;
  20285. }
  20286. if (i < n && s[i])
  20287. soap_strcpy(soap->path, sizeof(soap->path), s + i);
  20288. if (soap->override_host && *soap->override_host)
  20289. {
  20290. soap_strcpy(soap->host, sizeof(soap->host), soap->override_host);
  20291. if (soap->override_port)
  20292. soap->port = soap->override_port;
  20293. }
  20294. if (soap->userid && !soap->authrealm)
  20295. soap->authrealm = soap->host;
  20296. }
  20297. /******************************************************************************/
  20298. #ifndef WITH_NOHTTP
  20299. SOAP_FMAC1
  20300. int
  20301. SOAP_FMAC2
  20302. soap_GET(struct soap *soap, const char *endpoint, const char *action)
  20303. {
  20304. return soap_connect_command(soap, SOAP_GET, endpoint, action);
  20305. }
  20306. #endif
  20307. /******************************************************************************/
  20308. #ifndef WITH_NOHTTP
  20309. SOAP_FMAC1
  20310. int
  20311. SOAP_FMAC2
  20312. soap_PUT(struct soap *soap, const char *endpoint, const char *action, const char *type)
  20313. {
  20314. soap->http_content = type;
  20315. if ((soap->omode & SOAP_IO) != SOAP_IO_CHUNK)
  20316. {
  20317. soap->omode &= ~SOAP_IO;
  20318. soap->omode |= SOAP_IO_STORE;
  20319. }
  20320. return soap_connect_command(soap, SOAP_PUT, endpoint, action);
  20321. }
  20322. #endif
  20323. /******************************************************************************/
  20324. #ifndef WITH_NOHTTP
  20325. SOAP_FMAC1
  20326. int
  20327. SOAP_FMAC2
  20328. soap_POST(struct soap *soap, const char *endpoint, const char *action, const char *type)
  20329. {
  20330. soap->http_content = type;
  20331. if ((soap->omode & SOAP_IO) != SOAP_IO_CHUNK)
  20332. {
  20333. soap->omode &= ~SOAP_IO;
  20334. soap->omode |= SOAP_IO_STORE;
  20335. }
  20336. return soap_connect_command(soap, SOAP_POST_FILE, endpoint, action);
  20337. }
  20338. #endif
  20339. /******************************************************************************/
  20340. #ifndef WITH_NOHTTP
  20341. SOAP_FMAC1
  20342. int
  20343. SOAP_FMAC2
  20344. soap_PATCH(struct soap *soap, const char *endpoint, const char *action, const char *type)
  20345. {
  20346. soap->http_content = type;
  20347. if ((soap->omode & SOAP_IO) != SOAP_IO_CHUNK)
  20348. {
  20349. soap->omode &= ~SOAP_IO;
  20350. soap->omode |= SOAP_IO_STORE;
  20351. }
  20352. return soap_connect_command(soap, SOAP_PATCH, endpoint, action);
  20353. }
  20354. #endif
  20355. /******************************************************************************/
  20356. #ifndef WITH_NOHTTP
  20357. SOAP_FMAC1
  20358. int
  20359. SOAP_FMAC2
  20360. soap_DELETE(struct soap *soap, const char *endpoint)
  20361. {
  20362. if (soap_connect_command(soap, SOAP_DEL, endpoint, NULL)
  20363. || soap_recv_empty_response(soap))
  20364. return soap_closesock(soap);
  20365. return SOAP_OK;
  20366. }
  20367. #endif
  20368. /******************************************************************************/
  20369. SOAP_FMAC1
  20370. int
  20371. SOAP_FMAC2
  20372. soap_connect(struct soap *soap, const char *endpoint, const char *action)
  20373. {
  20374. return soap_connect_command(soap, SOAP_POST, endpoint, action);
  20375. }
  20376. /******************************************************************************/
  20377. SOAP_FMAC1
  20378. int
  20379. SOAP_FMAC2
  20380. soap_connect_command(struct soap *soap, int http_command, const char *endpoints, const char *action)
  20381. {
  20382. if (endpoints)
  20383. {
  20384. const char *s;
  20385. s = strchr(endpoints, ' ');
  20386. if (s)
  20387. {
  20388. size_t l = strlen(endpoints);
  20389. char *endpoint = NULL;
  20390. if (SOAP_MAXALLOCSIZE == 0 || l <= SOAP_MAXALLOCSIZE)
  20391. endpoint = (char*)SOAP_MALLOC(soap, l + 1);
  20392. if (!endpoint)
  20393. return soap->error = SOAP_EOM;
  20394. for (;;)
  20395. {
  20396. (void)soap_strncpy(endpoint, l + 1, endpoints, s - endpoints);
  20397. endpoint[s - endpoints] = '\0';
  20398. if (soap_try_connect_command(soap, http_command, endpoint, action) != SOAP_TCP_ERROR)
  20399. break;
  20400. if (!*s)
  20401. break;
  20402. soap->error = SOAP_OK;
  20403. while (*s == ' ')
  20404. s++;
  20405. endpoints = s;
  20406. s = strchr(endpoints, ' ');
  20407. if (!s)
  20408. s = endpoints + strlen(endpoints);
  20409. }
  20410. SOAP_FREE(soap, endpoint);
  20411. }
  20412. else
  20413. {
  20414. soap_try_connect_command(soap, http_command, endpoints, action);
  20415. }
  20416. }
  20417. return soap->error;
  20418. }
  20419. /******************************************************************************/
  20420. static int
  20421. soap_try_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action)
  20422. {
  20423. char host[sizeof(soap->host)];
  20424. int port;
  20425. ULONG64 count;
  20426. soap->error = SOAP_OK;
  20427. soap_memcpy(host, sizeof(host), soap->host, sizeof(soap->host)); /* save previous host name: if != then reconnect */
  20428. port = soap->port; /* save previous port to compare */
  20429. soap->status = http_command;
  20430. soap_set_endpoint(soap, endpoint);
  20431. soap->action = soap_strdup(soap, action);
  20432. #ifndef WITH_LEANER
  20433. if (soap->fconnect)
  20434. {
  20435. soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port);
  20436. if (soap->error)
  20437. return soap->error;
  20438. }
  20439. else
  20440. #endif
  20441. if (soap->fopen && *soap->host)
  20442. {
  20443. if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap))
  20444. {
  20445. soap->error = SOAP_OK;
  20446. #ifndef WITH_LEAN
  20447. if (!strncmp(endpoint, "soap.udp:", 9) || !strncmp(endpoint, "udp:", 4))
  20448. {
  20449. soap->omode |= SOAP_IO_UDP;
  20450. }
  20451. else
  20452. #endif
  20453. {
  20454. soap->keep_alive = 0; /* to force close */
  20455. soap->omode &= ~SOAP_IO_UDP; /* to force close */
  20456. }
  20457. soap_closesock(soap);
  20458. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect/reconnect to '%s' host='%s' path='%s' port=%d\n", endpoint?endpoint:"(null)", soap->host, soap->path, soap->port));
  20459. if (!soap->keep_alive || !soap_valid_socket(soap->socket))
  20460. {
  20461. soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port);
  20462. if (!soap_valid_socket(soap->socket) || soap->error)
  20463. {
  20464. if (soap->error)
  20465. return soap->error;
  20466. return soap->error = SOAP_TCP_ERROR;
  20467. }
  20468. soap->keep_alive = -((soap->omode & SOAP_IO_KEEPALIVE) != 0);
  20469. }
  20470. }
  20471. }
  20472. #ifdef WITH_NTLM
  20473. if (soap_ntlm_handshake(soap, SOAP_GET, endpoint, soap->host, soap->port))
  20474. return soap->error;
  20475. #endif
  20476. count = soap_count_attachments(soap);
  20477. if (soap_init_send(soap))
  20478. return soap->error;
  20479. #ifndef WITH_NOHTTP
  20480. if (http_command == SOAP_GET || http_command == SOAP_DEL || http_command == SOAP_HEAD || http_command == SOAP_OPTIONS)
  20481. {
  20482. soap->mode &= ~SOAP_IO;
  20483. soap->mode |= SOAP_IO_BUFFER;
  20484. }
  20485. if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_PLAIN) && endpoint)
  20486. {
  20487. soap_mode k = soap->mode;
  20488. soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
  20489. if ((k & SOAP_IO) != SOAP_IO_FLUSH)
  20490. soap->mode |= SOAP_IO_BUFFER;
  20491. soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count);
  20492. if (soap->error)
  20493. return soap->error;
  20494. if ((k & SOAP_IO) == SOAP_IO_CHUNK)
  20495. {
  20496. if (soap_flush(soap))
  20497. return soap->error;
  20498. }
  20499. soap->mode = k;
  20500. }
  20501. if (http_command == SOAP_GET || http_command == SOAP_DEL || http_command == SOAP_HEAD || http_command == SOAP_OPTIONS)
  20502. return soap_end_send_flush(soap);
  20503. #endif
  20504. #ifndef WITH_LEANER
  20505. if (soap_begin_attachments(soap))
  20506. return soap->error;
  20507. #endif
  20508. return SOAP_OK;
  20509. }
  20510. /******************************************************************************/
  20511. #ifdef WITH_NTLM
  20512. static int
  20513. soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const char *host, int port)
  20514. {
  20515. /* requires libntlm from http://www.nongnu.org/libntlm/ */
  20516. const char *userid = (soap->proxy_userid ? soap->proxy_userid : soap->userid);
  20517. const char *passwd = (soap->proxy_passwd ? soap->proxy_passwd : soap->passwd);
  20518. struct SOAP_ENV__Header *oldheader;
  20519. if (soap->ntlm_challenge && userid && passwd && soap->authrealm)
  20520. {
  20521. tSmbNtlmAuthRequest req;
  20522. tSmbNtlmAuthResponse res;
  20523. tSmbNtlmAuthChallenge ch;
  20524. int k = soap->keep_alive;
  20525. ULONG64 l = soap->length;
  20526. ULONG64 c = soap->count;
  20527. soap_mode m = soap->mode, o = soap->omode;
  20528. int s = soap->status;
  20529. char *a = soap->action;
  20530. short v = soap->version;
  20531. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "NTLM '%s'\n", soap->ntlm_challenge));
  20532. if (!*soap->ntlm_challenge)
  20533. {
  20534. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "NTLM S->C Type 1: received NTLM authentication challenge from server\n"));
  20535. /* S -> C 401 Unauthorized
  20536. WWW-Authenticate: NTLM
  20537. */
  20538. buildSmbNtlmAuthRequest(&req, userid, soap->authrealm);
  20539. soap->ntlm_challenge = soap_s2base64(soap, (unsigned char*)(void*)&req, NULL, SmbLength(&req));
  20540. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "NTLM C->S Type 2: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap->ntlm_challenge));
  20541. /* C -> S GET ...
  20542. Authorization: NTLM TlRMTVNTUAABAAAAA7IAAAoACgApAAAACQAJACAAAABMSUdIVENJVFlVUlNBLU1JTk9S
  20543. */
  20544. soap->omode = SOAP_IO_BUFFER;
  20545. if (soap_init_send(soap))
  20546. return soap->error;
  20547. if (!soap->keep_alive)
  20548. soap->keep_alive = -1; /* client keep alive */
  20549. soap->status = command;
  20550. if (soap->fpost(soap, endpoint, host, port, soap->path, soap->action, 0)
  20551. || soap_end_send_flush(soap))
  20552. return soap->error;
  20553. soap->mode = m;
  20554. soap->keep_alive = k;
  20555. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "NTLM S->C Type 2: waiting on server NTLM response\n"));
  20556. oldheader = soap->header;
  20557. if (soap_begin_recv(soap))
  20558. if (soap->error == SOAP_EOF)
  20559. return soap->error;
  20560. (void)soap_end_recv(soap);
  20561. soap->header = oldheader;
  20562. soap->length = l;
  20563. if (soap->status != 401 && soap->status != 407)
  20564. return soap->error = SOAP_NTLM_ERROR;
  20565. soap->error = SOAP_OK;
  20566. }
  20567. /* S -> C 401 Unauthorized
  20568. WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAU3J2Tm9uY2UAAAAAAAAAAA==
  20569. */
  20570. soap_base642s(soap, soap->ntlm_challenge, (char*)&ch, sizeof(tSmbNtlmAuthChallenge), NULL);
  20571. buildSmbNtlmAuthResponse(&ch, &res, userid, passwd);
  20572. soap->ntlm_challenge = soap_s2base64(soap, (unsigned char*)(void*)&res, NULL, SmbLength(&res));
  20573. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "NTLM C->S Type 3: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap->ntlm_challenge));
  20574. /* C -> S GET ...
  20575. Authorization: NTLM TlRMTVNTUAADAAAAGAAYAHIAAAAYABgAigAAABQAFABAAAAADAAMAFQAAAASABIAYAAAAAAAAACiAAAAAYIAAFUAUgBTAEEALQBNAEkATgBPAFIAWgBhAHAAaABvAGQATABJAEcASABUAEMASQBUAFkArYfKbe/jRoW5xDxHeoxC1gBmfWiS5+iX4OAN4xBKG/IFPwfH3agtPEia6YnhsADT
  20576. */
  20577. soap->userid = NULL;
  20578. soap->passwd = NULL;
  20579. soap->proxy_userid = NULL;
  20580. soap->proxy_passwd = NULL;
  20581. soap->keep_alive = k;
  20582. soap->length = l;
  20583. soap->count = c;
  20584. soap->mode = m;
  20585. soap->omode = o;
  20586. soap->status = s;
  20587. soap->action = a;
  20588. soap->version = v;
  20589. }
  20590. return SOAP_OK;
  20591. }
  20592. #endif
  20593. /******************************************************************************/
  20594. SOAP_FMAC1
  20595. char*
  20596. SOAP_FMAC2
  20597. soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n)
  20598. {
  20599. int i;
  20600. unsigned long m;
  20601. char *p;
  20602. if (!t)
  20603. t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1);
  20604. if (!t)
  20605. return NULL;
  20606. p = t;
  20607. t[0] = '\0';
  20608. if (!s)
  20609. return p;
  20610. for (; n > 2; n -= 3, s += 3)
  20611. {
  20612. m = s[0];
  20613. m = (m << 8) | s[1];
  20614. m = (m << 8) | s[2];
  20615. for (i = 4; i > 0; m >>= 6)
  20616. t[--i] = soap_base64o[m & 0x3F];
  20617. t += 4;
  20618. }
  20619. t[0] = '\0';
  20620. if (n > 0) /* 0 < n <= 2 implies that t[0..4] is allocated (base64 scaling formula) */
  20621. {
  20622. m = 0;
  20623. for (i = 0; i < n; i++)
  20624. m = (m << 8) | *s++;
  20625. for (; i < 3; i++)
  20626. m <<= 8;
  20627. for (i = 4; i > 0; m >>= 6)
  20628. t[--i] = soap_base64o[m & 0x3F];
  20629. for (i = 3; i > n; i--)
  20630. t[i] = '=';
  20631. t[4] = '\0';
  20632. }
  20633. return p;
  20634. }
  20635. /******************************************************************************/
  20636. SOAP_FMAC1
  20637. const char*
  20638. SOAP_FMAC2
  20639. soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n)
  20640. {
  20641. size_t i, j;
  20642. soap_wchar c;
  20643. unsigned long m;
  20644. const char *p;
  20645. if (!s || !*s)
  20646. {
  20647. if (n)
  20648. *n = 0;
  20649. if (soap->error)
  20650. return NULL;
  20651. return SOAP_NON_NULL;
  20652. }
  20653. if (!t)
  20654. {
  20655. l = (strlen(s) + 3) / 4 * 3 + 1; /* space for raw binary and \0 */
  20656. t = (char*)soap_malloc(soap, l);
  20657. }
  20658. if (!t)
  20659. return NULL;
  20660. p = t;
  20661. if (n)
  20662. *n = 0;
  20663. for (i = 0; ; i += 3, l -= 3)
  20664. {
  20665. m = 0;
  20666. j = 0;
  20667. while (j < 4)
  20668. {
  20669. c = *s++;
  20670. if (c == '=' || !c)
  20671. {
  20672. if (l >= j - 1)
  20673. {
  20674. switch (j)
  20675. {
  20676. case 2:
  20677. *t++ = (char)((m >> 4) & 0xFF);
  20678. i++;
  20679. l--;
  20680. break;
  20681. case 3:
  20682. *t++ = (char)((m >> 10) & 0xFF);
  20683. *t++ = (char)((m >> 2) & 0xFF);
  20684. i += 2;
  20685. l -= 2;
  20686. }
  20687. }
  20688. if (n)
  20689. *n = (int)i;
  20690. if (l)
  20691. *t = '\0';
  20692. return p;
  20693. }
  20694. c -= '+';
  20695. if (c >= 0 && c <= 79)
  20696. {
  20697. int b = soap_base64i[c];
  20698. if (b >= 64)
  20699. {
  20700. soap->error = SOAP_TYPE;
  20701. return NULL;
  20702. }
  20703. m = (m << 6) + b;
  20704. j++;
  20705. }
  20706. else if (!soap_coblank(c + '+'))
  20707. {
  20708. soap->error = SOAP_TYPE;
  20709. return NULL;
  20710. }
  20711. }
  20712. if (l < 3)
  20713. {
  20714. if (n)
  20715. *n = (int)i;
  20716. if (l)
  20717. *t = '\0';
  20718. return p;
  20719. }
  20720. *t++ = (char)((m >> 16) & 0xFF);
  20721. *t++ = (char)((m >> 8) & 0xFF);
  20722. *t++ = (char)(m & 0xFF);
  20723. }
  20724. }
  20725. /******************************************************************************/
  20726. SOAP_FMAC1
  20727. char*
  20728. SOAP_FMAC2
  20729. soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n)
  20730. {
  20731. char *p;
  20732. if (!t)
  20733. t = (char*)soap_malloc(soap, 2 * n + 1);
  20734. if (!t)
  20735. return NULL;
  20736. p = t;
  20737. t[0] = '\0';
  20738. if (s)
  20739. {
  20740. for (; n > 0; n--)
  20741. {
  20742. int m = *s++;
  20743. *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0'));
  20744. m &= 0x0F;
  20745. *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0'));
  20746. }
  20747. }
  20748. *t++ = '\0';
  20749. return p;
  20750. }
  20751. /******************************************************************************/
  20752. SOAP_FMAC1
  20753. const char*
  20754. SOAP_FMAC2
  20755. soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n)
  20756. {
  20757. const char *p;
  20758. if (!s || !*s)
  20759. {
  20760. if (n)
  20761. *n = 0;
  20762. if (soap->error)
  20763. return NULL;
  20764. return SOAP_NON_NULL;
  20765. }
  20766. if (!t)
  20767. {
  20768. l = strlen(s) / 2 + 1; /* make sure enough space for \0 */
  20769. t = (char*)soap_malloc(soap, l);
  20770. }
  20771. if (!t)
  20772. return NULL;
  20773. p = t;
  20774. while (l)
  20775. {
  20776. int d1, d2;
  20777. d1 = *s++;
  20778. if (!d1)
  20779. break;
  20780. d2 = *s++;
  20781. if (!d2)
  20782. break;
  20783. *t++ = (char)(((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'));
  20784. l--;
  20785. }
  20786. if (n)
  20787. *n = (int)(t - p);
  20788. if (l)
  20789. *t = '\0';
  20790. return p;
  20791. }
  20792. /******************************************************************************/
  20793. #ifndef WITH_NOHTTP
  20794. SOAP_FMAC1
  20795. const char *
  20796. SOAP_FMAC2
  20797. soap_http_content_type(struct soap *soap, int status)
  20798. {
  20799. if (soap->status != SOAP_GET && soap->status != SOAP_DEL && soap->status != SOAP_CONNECT)
  20800. {
  20801. const char *s = "text/xml; charset=utf-8";
  20802. #ifndef WITH_LEANER
  20803. const char *r = NULL;
  20804. size_t n;
  20805. #endif
  20806. if (((status >= SOAP_FILE && status < SOAP_FILE + 600) || soap->status == SOAP_PUT || soap->status == SOAP_POST_FILE || soap->status == SOAP_PATCH) && soap->http_content && *soap->http_content && !strchr(soap->http_content, 10) && !strchr(soap->http_content, 13))
  20807. s = soap->http_content;
  20808. else if (status == SOAP_HTML)
  20809. s = "text/html; charset=utf-8";
  20810. else if (soap->version == 2)
  20811. s = "application/soap+xml; charset=utf-8";
  20812. soap->http_content = NULL; /* use http_content once (assign new value before each call) */
  20813. #ifndef WITH_LEANER
  20814. if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM))
  20815. {
  20816. if ((soap->mode & SOAP_ENC_MTOM))
  20817. {
  20818. if (soap->version == 2)
  20819. r = "application/soap+xml";
  20820. else
  20821. r = "text/xml";
  20822. s = "application/xop+xml";
  20823. }
  20824. else
  20825. {
  20826. s = "application/dime";
  20827. }
  20828. }
  20829. if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary)
  20830. {
  20831. const char *t;
  20832. size_t l;
  20833. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(soap->mime.boundary) + 53), "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary);
  20834. t = strchr(s, ';');
  20835. if (t)
  20836. n = t - s;
  20837. else
  20838. n = strlen(s);
  20839. l = strlen(soap->tmpbuf);
  20840. if (sizeof(soap->tmpbuf) > l + n)
  20841. (void)soap_strncpy(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, s, n);
  20842. if (soap->mime.start)
  20843. {
  20844. l = strlen(soap->tmpbuf);
  20845. (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, strlen(soap->mime.start) + 10), "\"; start=\"%s", soap->mime.start);
  20846. }
  20847. if (r)
  20848. {
  20849. l = strlen(soap->tmpbuf);
  20850. (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, strlen(r) + 15), "\"; start-info=\"%s", r);
  20851. }
  20852. l = strlen(soap->tmpbuf);
  20853. if (sizeof(soap->tmpbuf) > l)
  20854. soap_strcpy(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, "\"");
  20855. }
  20856. else
  20857. {
  20858. soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), s);
  20859. }
  20860. if (status == SOAP_OK && soap->version == 2 && soap->action)
  20861. {
  20862. size_t l = strlen(soap->tmpbuf);
  20863. n = strlen(soap->action);
  20864. (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, n + 11), "; action=\"%s\"", soap->action);
  20865. }
  20866. #else
  20867. soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), s);
  20868. #endif
  20869. return soap->tmpbuf;
  20870. }
  20871. return NULL;
  20872. }
  20873. #endif
  20874. /******************************************************************************/
  20875. #ifndef WITH_NOHTTP
  20876. SOAP_FMAC1
  20877. int
  20878. SOAP_FMAC2
  20879. soap_puthttphdr(struct soap *soap, int status, ULONG64 count)
  20880. {
  20881. int err = SOAP_OK;
  20882. if (soap_http_content_type(soap, status))
  20883. {
  20884. err = soap->fposthdr(soap, "Content-Type", soap->tmpbuf);
  20885. if (err)
  20886. return err;
  20887. #ifdef WITH_ZLIB
  20888. if ((soap->omode & SOAP_ENC_ZLIB))
  20889. {
  20890. #ifdef WITH_GZIP
  20891. err = soap->fposthdr(soap, "Content-Encoding", soap->zlib_out == SOAP_ZLIB_DEFLATE ? "deflate" : "gzip");
  20892. #else
  20893. err = soap->fposthdr(soap, "Content-Encoding", "deflate");
  20894. #endif
  20895. if (err)
  20896. return err;
  20897. }
  20898. #endif
  20899. #ifndef WITH_LEANER
  20900. if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)
  20901. {
  20902. err = soap->fposthdr(soap, "Transfer-Encoding", "chunked");
  20903. }
  20904. else
  20905. #endif
  20906. {
  20907. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), SOAP_ULONG_FORMAT, count);
  20908. err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf);
  20909. }
  20910. if (err)
  20911. return err;
  20912. }
  20913. if (soap->http_extra_header)
  20914. {
  20915. err = soap_send(soap, soap->http_extra_header);
  20916. soap->http_extra_header = NULL; /* use http_extra_header once (assign new value before each call) */
  20917. if (err)
  20918. return err;
  20919. err = soap_send_raw(soap, "\r\n", 2);
  20920. if (err)
  20921. return err;
  20922. }
  20923. if (soap->keep_alive)
  20924. {
  20925. if (soap->keep_alive > 0 && soap->recv_timeout)
  20926. {
  20927. int t = soap->recv_timeout;
  20928. if (t < 0)
  20929. t = 1;
  20930. (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), "timeout=%d, max=%d", soap->recv_timeout, soap->keep_alive);
  20931. err = soap->fposthdr(soap, "Keep-Alive", soap->tmpbuf);
  20932. if (err)
  20933. return err;
  20934. }
  20935. return soap->fposthdr(soap, "Connection", "keep-alive");
  20936. }
  20937. return soap->fposthdr(soap, "Connection", "close");
  20938. }
  20939. #endif
  20940. /******************************************************************************/
  20941. #ifndef WITH_LEAN
  20942. static const char*
  20943. soap_set_validation_fault(struct soap *soap, const char *s, const char *t)
  20944. {
  20945. if (!t)
  20946. t = SOAP_STR_EOS;
  20947. if (*soap->tag)
  20948. (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(s) + strlen(t) + strlen(soap->tag) + 47), "Validation constraint violation: %s%s in element '%s'", s, t, soap->tag);
  20949. else
  20950. (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(s) + strlen(t) + 33), "Validation constraint violation: %s%s", s, t);
  20951. return soap->msgbuf;
  20952. }
  20953. #endif
  20954. /******************************************************************************/
  20955. SOAP_FMAC1
  20956. void
  20957. SOAP_FMAC2
  20958. soap_set_fault(struct soap *soap)
  20959. {
  20960. const char **c;
  20961. const char **s;
  20962. if (soap->version == 0)
  20963. soap_version(soap);
  20964. c = soap_faultcode(soap);
  20965. s = soap_faultstring(soap);
  20966. if (soap->fseterror)
  20967. soap->fseterror(soap, c, s);
  20968. if (!*c)
  20969. {
  20970. if (soap->version == 2)
  20971. *c = "SOAP-ENV:Sender";
  20972. else if (soap->version == 1)
  20973. *c = "SOAP-ENV:Client";
  20974. else
  20975. *c = "";
  20976. }
  20977. if (*s)
  20978. return;
  20979. if (soap->error >= SOAP_POST)
  20980. soap->error = SOAP_HTTP_METHOD;
  20981. switch (soap->error)
  20982. {
  20983. #ifndef WITH_LEAN
  20984. case SOAP_CLI_FAULT:
  20985. *s = "Client fault";
  20986. break;
  20987. case SOAP_SVR_FAULT:
  20988. *s = "Server fault";
  20989. break;
  20990. case SOAP_TAG_MISMATCH:
  20991. *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL);
  20992. break;
  20993. case SOAP_TYPE:
  20994. if (*soap->type)
  20995. *s = soap_set_validation_fault(soap, "type mismatch ", soap->type);
  20996. else if (*soap->arrayType)
  20997. *s = soap_set_validation_fault(soap, "array type mismatch", NULL);
  20998. else
  20999. *s = soap_set_validation_fault(soap, "invalid value", NULL);
  21000. break;
  21001. case SOAP_SYNTAX_ERROR:
  21002. *s = soap_set_validation_fault(soap, "syntax error", NULL);
  21003. break;
  21004. case SOAP_NO_TAG:
  21005. if (soap->version == 0 && soap->level == 0)
  21006. *s = soap_set_validation_fault(soap, "root element expected", NULL);
  21007. else if (soap->level == 0)
  21008. *s = soap_set_validation_fault(soap, "SOAP message expected", NULL);
  21009. else
  21010. *s = soap_set_validation_fault(soap, "element tag expected", NULL);
  21011. break;
  21012. case SOAP_END_TAG:
  21013. *s = soap_set_validation_fault(soap, "closing tag expected", NULL);
  21014. break;
  21015. case SOAP_MUSTUNDERSTAND:
  21016. *c = "SOAP-ENV:MustUnderstand";
  21017. (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(soap->tag) + 65), "The data in element '%s' must be understood but cannot be processed, Sassan %s", soap->tag,debug);
  21018. *s = soap->msgbuf;
  21019. break;
  21020. case SOAP_VERSIONMISMATCH:
  21021. *c = "SOAP-ENV:VersionMismatch";
  21022. *s = "Invalid SOAP message or SOAP version mismatch";
  21023. break;
  21024. case SOAP_DATAENCODINGUNKNOWN:
  21025. *c = "SOAP-ENV:DataEncodingUnknown";
  21026. *s = "Unsupported SOAP data encoding";
  21027. break;
  21028. case SOAP_NAMESPACE:
  21029. *s = soap_set_validation_fault(soap, "namespace error", NULL);
  21030. break;
  21031. case SOAP_USER_ERROR:
  21032. *s = "User data access error";
  21033. break;
  21034. case SOAP_NO_METHOD:
  21035. (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(soap->tag) + 66), "Method '%s' not implemented: method name or namespace not recognized", soap->tag);
  21036. *s = soap->msgbuf;
  21037. break;
  21038. case SOAP_NO_DATA:
  21039. *s = "Data required for operation";
  21040. break;
  21041. case SOAP_GET_METHOD:
  21042. *s = "HTTP GET method not implemented";
  21043. break;
  21044. case SOAP_PUT_METHOD:
  21045. *s = "HTTP PUT method not implemented";
  21046. break;
  21047. case SOAP_PATCH_METHOD:
  21048. *s = "HTTP PATCH method not implemented";
  21049. break;
  21050. case SOAP_DEL_METHOD:
  21051. *s = "HTTP DELETE method not implemented";
  21052. break;
  21053. case SOAP_HTTP_METHOD:
  21054. *s = "HTTP method error";
  21055. break;
  21056. case SOAP_EOM:
  21057. *s = "Out of memory";
  21058. break;
  21059. case SOAP_MOE:
  21060. *s = "Memory overflow or memory corruption error";
  21061. break;
  21062. case SOAP_HDR:
  21063. *s = "Header line too long";
  21064. break;
  21065. case SOAP_IOB:
  21066. *s = "Array index out of bounds";
  21067. break;
  21068. case SOAP_NULL:
  21069. *s = soap_set_validation_fault(soap, "nil not allowed", NULL);
  21070. break;
  21071. case SOAP_DUPLICATE_ID:
  21072. *s = soap_set_validation_fault(soap, "multiple elements (use the SOAP_XML_TREE flag) with duplicate id ", soap->id);
  21073. if (soap->version == 2)
  21074. *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID";
  21075. break;
  21076. case SOAP_MISSING_ID:
  21077. *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id);
  21078. if (soap->version == 2)
  21079. *soap_faultsubcode(soap) = "SOAP-ENC:MissingID";
  21080. break;
  21081. case SOAP_HREF:
  21082. *s = soap_set_validation_fault(soap, "incompatible object type id-ref ", soap->id);
  21083. break;
  21084. case SOAP_FAULT:
  21085. break;
  21086. #ifndef WITH_NOIO
  21087. case SOAP_UDP_ERROR:
  21088. *s = "Message too large for UDP packet";
  21089. break;
  21090. case SOAP_TCP_ERROR:
  21091. *s = tcp_error(soap);
  21092. break;
  21093. #endif
  21094. case SOAP_HTTP_ERROR:
  21095. *s = "An HTTP processing error occurred";
  21096. break;
  21097. case SOAP_NTLM_ERROR:
  21098. *s = "An HTTP NTLM authentication error occurred";
  21099. break;
  21100. case SOAP_SSL_ERROR:
  21101. #ifdef WITH_OPENSSL
  21102. *s = "SSL/TLS error";
  21103. #else
  21104. *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL";
  21105. #endif
  21106. break;
  21107. case SOAP_PLUGIN_ERROR:
  21108. *s = "Plugin registry error";
  21109. break;
  21110. case SOAP_DIME_ERROR:
  21111. *s = "DIME format error or max DIME size exceeds SOAP_MAXDIMESIZE currently set to " SOAP_XSTRINGIFY(SOAP_MAXDIMESIZE);
  21112. break;
  21113. case SOAP_DIME_HREF:
  21114. *s = "DIME href to missing attachment";
  21115. break;
  21116. case SOAP_DIME_MISMATCH:
  21117. *s = "DIME version/transmission error";
  21118. break;
  21119. case SOAP_DIME_END:
  21120. *s = "End of DIME error";
  21121. break;
  21122. case SOAP_MIME_ERROR:
  21123. *s = "MIME format error";
  21124. break;
  21125. case SOAP_MIME_HREF:
  21126. *s = "MIME href to missing attachment";
  21127. break;
  21128. case SOAP_MIME_END:
  21129. *s = "End of MIME error";
  21130. break;
  21131. case SOAP_ZLIB_ERROR:
  21132. #ifdef WITH_ZLIB
  21133. (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);
  21134. *s = soap->msgbuf;
  21135. #else
  21136. *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP";
  21137. #endif
  21138. break;
  21139. case SOAP_REQUIRED:
  21140. *s = soap_set_validation_fault(soap, "missing required attribute", NULL);
  21141. break;
  21142. case SOAP_PROHIBITED:
  21143. *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL);
  21144. break;
  21145. case SOAP_LEVEL:
  21146. *s = "Maximum XML nesting depth level exceeded: increase maxlevel";
  21147. break;
  21148. case SOAP_LENGTH:
  21149. *s = soap_set_validation_fault(soap, "value range or content length violation", NULL);
  21150. break;
  21151. case SOAP_OCCURS:
  21152. *s = soap_set_validation_fault(soap, "occurrence constraint violation", NULL);
  21153. break;
  21154. case SOAP_FIXED:
  21155. *s = soap_set_validation_fault(soap, "value does not match the fixed value required", NULL);
  21156. break;
  21157. case SOAP_EMPTY:
  21158. *s = soap_set_validation_fault(soap, "empty value provided where a value is required", NULL);
  21159. break;
  21160. case SOAP_FD_EXCEEDED:
  21161. *s = "Maximum number of open connections was reached: increase FD_SETSIZE or define HAVE_POLL";
  21162. break;
  21163. case SOAP_UTF_ERROR:
  21164. *s = "UTF content encoding error";
  21165. break;
  21166. case SOAP_STOP:
  21167. *s = "Stopped: service request already handled by plugin (informative)";
  21168. break;
  21169. #endif
  21170. case SOAP_EOF:
  21171. #ifndef WITH_NOIO
  21172. *s = soap_strerror(soap); /* *s = soap->msgbuf */
  21173. #ifndef WITH_LEAN
  21174. if (strlen(soap->msgbuf) + 25 < sizeof(soap->msgbuf))
  21175. {
  21176. (void)soap_memmove((void*)(soap->msgbuf + 25), sizeof(soap->tmpbuf) - 25, (const void*)soap->msgbuf, strlen(soap->msgbuf) + 1);
  21177. if (soap->is)
  21178. #if defined(__cplusplus) && !defined(WITH_COMPAT)
  21179. (void)soap_memcpy((void*)soap->msgbuf, sizeof(soap->msgbuf), (const void*)"End or bad std::istream: ", 25);
  21180. #else
  21181. (void)soap_memcpy((void*)soap->msgbuf, sizeof(soap->msgbuf), (const void*)"End at NUL buffer input: ", 25);
  21182. #endif
  21183. else
  21184. (void)soap_memcpy((void*)soap->msgbuf, sizeof(soap->msgbuf), (const void*)"End of file or no input: ", 25);
  21185. }
  21186. #endif
  21187. break;
  21188. #else
  21189. *s = "End of file or no input";
  21190. break;
  21191. #endif
  21192. case SOAP_ERR:
  21193. *s = "An unspecified error occurred";
  21194. break;
  21195. default:
  21196. #ifndef WITH_NOHTTP
  21197. #ifndef WITH_LEAN
  21198. if (soap->error >= 200 && soap->error < 600)
  21199. {
  21200. const char *t = http_error(soap, soap->error);
  21201. (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(t) + 54), "Error %d: HTTP %d %s", soap->error, soap->error, t);
  21202. *s = soap->msgbuf;
  21203. }
  21204. else
  21205. #endif
  21206. #endif
  21207. {
  21208. (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), 26), "Error %d", soap->error);
  21209. *s = soap->msgbuf;
  21210. }
  21211. }
  21212. }
  21213. /******************************************************************************/
  21214. SOAP_FMAC1
  21215. int
  21216. SOAP_FMAC2
  21217. soap_send_fault(struct soap *soap)
  21218. {
  21219. int status = soap->error;
  21220. if (status == SOAP_OK || status == SOAP_STOP)
  21221. return soap_closesock(soap);
  21222. #ifndef WITH_NOHTTP
  21223. if (status >= 200 && status <= 299)
  21224. return soap_send_empty_response(soap, status);
  21225. #endif
  21226. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error));
  21227. soap->keep_alive = 0; /* error: close connection later by disabling keep-alive here */
  21228. soap_set_fault(soap);
  21229. if (soap->error < 200 && soap->error != SOAP_FAULT)
  21230. soap->header = NULL;
  21231. if (status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout))
  21232. {
  21233. int r = 1;
  21234. #ifndef WITH_NOIO
  21235. if (soap->fpoll && soap->fpoll(soap))
  21236. {
  21237. r = 0;
  21238. }
  21239. #ifndef WITH_LEAN
  21240. else if (soap_valid_socket(soap->socket))
  21241. {
  21242. r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_SND, 0);
  21243. if (r > 0)
  21244. {
  21245. int t;
  21246. if (!(r & SOAP_TCP_SELECT_SND)
  21247. || ((r & SOAP_TCP_SELECT_RCV)
  21248. && recv(soap->socket, (char*)&t, 1, MSG_PEEK) < 0))
  21249. r = 0;
  21250. }
  21251. }
  21252. #endif
  21253. #endif
  21254. if (r > 0)
  21255. {
  21256. soap->error = SOAP_OK;
  21257. if (soap->version > 0)
  21258. {
  21259. soap->encodingStyle = NULL; /* no encodingStyle in Faults */
  21260. soap_serializeheader(soap);
  21261. soap_serializefault(soap);
  21262. (void)soap_begin_count(soap);
  21263. if ((soap->mode & SOAP_IO_LENGTH))
  21264. {
  21265. if (soap_envelope_begin_out(soap)
  21266. || soap_putheader(soap)
  21267. || soap_body_begin_out(soap)
  21268. || soap_putfault(soap)
  21269. || soap_body_end_out(soap)
  21270. || soap_envelope_end_out(soap))
  21271. return soap_closesock(soap);
  21272. }
  21273. (void)soap_end_count(soap);
  21274. if (soap_response(soap, status)
  21275. || soap_envelope_begin_out(soap)
  21276. || soap_putheader(soap)
  21277. || soap_body_begin_out(soap)
  21278. || soap_putfault(soap)
  21279. || soap_body_end_out(soap)
  21280. || soap_envelope_end_out(soap)
  21281. || soap_end_send(soap))
  21282. return soap_closesock(soap);
  21283. }
  21284. else
  21285. {
  21286. const char *s = *soap_faultstring(soap);
  21287. const char **d = soap_faultdetail(soap);
  21288. (void)soap_begin_count(soap);
  21289. if ((soap->mode & SOAP_IO_LENGTH))
  21290. if (soap_element_begin_out(soap, "fault", 0, NULL)
  21291. || soap_outstring(soap, "reason", 0, (char*const*)&s, NULL, 0)
  21292. || soap_outliteral(soap, "detail", (char*const*)d, NULL)
  21293. || soap_element_end_out(soap, "fault"))
  21294. return soap_closesock(soap);
  21295. (void)soap_end_count(soap);
  21296. if (soap_response(soap, status)
  21297. || soap_element_begin_out(soap, "fault", 0, NULL)
  21298. || soap_outstring(soap, "reason", 0, (char*const*)&s, NULL, 0)
  21299. || soap_outliteral(soap, "detail", (char*const*)d, NULL)
  21300. || soap_element_end_out(soap, "fault")
  21301. || soap_end_send(soap))
  21302. return soap_closesock(soap);
  21303. }
  21304. }
  21305. }
  21306. soap->error = status;
  21307. return soap_closesock(soap);
  21308. }
  21309. /******************************************************************************/
  21310. SOAP_FMAC1
  21311. int
  21312. SOAP_FMAC2
  21313. soap_recv_fault(struct soap *soap, int check)
  21314. {
  21315. int status = soap->status;
  21316. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Check (%d) if receiving SOAP Fault (status = %d)\n", check, status));
  21317. if (!check)
  21318. {
  21319. /* try getfault when no tag or tag mismatched at level 2, otherwise close and return SOAP_TAG_MISMATCH or HTTP error code */
  21320. if (soap->error != SOAP_NO_TAG && (soap->error != SOAP_TAG_MISMATCH || soap->level != 2))
  21321. {
  21322. if (soap->error == SOAP_TAG_MISMATCH && soap->level == 0)
  21323. {
  21324. soap->error = SOAP_OK;
  21325. if (!soap_element_begin_in(soap, "fault", 0, NULL))
  21326. {
  21327. char *s = NULL, *d = NULL;
  21328. (void)soap_instring(soap, "reason", &s, NULL, 0, 1, 0, -1, NULL);
  21329. (void)soap_inliteral(soap, "detail", &d);
  21330. if (!soap_element_end_in(soap, "fault") && !soap_end_recv(soap))
  21331. {
  21332. *soap_faultstring(soap) = s;
  21333. *soap_faultdetail(soap) = d;
  21334. if (status)
  21335. soap->error = status;
  21336. else
  21337. soap->error = SOAP_FAULT;
  21338. soap_set_fault(soap);
  21339. return soap_closesock(soap);
  21340. }
  21341. }
  21342. soap->error = SOAP_TAG_MISMATCH;
  21343. }
  21344. if (status && (status < 200 || status > 299))
  21345. soap->error = status;
  21346. return soap_closesock(soap);
  21347. }
  21348. }
  21349. soap->error = SOAP_OK;
  21350. if (soap_getfault(soap))
  21351. {
  21352. /* if check>0 and no SOAP Fault is present and no HTTP error then just return to parse request */
  21353. if (check
  21354. && (status == 0 || (status >= 200 && status <= 299))
  21355. && ((soap->error == SOAP_TAG_MISMATCH && soap->level == 2) || soap->error == SOAP_NO_TAG))
  21356. return soap->error = SOAP_OK;
  21357. /* if check=0 and empty SOAP Body and encodingStyle is NULL and no HTTP error then just return */
  21358. if (!check
  21359. && (status == 0 || (status >= 200 && status <= 299))
  21360. && !soap->encodingStyle
  21361. && (soap->error == SOAP_NO_TAG && soap->level <= 2))
  21362. return soap->error = SOAP_OK;
  21363. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed with error %d at level %u tag '%s'\n", soap->error, soap->level, soap->tag));
  21364. *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client");
  21365. if (status)
  21366. soap->error = status;
  21367. else
  21368. soap->error = status = SOAP_NO_DATA;
  21369. soap_set_fault(soap);
  21370. }
  21371. else
  21372. {
  21373. const char *s = *soap_faultcode(soap);
  21374. if (!soap_match_tag(soap, s, "SOAP-ENV:Server")
  21375. || !soap_match_tag(soap, s, "SOAP-ENV:Receiver"))
  21376. {
  21377. status = SOAP_SVR_FAULT;
  21378. }
  21379. else if (!soap_match_tag(soap, s, "SOAP-ENV:Client")
  21380. || !soap_match_tag(soap, s, "SOAP-ENV:Sender"))
  21381. {
  21382. status = SOAP_CLI_FAULT;
  21383. }
  21384. else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand"))
  21385. {
  21386. status = SOAP_MUSTUNDERSTAND;
  21387. }
  21388. else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch"))
  21389. {
  21390. status = SOAP_VERSIONMISMATCH;
  21391. }
  21392. else
  21393. {
  21394. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Received SOAP Fault code %s\n", s));
  21395. status = SOAP_FAULT;
  21396. }
  21397. if (!soap_body_end_in(soap))
  21398. soap_envelope_end_in(soap);
  21399. }
  21400. (void)soap_end_recv(soap);
  21401. soap->error = status;
  21402. return soap_closesock(soap);
  21403. }
  21404. /******************************************************************************/
  21405. #ifndef WITH_NOHTTP
  21406. SOAP_FMAC1
  21407. int
  21408. SOAP_FMAC2
  21409. soap_send_empty_response(struct soap *soap, int httpstatuscode)
  21410. {
  21411. soap_mode m = soap->omode;
  21412. if (!(m & SOAP_IO_UDP))
  21413. {
  21414. soap->count = 0;
  21415. if ((m & SOAP_IO) == SOAP_IO_CHUNK)
  21416. soap->omode = (m & ~SOAP_IO) | SOAP_IO_BUFFER;
  21417. (void)soap_response(soap, httpstatuscode);
  21418. (void)soap_end_send(soap); /* force end of sends */
  21419. soap->error = SOAP_STOP; /* stops the server from returning another response */
  21420. soap->omode = m;
  21421. }
  21422. return soap_closesock(soap);
  21423. }
  21424. #endif
  21425. /******************************************************************************/
  21426. #ifndef WITH_NOHTTP
  21427. SOAP_FMAC1
  21428. int
  21429. SOAP_FMAC2
  21430. soap_recv_empty_response(struct soap *soap)
  21431. {
  21432. soap->error = SOAP_OK;
  21433. if (!(soap->omode & SOAP_IO_UDP) && !(soap->omode & SOAP_ENC_PLAIN))
  21434. {
  21435. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Receiving empty response\n"));
  21436. if (soap_begin_recv(soap) == SOAP_OK)
  21437. {
  21438. if (soap_http_skip_body(soap) || soap_end_recv(soap))
  21439. return soap_closesock(soap);
  21440. }
  21441. else if (soap->error == 200 || soap->error == 201 || soap->error == 202)
  21442. {
  21443. soap->error = SOAP_OK;
  21444. }
  21445. }
  21446. #ifndef WITH_LEANER
  21447. else if ((soap->fprepareinitrecv && (soap->error = soap->fprepareinitrecv(soap)))
  21448. || (soap->fpreparefinalrecv && (soap->error = soap->fpreparefinalrecv(soap))))
  21449. {
  21450. return soap->error;
  21451. }
  21452. #endif
  21453. return soap_closesock(soap);
  21454. }
  21455. #endif
  21456. /******************************************************************************/
  21457. #ifndef WITH_NOIO
  21458. static const char*
  21459. soap_strerror(struct soap *soap)
  21460. {
  21461. int err = soap->errnum;
  21462. *soap->msgbuf = '\0';
  21463. if (err)
  21464. {
  21465. #ifndef WIN32
  21466. # ifdef HAVE_STRERROR_R
  21467. # if (!_GNU_SOURCE && !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__ANDROID__) || !defined(__GLIBC__)
  21468. strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* XSI-compliant */
  21469. # else
  21470. return strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* GNU-specific */
  21471. # endif
  21472. # else
  21473. return strerror(err);
  21474. # endif
  21475. #else
  21476. #ifndef UNDER_CE
  21477. DWORD len;
  21478. *soap->msgbuf = '\0';
  21479. 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);
  21480. #else
  21481. DWORD i, len;
  21482. *soap->msgbuf = '\0';
  21483. len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)soap->msgbuf, (DWORD)(sizeof(soap->msgbuf)/sizeof(TCHAR)), NULL);
  21484. for (i = 0; i <= len; i++)
  21485. {
  21486. if (((TCHAR*)soap->msgbuf)[i] < 0x80)
  21487. soap->msgbuf[i] = (char)((TCHAR*)soap->msgbuf)[i];
  21488. else
  21489. soap->msgbuf[i] = '?';
  21490. }
  21491. #endif
  21492. #endif
  21493. }
  21494. else
  21495. {
  21496. if (soap->recv_maxlength && soap->count > soap->recv_maxlength)
  21497. {
  21498. soap_strcpy(soap->msgbuf, sizeof(soap->msgbuf), "max message length exceeded");
  21499. }
  21500. else
  21501. {
  21502. int tt = soap->transfer_timeout, rt = soap->recv_timeout, st = soap->send_timeout;
  21503. #ifndef WITH_LEAN
  21504. int tu = ' ', ru = ' ', su = ' ';
  21505. #endif
  21506. soap_strcpy(soap->msgbuf, sizeof(soap->msgbuf), "message transfer interrupted");
  21507. if (tt | rt || st)
  21508. soap_strcpy(soap->msgbuf + 28, sizeof(soap->msgbuf) - 28, " or timed out");
  21509. #ifndef WITH_LEAN
  21510. if (tt < 0)
  21511. {
  21512. tt = -tt;
  21513. tu = 'u';
  21514. }
  21515. if (rt < 0)
  21516. {
  21517. rt = -rt;
  21518. ru = 'u';
  21519. }
  21520. if (st < 0)
  21521. {
  21522. st = -st;
  21523. su = 'u';
  21524. }
  21525. if (tt)
  21526. {
  21527. size_t l = strlen(soap->msgbuf);
  21528. (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, 43), " (%d%csec max transfer time)", tt, tu);
  21529. }
  21530. if (rt)
  21531. {
  21532. size_t l = strlen(soap->msgbuf);
  21533. (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, 40), " (%d%csec max recv delay)", rt, ru);
  21534. }
  21535. if (st)
  21536. {
  21537. size_t l = strlen(soap->msgbuf);
  21538. (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, 40), " (%d%csec max send delay)", st, su);
  21539. }
  21540. #endif
  21541. }
  21542. }
  21543. return soap->msgbuf;
  21544. }
  21545. #endif
  21546. /******************************************************************************/
  21547. static int
  21548. soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML, int soaperror)
  21549. {
  21550. *soap_faultcode(soap) = faultcode;
  21551. if (faultsubcodeQName)
  21552. *soap_faultsubcode(soap) = faultsubcodeQName;
  21553. *soap_faultstring(soap) = faultstring;
  21554. if (faultdetailXML && *faultdetailXML)
  21555. {
  21556. const char **s = soap_faultdetail(soap);
  21557. if (s)
  21558. *s = faultdetailXML;
  21559. }
  21560. return soap->error = soaperror;
  21561. }
  21562. /******************************************************************************/
  21563. SOAP_FMAC1
  21564. int
  21565. SOAP_FMAC2
  21566. soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror)
  21567. {
  21568. return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : soap->version == 1 ? "SOAP-ENV:Client" : "at sender", NULL, faultstring, faultdetailXML, soaperror);
  21569. }
  21570. /******************************************************************************/
  21571. SOAP_FMAC1
  21572. int
  21573. SOAP_FMAC2
  21574. soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror)
  21575. {
  21576. return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : soap->version == 1 ? "SOAP-ENV:Server" : "detected", NULL, faultstring, faultdetailXML, soaperror);
  21577. }
  21578. /******************************************************************************/
  21579. static int
  21580. soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
  21581. {
  21582. char *r = NULL, *s = NULL, *t = NULL;
  21583. DBGFUN2("soap_copy_fault", "code=%s", faultcode ? faultcode : "(null)", "string=%s", faultstring ? faultstring : "(null)")
  21584. if (faultsubcodeQName)
  21585. r = soap_strdup(soap, faultsubcodeQName);
  21586. if (faultstring)
  21587. s = soap_strdup(soap, faultstring);
  21588. if (faultdetailXML)
  21589. t = soap_strdup(soap, faultdetailXML);
  21590. return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT);
  21591. }
  21592. /******************************************************************************/
  21593. SOAP_FMAC1
  21594. int
  21595. SOAP_FMAC2
  21596. soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
  21597. {
  21598. return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetailXML);
  21599. }
  21600. /******************************************************************************/
  21601. SOAP_FMAC1
  21602. int
  21603. SOAP_FMAC2
  21604. soap_sender_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
  21605. {
  21606. return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : soap->version == 1 ? "SOAP-ENV:Client" : "at source", faultsubcodeQName, faultstring, faultdetailXML);
  21607. }
  21608. /******************************************************************************/
  21609. SOAP_FMAC1
  21610. int
  21611. SOAP_FMAC2
  21612. soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
  21613. {
  21614. return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetailXML);
  21615. }
  21616. /******************************************************************************/
  21617. SOAP_FMAC1
  21618. int
  21619. SOAP_FMAC2
  21620. soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
  21621. {
  21622. return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : soap->version == 1 ? "SOAP-ENV:Server" : "is internal", faultsubcodeQName, faultstring, faultdetailXML);
  21623. }
  21624. /******************************************************************************/
  21625. #ifndef WITH_NOSTDLIB
  21626. SOAP_FMAC1
  21627. void
  21628. SOAP_FMAC2
  21629. soap_print_fault(struct soap *soap, FILE *fd)
  21630. {
  21631. if (soap_check_state(soap))
  21632. {
  21633. fprintf(fd, "Error: soap struct state not initialized\n");
  21634. }
  21635. else if (soap->error)
  21636. {
  21637. const char **c, *v = NULL, *s, *d;
  21638. c = soap_faultcode(soap);
  21639. if (!*c)
  21640. {
  21641. soap_set_fault(soap);
  21642. c = soap_faultcode(soap);
  21643. }
  21644. if (soap->version == 2)
  21645. v = soap_fault_subcode(soap);
  21646. s = soap_fault_string(soap);
  21647. d = soap_fault_detail(soap);
  21648. fprintf(fd, "%s%d fault %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c, v ? v : "no subcode", s ? s : "[no reason]", d ? d : "[no detail]");
  21649. }
  21650. }
  21651. #endif
  21652. /******************************************************************************/
  21653. #ifdef __cplusplus
  21654. #ifndef WITH_LEAN
  21655. #ifndef WITH_NOSTDLIB
  21656. #ifndef WITH_COMPAT
  21657. SOAP_FMAC1
  21658. void
  21659. SOAP_FMAC2
  21660. soap_stream_fault(struct soap *soap, std::ostream& os)
  21661. {
  21662. if (soap_check_state(soap))
  21663. {
  21664. os << "Error: soap struct state not initialized\n";
  21665. }
  21666. else if (soap->error)
  21667. {
  21668. const char **c, *v = NULL, *s, *d;
  21669. c = soap_faultcode(soap);
  21670. if (!*c)
  21671. {
  21672. soap_set_fault(soap);
  21673. c = soap_faultcode(soap);
  21674. }
  21675. if (soap->version == 2)
  21676. v = soap_fault_subcode(soap);
  21677. s = soap_fault_string(soap);
  21678. d = soap_fault_detail(soap);
  21679. os << (soap->version ? "SOAP 1." : "Error ")
  21680. << (soap->version ? (int)soap->version : soap->error)
  21681. << " fault " << *c
  21682. << "[" << (v ? v : "no subcode") << "]"
  21683. << std::endl
  21684. << "\"" << (s ? s : "[no reason]") << "\""
  21685. << std::endl
  21686. << "Detail: " << (d ? d : "[no detail]")
  21687. << std::endl;
  21688. }
  21689. }
  21690. #endif
  21691. #endif
  21692. #endif
  21693. #endif
  21694. /******************************************************************************/
  21695. #ifndef WITH_LEAN
  21696. #ifndef WITH_NOSTDLIB
  21697. SOAP_FMAC1
  21698. char*
  21699. SOAP_FMAC2
  21700. soap_sprint_fault(struct soap *soap, char *buf, size_t len)
  21701. {
  21702. if (soap_check_state(soap))
  21703. {
  21704. soap_strcpy(buf, len, "Error: soap struct not initialized");
  21705. }
  21706. else if (soap->error)
  21707. {
  21708. const char **c, *v = NULL, *s, *d;
  21709. c = soap_faultcode(soap);
  21710. if (!*c)
  21711. {
  21712. soap_set_fault(soap);
  21713. c = soap_faultcode(soap);
  21714. }
  21715. if (soap->version == 2)
  21716. v = soap_fault_subcode(soap);
  21717. if (!v)
  21718. v = "no subcode";
  21719. s = soap_fault_string(soap);
  21720. if (!s)
  21721. s = "[no reason]";
  21722. d = soap_fault_detail(soap);
  21723. if (!d)
  21724. d = "[no detail]";
  21725. (SOAP_SNPRINTF(buf, len, strlen(*c) + strlen(v) + strlen(s) + strlen(d) + 72), "%s%d fault %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c, v, s, d);
  21726. }
  21727. else if (len > 0)
  21728. {
  21729. *buf = '\0';
  21730. }
  21731. return buf;
  21732. }
  21733. #endif
  21734. #endif
  21735. /******************************************************************************/
  21736. #ifndef WITH_NOSTDLIB
  21737. SOAP_FMAC1
  21738. void
  21739. SOAP_FMAC2
  21740. soap_print_fault_location(struct soap *soap, FILE *fd)
  21741. {
  21742. #ifndef WITH_LEAN
  21743. int i, j, c1, c2;
  21744. if (soap_check_state(soap) == SOAP_OK && soap->error && soap->error != SOAP_STOP && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= sizeof(soap->buf))
  21745. {
  21746. i = (int)soap->bufidx - 1;
  21747. if (i <= 0)
  21748. i = 0;
  21749. c1 = soap->buf[i];
  21750. soap->buf[i] = '\0';
  21751. if ((int)soap->buflen >= i + 1024)
  21752. j = i + 1023;
  21753. else
  21754. j = (int)soap->buflen - 1;
  21755. c2 = soap->buf[j];
  21756. soap->buf[j] = '\0';
  21757. fprintf(fd, "%s%c\n<!-- ** HERE ** -->\n", soap->buf, c1);
  21758. if (soap->bufidx < soap->buflen)
  21759. fprintf(fd, "%s\n", soap->buf + soap->bufidx);
  21760. soap->buf[i] = (char)c1;
  21761. soap->buf[j] = (char)c2;
  21762. }
  21763. #else
  21764. (void)soap;
  21765. (void)fd;
  21766. #endif
  21767. }
  21768. #endif
  21769. /******************************************************************************/
  21770. #ifdef __cplusplus
  21771. #ifndef WITH_LEAN
  21772. #ifndef WITH_NOSTDLIB
  21773. #ifndef WITH_COMPAT
  21774. SOAP_FMAC1
  21775. void
  21776. SOAP_FMAC2
  21777. soap_stream_fault_location(struct soap *soap, std::ostream& os)
  21778. {
  21779. int i, j, c1, c2;
  21780. if (soap_check_state(soap) == SOAP_OK && soap->error && soap->error != SOAP_STOP && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= sizeof(soap->buf))
  21781. {
  21782. i = (int)soap->bufidx - 1;
  21783. if (i <= 0)
  21784. i = 0;
  21785. c1 = soap->buf[i];
  21786. soap->buf[i] = '\0';
  21787. if ((int)soap->buflen >= i + 1024)
  21788. j = i + 1023;
  21789. else
  21790. j = (int)soap->buflen - 1;
  21791. c2 = soap->buf[j];
  21792. soap->buf[j] = '\0';
  21793. os << soap->buf << (char)c1 << std::endl << "<!-- ** HERE ** -->" << std::endl;
  21794. if (soap->bufidx < soap->buflen)
  21795. os << soap->buf + soap->bufidx << std::endl;
  21796. soap->buf[i] = (char)c1;
  21797. soap->buf[j] = (char)c2;
  21798. }
  21799. }
  21800. #endif
  21801. #endif
  21802. #endif
  21803. #endif
  21804. /******************************************************************************/
  21805. SOAP_FMAC1
  21806. int
  21807. SOAP_FMAC2
  21808. soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg)
  21809. {
  21810. struct soap_plugin *p;
  21811. int err;
  21812. p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin));
  21813. if (!p)
  21814. return soap->error = SOAP_EOM;
  21815. p->id = NULL;
  21816. p->data = NULL;
  21817. p->fcopy = NULL;
  21818. p->fdelete = NULL;
  21819. err = fcreate(soap, p, arg);
  21820. if (!err && p->fdelete && p->id)
  21821. {
  21822. if (!soap_lookup_plugin(soap, p->id))
  21823. {
  21824. p->next = soap->plugins;
  21825. soap->plugins = p;
  21826. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id));
  21827. return SOAP_OK;
  21828. }
  21829. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin with the same ID already registered\n", p->id));
  21830. SOAP_FREE(soap, p);
  21831. return SOAP_OK;
  21832. }
  21833. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin returned error %d or plugin ID not set or fdelete callback not set\n", p->id ? p->id : "plugin ID not set", err));
  21834. SOAP_FREE(soap, p);
  21835. soap->error = err ? err : SOAP_PLUGIN_ERROR;
  21836. return soap->error;
  21837. }
  21838. /******************************************************************************/
  21839. static void *
  21840. fplugin(struct soap *soap, const char *id)
  21841. {
  21842. struct soap_plugin *p;
  21843. for (p = soap->plugins; p; p = p->next)
  21844. if (p->id == id || !strcmp(p->id, id))
  21845. return p->data;
  21846. return NULL;
  21847. }
  21848. /******************************************************************************/
  21849. SOAP_FMAC1
  21850. void *
  21851. SOAP_FMAC2
  21852. soap_lookup_plugin(struct soap *soap, const char *id)
  21853. {
  21854. return soap->fplugin(soap, id);
  21855. }
  21856. /******************************************************************************/
  21857. #ifdef __cplusplus
  21858. }
  21859. #endif
  21860. /******************************************************************************\
  21861. *
  21862. * C++ soap struct methods
  21863. *
  21864. \******************************************************************************/
  21865. #ifdef __cplusplus
  21866. soap::soap()
  21867. {
  21868. soap_init(this);
  21869. /* no logs to prevent DEBUG mode leaks when the user calls a soap_init() on this context */
  21870. soap_set_test_logfile(this, NULL);
  21871. soap_set_sent_logfile(this, NULL);
  21872. soap_set_recv_logfile(this, NULL);
  21873. }
  21874. #endif
  21875. /******************************************************************************/
  21876. #ifdef __cplusplus
  21877. soap::soap(soap_mode m)
  21878. {
  21879. soap_init1(this, m);
  21880. }
  21881. #endif
  21882. /******************************************************************************/
  21883. #ifdef __cplusplus
  21884. soap::soap(soap_mode im, soap_mode om)
  21885. {
  21886. soap_init2(this, im, om);
  21887. }
  21888. #endif
  21889. /******************************************************************************/
  21890. #ifdef __cplusplus
  21891. soap::soap(const struct soap& soap)
  21892. {
  21893. soap_copy_context(this, &soap);
  21894. }
  21895. #endif
  21896. /******************************************************************************/
  21897. #ifdef __cplusplus
  21898. struct soap& soap::operator=(const struct soap& soap)
  21899. {
  21900. soap_done(this);
  21901. soap_copy_context(this, &soap);
  21902. return *this;
  21903. }
  21904. #endif
  21905. /******************************************************************************/
  21906. #ifdef __cplusplus
  21907. void soap::destroy()
  21908. {
  21909. soap_destroy(this);
  21910. soap_end(this);
  21911. }
  21912. #endif
  21913. /******************************************************************************/
  21914. #ifdef __cplusplus
  21915. soap::~soap()
  21916. {
  21917. soap_done(this);
  21918. }
  21919. #endif
  21920. /******************************************************************************/