php_imap.c 135 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Copyright (c) The PHP Group |
  4. +----------------------------------------------------------------------+
  5. | This source file is subject to version 3.01 of the PHP license, |
  6. | that is bundled with this package in the file LICENSE, and is |
  7. | available through the world-wide-web at the following url: |
  8. | https://www.php.net/license/3_01.txt |
  9. | If you did not receive a copy of the PHP license and are unable to |
  10. | obtain it through the world-wide-web, please send a note to |
  11. | license@php.net so we can mail you a copy immediately. |
  12. +----------------------------------------------------------------------+
  13. | Authors: Rex Logan <veebert@dimensional.com> |
  14. | Mark Musone <musone@afterfive.com> |
  15. | Brian Wang <brian@vividnet.com> |
  16. | Kaj-Michael Lang <milang@tal.org> |
  17. | Antoni Pamies Olive <toni@readysoft.net> |
  18. | Rasmus Lerdorf <rasmus@php.net> |
  19. | Chuck Hagenbuch <chuck@horde.org> |
  20. | Andrew Skalski <askalski@chekinc.com> |
  21. | Hartmut Holzgraefe <hholzgra@php.net> |
  22. | Jani Taskinen <jani.taskinen@iki.fi> |
  23. | Daniel R. Kalowsky <kalowsky@php.net> |
  24. | PHP 4.0 updates: Zeev Suraski <zeev@php.net> |
  25. +----------------------------------------------------------------------+
  26. */
  27. #define IMAP41
  28. #ifdef HAVE_CONFIG_H
  29. #include "config.h"
  30. #endif
  31. #include "php.h"
  32. #include "php_ini.h"
  33. #include "php_streams.h"
  34. #include "Zend/zend_exceptions.h"
  35. #include "ext/standard/php_string.h"
  36. #include "ext/standard/info.h"
  37. #include "ext/standard/file.h"
  38. #include "zend_smart_str.h"
  39. #include "ext/pcre/php_pcre.h"
  40. #ifdef ERROR
  41. #undef ERROR
  42. #endif
  43. #include "php_imap.h"
  44. #include "php_imap_arginfo.h"
  45. #include <time.h>
  46. #include <stdio.h>
  47. #include <ctype.h>
  48. #include <signal.h>
  49. #ifdef PHP_WIN32
  50. #include <winsock2.h>
  51. #include <stdlib.h>
  52. #include "win32/sendmail.h"
  53. MAILSTREAM DEFAULTPROTO;
  54. #endif
  55. #define CRLF "\015\012"
  56. #define CRLF_LEN sizeof("\015\012") - 1
  57. #define PHP_EXPUNGE 32768
  58. #define PHP_IMAP_ADDRESS_SIZE_BUF 10
  59. #ifndef SENDBUFLEN
  60. #define SENDBUFLEN 16385
  61. #endif
  62. #if defined(__GNUC__) && __GNUC__ >= 4
  63. # define PHP_IMAP_EXPORT __attribute__ ((visibility("default")))
  64. #else
  65. # define PHP_IMAP_EXPORT
  66. #endif
  67. static void _php_make_header_object(zval *myzvalue, ENVELOPE *en);
  68. static void _php_imap_add_body(zval *arg, BODY *body);
  69. static zend_string* _php_imap_parse_address(ADDRESS *addresslist, zval *paddress);
  70. static zend_string* _php_rfc822_write_address(ADDRESS *addresslist);
  71. /* the gets we use */
  72. static char *php_mail_gets(readfn_t f, void *stream, unsigned long size, GETS_DATA *md);
  73. /* These function declarations are missing from the IMAP header files... */
  74. void rfc822_date(char *date);
  75. char *cpystr(const char *str);
  76. char *cpytxt(SIZEDTEXT *dst, char *text, unsigned long size);
  77. #ifndef HAVE_NEW_MIME2TEXT
  78. long utf8_mime2text(SIZEDTEXT *src, SIZEDTEXT *dst);
  79. #else
  80. long utf8_mime2text (SIZEDTEXT *src, SIZEDTEXT *dst, long flags);
  81. #endif
  82. unsigned long find_rightmost_bit(unsigned long *valptr);
  83. void fs_give(void **block);
  84. void *fs_get(size_t size);
  85. ZEND_DECLARE_MODULE_GLOBALS(imap)
  86. static PHP_GINIT_FUNCTION(imap);
  87. /* {{{ imap dependencies */
  88. static const zend_module_dep imap_deps[] = {
  89. ZEND_MOD_REQUIRED("standard")
  90. ZEND_MOD_END
  91. };
  92. /* }}} */
  93. /* {{{ PHP_INI */
  94. PHP_INI_BEGIN()
  95. STD_PHP_INI_BOOLEAN("imap.enable_insecure_rsh", "0", PHP_INI_SYSTEM, OnUpdateBool, enable_rsh, zend_imap_globals, imap_globals)
  96. PHP_INI_END()
  97. /* }}} */
  98. /* {{{ imap_module_entry */
  99. zend_module_entry imap_module_entry = {
  100. STANDARD_MODULE_HEADER_EX, NULL,
  101. imap_deps,
  102. "imap",
  103. ext_functions,
  104. PHP_MINIT(imap),
  105. NULL,
  106. PHP_RINIT(imap),
  107. PHP_RSHUTDOWN(imap),
  108. PHP_MINFO(imap),
  109. PHP_IMAP_VERSION,
  110. PHP_MODULE_GLOBALS(imap),
  111. PHP_GINIT(imap),
  112. NULL,
  113. NULL,
  114. STANDARD_MODULE_PROPERTIES_EX
  115. };
  116. /* }}} */
  117. #ifdef COMPILE_DL_IMAP
  118. #ifdef ZTS
  119. ZEND_TSRMLS_CACHE_DEFINE()
  120. #endif
  121. ZEND_GET_MODULE(imap)
  122. #endif
  123. /* Imap class entry definition */
  124. static zend_class_entry *php_imap_ce = NULL;
  125. static zend_object_handlers imap_object_handlers;
  126. typedef struct _php_imap_object {
  127. MAILSTREAM *imap_stream;
  128. long flags;
  129. zend_object std;
  130. } php_imap_object;
  131. static inline zend_object *imap_object_to_zend_object(php_imap_object *obj) {
  132. return ((zend_object*)(obj + 1)) - 1;
  133. }
  134. static inline php_imap_object *imap_object_from_zend_object(zend_object *zobj) {
  135. return ((php_imap_object*)(zobj + 1)) - 1;
  136. }
  137. static zend_object* imap_object_create(zend_class_entry* ce) {
  138. php_imap_object *obj = zend_object_alloc(sizeof(php_imap_object), ce);
  139. zend_object *zobj = imap_object_to_zend_object(obj);
  140. obj->imap_stream = NULL;
  141. obj->flags = 0;
  142. zend_object_std_init(zobj, ce);
  143. object_properties_init(zobj, ce);
  144. zobj->handlers = &imap_object_handlers;
  145. return zobj;
  146. }
  147. static zend_function *imap_object_get_constructor(zend_object *zobj) {
  148. zend_throw_error(NULL, "Cannot directly construct IMAP\\Connection, use imap_open() instead");
  149. return NULL;
  150. }
  151. static void imap_object_destroy(zend_object *zobj) {
  152. php_imap_object *obj = imap_object_from_zend_object(zobj);
  153. if (obj->imap_stream) {
  154. /* Do not try to close prototype streams */
  155. if (!(obj->flags & OP_PROTOTYPE)) {
  156. mail_close_full(obj->imap_stream, obj->flags);
  157. }
  158. }
  159. if (IMAPG(imap_user)) {
  160. efree(IMAPG(imap_user));
  161. IMAPG(imap_user) = 0;
  162. }
  163. if (IMAPG(imap_password)) {
  164. efree(IMAPG(imap_password));
  165. IMAPG(imap_password) = 0;
  166. }
  167. zend_object_std_dtor(zobj);
  168. }
  169. #define GET_IMAP_STREAM(imap_conn_struct, zval_imap_obj) \
  170. imap_conn_struct = imap_object_from_zend_object(Z_OBJ_P(zval_imap_obj)); \
  171. if (imap_conn_struct->imap_stream == NULL) { \
  172. zend_throw_exception(zend_ce_value_error, "IMAP\\Connection is already closed", 0); \
  173. RETURN_THROWS(); \
  174. }
  175. #define PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgindex, arg_pos) \
  176. if (msgindex < 1) { \
  177. zend_argument_value_error(arg_pos, "must be greater than 0"); \
  178. RETURN_THROWS(); \
  179. } \
  180. #define PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgindex, arg_pos, func_flags, uid_flag) \
  181. if (func_flags & uid_flag) { \
  182. /* This should be cached; if it causes an extra RTT to the IMAP server, */ \
  183. /* then that's the price we pay for making sure we don't crash. */ \
  184. unsigned int msg_no_from_uid = mail_msgno(imap_conn_struct->imap_stream, msgindex); \
  185. if (msg_no_from_uid == 0) { \
  186. php_error_docref(NULL, E_WARNING, "UID does not exist"); \
  187. RETURN_FALSE; \
  188. } \
  189. } else { \
  190. if (((unsigned) msgindex) > imap_conn_struct->imap_stream->nmsgs) { \
  191. php_error_docref(NULL, E_WARNING, "Bad message number"); \
  192. RETURN_FALSE; \
  193. } \
  194. } \
  195. // TODO Promote to ValueError?
  196. #define PHP_IMAP_CHECK_MSGNO(msgindex, arg_pos) \
  197. if (msgindex < 1) { \
  198. zend_argument_value_error(arg_pos, "must be greater than 0"); \
  199. RETURN_THROWS(); \
  200. } \
  201. if (((unsigned) msgindex) > imap_conn_struct->imap_stream->nmsgs) { \
  202. php_error_docref(NULL, E_WARNING, "Bad message number"); \
  203. RETURN_FALSE; \
  204. } \
  205. /* {{{ php_imap_hash_add_object */
  206. static zval *php_imap_hash_add_object(zval *arg, char *key, zval *tmp)
  207. {
  208. HashTable *symtable;
  209. if (Z_TYPE_P(arg) == IS_OBJECT) {
  210. symtable = Z_OBJPROP_P(arg);
  211. } else {
  212. symtable = Z_ARRVAL_P(arg);
  213. }
  214. return zend_hash_str_update(symtable, key, strlen(key), tmp);
  215. }
  216. /* }}} */
  217. /* {{{ php_imap_list_add_object */
  218. static inline zval *php_imap_list_add_object(zval *arg, zval *tmp)
  219. {
  220. HashTable *symtable;
  221. if (Z_TYPE_P(arg) == IS_OBJECT) {
  222. symtable = Z_OBJPROP_P(arg);
  223. } else {
  224. symtable = Z_ARRVAL_P(arg);
  225. }
  226. return zend_hash_next_index_insert(symtable, tmp);
  227. }
  228. /* }}} */
  229. /* {{{ mail_newfolderobjectlist
  230. *
  231. * Mail instantiate FOBJECTLIST
  232. * Returns: new FOBJECTLIST list
  233. * Author: CJH
  234. */
  235. FOBJECTLIST *mail_newfolderobjectlist(void)
  236. {
  237. return (FOBJECTLIST *) memset(fs_get(sizeof(FOBJECTLIST)), 0, sizeof(FOBJECTLIST));
  238. }
  239. /* }}} */
  240. /* {{{ mail_free_foblist
  241. *
  242. * Mail garbage collect FOBJECTLIST
  243. * Accepts: pointer to FOBJECTLIST pointer
  244. * Author: CJH
  245. */
  246. void mail_free_foblist(FOBJECTLIST **foblist, FOBJECTLIST **tail)
  247. {
  248. FOBJECTLIST *cur, *next;
  249. for (cur=*foblist, next=cur->next; cur; cur=next) {
  250. next = cur->next;
  251. if(cur->text.data)
  252. fs_give((void **)&(cur->text.data));
  253. fs_give((void **)&cur);
  254. }
  255. *tail = NIL;
  256. *foblist = NIL;
  257. }
  258. /* }}} */
  259. /* {{{ mail_newerrorlist
  260. *
  261. * Mail instantiate ERRORLIST
  262. * Returns: new ERRORLIST list
  263. * Author: CJH
  264. */
  265. ERRORLIST *mail_newerrorlist(void)
  266. {
  267. return (ERRORLIST *) memset(fs_get(sizeof(ERRORLIST)), 0, sizeof(ERRORLIST));
  268. }
  269. /* }}} */
  270. /* {{{ mail_free_errorlist
  271. *
  272. * Mail garbage collect FOBJECTLIST
  273. * Accepts: pointer to FOBJECTLIST pointer
  274. * Author: CJH
  275. */
  276. void mail_free_errorlist(ERRORLIST **errlist)
  277. {
  278. if (*errlist) { /* only free if exists */
  279. if ((*errlist)->text.data) {
  280. fs_give((void **) &(*errlist)->text.data);
  281. }
  282. mail_free_errorlist (&(*errlist)->next);
  283. fs_give((void **) errlist); /* return string to free storage */
  284. }
  285. }
  286. /* }}} */
  287. /* {{{ mail_newmessagelist
  288. *
  289. * Mail instantiate MESSAGELIST
  290. * Returns: new MESSAGELIST list
  291. * Author: CJH
  292. */
  293. MESSAGELIST *mail_newmessagelist(void)
  294. {
  295. return (MESSAGELIST *) memset(fs_get(sizeof(MESSAGELIST)), 0, sizeof(MESSAGELIST));
  296. }
  297. /* }}} */
  298. /* {{{ mail_free_messagelist
  299. *
  300. * Mail garbage collect MESSAGELIST
  301. * Accepts: pointer to MESSAGELIST pointer
  302. * Author: CJH
  303. */
  304. void mail_free_messagelist(MESSAGELIST **msglist, MESSAGELIST **tail)
  305. {
  306. MESSAGELIST *cur, *next;
  307. for (cur = *msglist, next = cur->next; cur; cur = next) {
  308. next = cur->next;
  309. fs_give((void **)&cur);
  310. }
  311. *tail = NIL;
  312. *msglist = NIL;
  313. }
  314. /* }}} */
  315. #if defined(HAVE_IMAP2000) || defined(HAVE_IMAP2001)
  316. /* {{{ mail_getquota
  317. *
  318. * Mail GET_QUOTA callback
  319. * Called via the mail_parameter function in c-client:src/c-client/mail.c
  320. * Author DRK
  321. */
  322. void mail_getquota(MAILSTREAM *stream, char *qroot, QUOTALIST *qlist)
  323. {
  324. zval t_map, *return_value;
  325. return_value = *IMAPG(quota_return);
  326. /* put parsing code here */
  327. for(; qlist; qlist = qlist->next) {
  328. array_init(&t_map);
  329. if (strncmp(qlist->name, "STORAGE", 7) == 0)
  330. {
  331. /* this is to add backwards compatibility */
  332. add_assoc_long_ex(return_value, "usage", sizeof("usage") - 1, qlist->usage);
  333. add_assoc_long_ex(return_value, "limit", sizeof("limit") - 1, qlist->limit);
  334. }
  335. add_assoc_long_ex(&t_map, "usage", sizeof("usage") - 1, qlist->usage);
  336. add_assoc_long_ex(&t_map, "limit", sizeof("limit") - 1, qlist->limit);
  337. add_assoc_zval_ex(return_value, qlist->name, strlen(qlist->name), &t_map);
  338. }
  339. }
  340. /* }}} */
  341. /* {{{ mail_getquota
  342. *
  343. * Mail GET_ACL callback
  344. * Called via the mail_parameter function in c-client:src/c-client/mail.c
  345. */
  346. void mail_getacl(MAILSTREAM *stream, char *mailbox, ACLLIST *alist)
  347. {
  348. /* walk through the ACLLIST */
  349. for(; alist; alist = alist->next) {
  350. add_assoc_stringl(IMAPG(imap_acl_list), alist->identifier, alist->rights, strlen(alist->rights));
  351. }
  352. }
  353. /* }}} */
  354. #endif
  355. /* {{{ PHP_GINIT_FUNCTION */
  356. static PHP_GINIT_FUNCTION(imap)
  357. {
  358. #if defined(COMPILE_DL_IMAP) && defined(ZTS)
  359. ZEND_TSRMLS_CACHE_UPDATE();
  360. #endif
  361. imap_globals->imap_user = NIL;
  362. imap_globals->imap_password = NIL;
  363. imap_globals->imap_alertstack = NIL;
  364. imap_globals->imap_errorstack = NIL;
  365. imap_globals->imap_folders = NIL;
  366. imap_globals->imap_folders_tail = NIL;
  367. imap_globals->imap_sfolders = NIL;
  368. imap_globals->imap_sfolders_tail = NIL;
  369. imap_globals->imap_messages = NIL;
  370. imap_globals->imap_messages_tail = NIL;
  371. imap_globals->imap_folder_objects = NIL;
  372. imap_globals->imap_folder_objects_tail = NIL;
  373. imap_globals->imap_sfolder_objects = NIL;
  374. imap_globals->imap_sfolder_objects_tail = NIL;
  375. imap_globals->folderlist_style = FLIST_ARRAY;
  376. #if defined(HAVE_IMAP2000) || defined(HAVE_IMAP2001)
  377. imap_globals->quota_return = NIL;
  378. imap_globals->imap_acl_list = NIL;
  379. #endif
  380. imap_globals->gets_stream = NIL;
  381. }
  382. /* }}} */
  383. /* {{{ PHP_MINIT_FUNCTION */
  384. PHP_MINIT_FUNCTION(imap)
  385. {
  386. unsigned long sa_all = SA_MESSAGES | SA_RECENT | SA_UNSEEN | SA_UIDNEXT | SA_UIDVALIDITY;
  387. REGISTER_INI_ENTRIES();
  388. #ifndef PHP_WIN32
  389. mail_link(&unixdriver); /* link in the unix driver */
  390. mail_link(&mhdriver); /* link in the mh driver */
  391. /* mail_link(&mxdriver); */ /* According to c-client docs (internal.txt) this shouldn't be used. */
  392. mail_link(&mmdfdriver); /* link in the mmdf driver */
  393. mail_link(&newsdriver); /* link in the news driver */
  394. mail_link(&philedriver); /* link in the phile driver */
  395. #endif
  396. mail_link(&imapdriver); /* link in the imap driver */
  397. mail_link(&nntpdriver); /* link in the nntp driver */
  398. mail_link(&pop3driver); /* link in the pop3 driver */
  399. mail_link(&mbxdriver); /* link in the mbx driver */
  400. mail_link(&tenexdriver); /* link in the tenex driver */
  401. mail_link(&mtxdriver); /* link in the mtx driver */
  402. mail_link(&dummydriver); /* link in the dummy driver */
  403. #ifndef PHP_WIN32
  404. auth_link(&auth_log); /* link in the log authenticator */
  405. auth_link(&auth_md5); /* link in the cram-md5 authenticator */
  406. #if defined(HAVE_IMAP_KRB) && defined(HAVE_IMAP_AUTH_GSS)
  407. auth_link(&auth_gss); /* link in the gss authenticator */
  408. #endif
  409. auth_link(&auth_pla); /* link in the plain authenticator */
  410. #endif
  411. #ifdef HAVE_IMAP_SSL
  412. ssl_onceonlyinit ();
  413. #endif
  414. php_imap_ce = register_class_IMAP_Connection();
  415. php_imap_ce->create_object = imap_object_create;
  416. memcpy(&imap_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
  417. imap_object_handlers.offset = XtOffsetOf(php_imap_object, std);
  418. imap_object_handlers.get_constructor = imap_object_get_constructor;
  419. imap_object_handlers.free_obj = imap_object_destroy;
  420. imap_object_handlers.clone_obj = NULL;
  421. /* lets allow NIL */
  422. REGISTER_LONG_CONSTANT("NIL", NIL, CONST_PERSISTENT | CONST_CS | CONST_DEPRECATED);
  423. /* plug in our gets */
  424. mail_parameters(NIL, SET_GETS, (void *) NIL);
  425. /* set default timeout values */
  426. mail_parameters(NIL, SET_OPENTIMEOUT, (void *) FG(default_socket_timeout));
  427. mail_parameters(NIL, SET_READTIMEOUT, (void *) FG(default_socket_timeout));
  428. mail_parameters(NIL, SET_WRITETIMEOUT, (void *) FG(default_socket_timeout));
  429. mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) FG(default_socket_timeout));
  430. /* timeout constants */
  431. REGISTER_LONG_CONSTANT("IMAP_OPENTIMEOUT", 1, CONST_PERSISTENT | CONST_CS);
  432. REGISTER_LONG_CONSTANT("IMAP_READTIMEOUT", 2, CONST_PERSISTENT | CONST_CS);
  433. REGISTER_LONG_CONSTANT("IMAP_WRITETIMEOUT", 3, CONST_PERSISTENT | CONST_CS);
  434. REGISTER_LONG_CONSTANT("IMAP_CLOSETIMEOUT", 4, CONST_PERSISTENT | CONST_CS);
  435. /* Open Options */
  436. REGISTER_LONG_CONSTANT("OP_DEBUG", OP_DEBUG, CONST_PERSISTENT | CONST_CS);
  437. /* debug protocol negotiations */
  438. REGISTER_LONG_CONSTANT("OP_READONLY", OP_READONLY, CONST_PERSISTENT | CONST_CS);
  439. /* read-only open */
  440. REGISTER_LONG_CONSTANT("OP_ANONYMOUS", OP_ANONYMOUS, CONST_PERSISTENT | CONST_CS);
  441. /* anonymous open of newsgroup */
  442. REGISTER_LONG_CONSTANT("OP_SHORTCACHE", OP_SHORTCACHE, CONST_PERSISTENT | CONST_CS);
  443. /* short (elt-only) caching */
  444. REGISTER_LONG_CONSTANT("OP_SILENT", OP_SILENT, CONST_PERSISTENT | CONST_CS);
  445. /* don't pass up events (internal use) */
  446. REGISTER_LONG_CONSTANT("OP_PROTOTYPE", OP_PROTOTYPE, CONST_PERSISTENT | CONST_CS);
  447. /* return driver prototype */
  448. REGISTER_LONG_CONSTANT("OP_HALFOPEN", OP_HALFOPEN, CONST_PERSISTENT | CONST_CS);
  449. /* half-open (IMAP connect but no select) */
  450. REGISTER_LONG_CONSTANT("OP_EXPUNGE", OP_EXPUNGE, CONST_PERSISTENT | CONST_CS);
  451. /* silently expunge recycle stream */
  452. REGISTER_LONG_CONSTANT("OP_SECURE", OP_SECURE, CONST_PERSISTENT | CONST_CS);
  453. /* don't do non-secure authentication */
  454. /*
  455. PHP re-assigns CL_EXPUNGE a custom value that can be used as part of the imap_open() bitfield
  456. because it seems like a good idea to be able to indicate that the mailbox should be
  457. automatically expunged during imap_open in case the script get interrupted and it doesn't get
  458. to the imap_close() where this option is normally placed. If the c-client library adds other
  459. options and the value for this one conflicts, simply make PHP_EXPUNGE higher at the top of
  460. this file
  461. */
  462. REGISTER_LONG_CONSTANT("CL_EXPUNGE", PHP_EXPUNGE, CONST_PERSISTENT | CONST_CS);
  463. /* expunge silently */
  464. /* Fetch options */
  465. REGISTER_LONG_CONSTANT("FT_UID", FT_UID, CONST_PERSISTENT | CONST_CS);
  466. /* argument is a UID */
  467. REGISTER_LONG_CONSTANT("FT_PEEK", FT_PEEK, CONST_PERSISTENT | CONST_CS);
  468. /* peek at data */
  469. REGISTER_LONG_CONSTANT("FT_NOT", FT_NOT, CONST_PERSISTENT | CONST_CS);
  470. /* NOT flag for header lines fetch */
  471. REGISTER_LONG_CONSTANT("FT_INTERNAL", FT_INTERNAL, CONST_PERSISTENT | CONST_CS);
  472. /* text can be internal strings */
  473. REGISTER_LONG_CONSTANT("FT_PREFETCHTEXT", FT_PREFETCHTEXT, CONST_PERSISTENT | CONST_CS);
  474. /* IMAP prefetch text when fetching header */
  475. /* Flagging options */
  476. REGISTER_LONG_CONSTANT("ST_UID", ST_UID, CONST_PERSISTENT | CONST_CS);
  477. /* argument is a UID sequence */
  478. REGISTER_LONG_CONSTANT("ST_SILENT", ST_SILENT, CONST_PERSISTENT | CONST_CS);
  479. /* don't return results */
  480. REGISTER_LONG_CONSTANT("ST_SET", ST_SET, CONST_PERSISTENT | CONST_CS);
  481. /* set vs. clear */
  482. /* Copy options */
  483. REGISTER_LONG_CONSTANT("CP_UID", CP_UID, CONST_PERSISTENT | CONST_CS);
  484. /* argument is a UID sequence */
  485. REGISTER_LONG_CONSTANT("CP_MOVE", CP_MOVE, CONST_PERSISTENT | CONST_CS);
  486. /* delete from source after copying */
  487. /* Search/sort options */
  488. REGISTER_LONG_CONSTANT("SE_UID", SE_UID, CONST_PERSISTENT | CONST_CS);
  489. /* return UID */
  490. REGISTER_LONG_CONSTANT("SE_FREE", SE_FREE, CONST_PERSISTENT | CONST_CS);
  491. /* free search program after finished */
  492. REGISTER_LONG_CONSTANT("SE_NOPREFETCH", SE_NOPREFETCH, CONST_PERSISTENT | CONST_CS);
  493. /* no search prefetching */
  494. REGISTER_LONG_CONSTANT("SO_FREE", SO_FREE, CONST_PERSISTENT | CONST_CS);
  495. /* free sort program after finished */
  496. REGISTER_LONG_CONSTANT("SO_NOSERVER", SO_NOSERVER, CONST_PERSISTENT | CONST_CS);
  497. /* don't do server-based sort */
  498. /* Status options */
  499. REGISTER_LONG_CONSTANT("SA_MESSAGES", SA_MESSAGES , CONST_PERSISTENT | CONST_CS);
  500. /* number of messages */
  501. REGISTER_LONG_CONSTANT("SA_RECENT", SA_RECENT, CONST_PERSISTENT | CONST_CS);
  502. /* number of recent messages */
  503. REGISTER_LONG_CONSTANT("SA_UNSEEN", SA_UNSEEN , CONST_PERSISTENT | CONST_CS);
  504. /* number of unseen messages */
  505. REGISTER_LONG_CONSTANT("SA_UIDNEXT", SA_UIDNEXT, CONST_PERSISTENT | CONST_CS);
  506. /* next UID to be assigned */
  507. REGISTER_LONG_CONSTANT("SA_UIDVALIDITY", SA_UIDVALIDITY , CONST_PERSISTENT | CONST_CS);
  508. /* UID validity value */
  509. REGISTER_LONG_CONSTANT("SA_ALL", sa_all, CONST_PERSISTENT | CONST_CS);
  510. /* get all status information */
  511. /* Bits for mm_list() and mm_lsub() */
  512. REGISTER_LONG_CONSTANT("LATT_NOINFERIORS", LATT_NOINFERIORS , CONST_PERSISTENT | CONST_CS);
  513. REGISTER_LONG_CONSTANT("LATT_NOSELECT", LATT_NOSELECT, CONST_PERSISTENT | CONST_CS);
  514. REGISTER_LONG_CONSTANT("LATT_MARKED", LATT_MARKED, CONST_PERSISTENT | CONST_CS);
  515. REGISTER_LONG_CONSTANT("LATT_UNMARKED", LATT_UNMARKED , CONST_PERSISTENT | CONST_CS);
  516. #ifdef LATT_REFERRAL
  517. REGISTER_LONG_CONSTANT("LATT_REFERRAL", LATT_REFERRAL, CONST_PERSISTENT | CONST_CS);
  518. #endif
  519. #ifdef LATT_HASCHILDREN
  520. REGISTER_LONG_CONSTANT("LATT_HASCHILDREN", LATT_HASCHILDREN, CONST_PERSISTENT | CONST_CS);
  521. #endif
  522. #ifdef LATT_HASNOCHILDREN
  523. REGISTER_LONG_CONSTANT("LATT_HASNOCHILDREN", LATT_HASNOCHILDREN, CONST_PERSISTENT | CONST_CS);
  524. #endif
  525. /* Sort functions */
  526. REGISTER_LONG_CONSTANT("SORTDATE", SORTDATE , CONST_PERSISTENT | CONST_CS);
  527. /* date */
  528. REGISTER_LONG_CONSTANT("SORTARRIVAL", SORTARRIVAL , CONST_PERSISTENT | CONST_CS);
  529. /* arrival date */
  530. REGISTER_LONG_CONSTANT("SORTFROM", SORTFROM , CONST_PERSISTENT | CONST_CS);
  531. /* from */
  532. REGISTER_LONG_CONSTANT("SORTSUBJECT", SORTSUBJECT , CONST_PERSISTENT | CONST_CS);
  533. /* subject */
  534. REGISTER_LONG_CONSTANT("SORTTO", SORTTO , CONST_PERSISTENT | CONST_CS);
  535. /* to */
  536. REGISTER_LONG_CONSTANT("SORTCC", SORTCC , CONST_PERSISTENT | CONST_CS);
  537. /* cc */
  538. REGISTER_LONG_CONSTANT("SORTSIZE", SORTSIZE , CONST_PERSISTENT | CONST_CS);
  539. /* size */
  540. REGISTER_LONG_CONSTANT("TYPETEXT", TYPETEXT , CONST_PERSISTENT | CONST_CS);
  541. REGISTER_LONG_CONSTANT("TYPEMULTIPART", TYPEMULTIPART , CONST_PERSISTENT | CONST_CS);
  542. REGISTER_LONG_CONSTANT("TYPEMESSAGE", TYPEMESSAGE , CONST_PERSISTENT | CONST_CS);
  543. REGISTER_LONG_CONSTANT("TYPEAPPLICATION", TYPEAPPLICATION , CONST_PERSISTENT | CONST_CS);
  544. REGISTER_LONG_CONSTANT("TYPEAUDIO", TYPEAUDIO , CONST_PERSISTENT | CONST_CS);
  545. REGISTER_LONG_CONSTANT("TYPEIMAGE", TYPEIMAGE , CONST_PERSISTENT | CONST_CS);
  546. REGISTER_LONG_CONSTANT("TYPEVIDEO", TYPEVIDEO , CONST_PERSISTENT | CONST_CS);
  547. REGISTER_LONG_CONSTANT("TYPEMODEL", TYPEMODEL , CONST_PERSISTENT | CONST_CS);
  548. REGISTER_LONG_CONSTANT("TYPEOTHER", TYPEOTHER , CONST_PERSISTENT | CONST_CS);
  549. /*
  550. TYPETEXT unformatted text
  551. TYPEMULTIPART multiple part
  552. TYPEMESSAGE encapsulated message
  553. TYPEAPPLICATION application data
  554. TYPEAUDIO audio
  555. TYPEIMAGE static image (GIF, JPEG, etc.)
  556. TYPEVIDEO video
  557. TYPEMODEL model
  558. TYPEOTHER unknown
  559. */
  560. REGISTER_LONG_CONSTANT("ENC7BIT", ENC7BIT , CONST_PERSISTENT | CONST_CS);
  561. REGISTER_LONG_CONSTANT("ENC8BIT", ENC8BIT , CONST_PERSISTENT | CONST_CS);
  562. REGISTER_LONG_CONSTANT("ENCBINARY", ENCBINARY , CONST_PERSISTENT | CONST_CS);
  563. REGISTER_LONG_CONSTANT("ENCBASE64", ENCBASE64, CONST_PERSISTENT | CONST_CS);
  564. REGISTER_LONG_CONSTANT("ENCQUOTEDPRINTABLE", ENCQUOTEDPRINTABLE , CONST_PERSISTENT | CONST_CS);
  565. REGISTER_LONG_CONSTANT("ENCOTHER", ENCOTHER , CONST_PERSISTENT | CONST_CS);
  566. /*
  567. ENC7BIT 7 bit SMTP semantic data
  568. ENC8BIT 8 bit SMTP semantic data
  569. ENCBINARY 8 bit binary data
  570. ENCBASE64 base-64 encoded data
  571. ENCQUOTEDPRINTABLE human-readable 8-as-7 bit data
  572. ENCOTHER unknown
  573. */
  574. REGISTER_LONG_CONSTANT("IMAP_GC_ELT", GC_ELT , CONST_PERSISTENT | CONST_CS);
  575. REGISTER_LONG_CONSTANT("IMAP_GC_ENV", GC_ENV , CONST_PERSISTENT | CONST_CS);
  576. REGISTER_LONG_CONSTANT("IMAP_GC_TEXTS", GC_TEXTS , CONST_PERSISTENT | CONST_CS);
  577. /*
  578. GC_ELT message cache elements
  579. GC_ENV ENVELOPEs and BODYs
  580. GC_TEXTS texts
  581. */
  582. if (!IMAPG(enable_rsh)) {
  583. /* disable SSH and RSH, see https://bugs.php.net/bug.php?id=77153 */
  584. mail_parameters (NIL, SET_RSHTIMEOUT, 0);
  585. mail_parameters (NIL, SET_SSHTIMEOUT, 0);
  586. }
  587. return SUCCESS;
  588. }
  589. /* }}} */
  590. /* {{{ PHP_RINIT_FUNCTION */
  591. PHP_RINIT_FUNCTION(imap)
  592. {
  593. IMAPG(imap_errorstack) = NIL;
  594. IMAPG(imap_alertstack) = NIL;
  595. IMAPG(gets_stream) = NIL;
  596. return SUCCESS;
  597. }
  598. /* }}} */
  599. /* {{{ PHP_RSHUTDOWN_FUNCTION */
  600. PHP_RSHUTDOWN_FUNCTION(imap)
  601. {
  602. ERRORLIST *ecur = NIL;
  603. STRINGLIST *acur = NIL;
  604. if (IMAPG(imap_errorstack) != NIL) {
  605. /* output any remaining errors at their original error level */
  606. if (EG(error_reporting) & E_NOTICE) {
  607. zend_try {
  608. ecur = IMAPG(imap_errorstack);
  609. while (ecur != NIL) {
  610. php_error_docref(NULL, E_NOTICE, "%s (errflg=%ld)", ecur->LTEXT, ecur->errflg);
  611. ecur = ecur->next;
  612. }
  613. } zend_end_try();
  614. }
  615. mail_free_errorlist(&IMAPG(imap_errorstack));
  616. IMAPG(imap_errorstack) = NIL;
  617. }
  618. if (IMAPG(imap_alertstack) != NIL) {
  619. /* output any remaining alerts at E_NOTICE level */
  620. if (EG(error_reporting) & E_NOTICE) {
  621. zend_try {
  622. acur = IMAPG(imap_alertstack);
  623. while (acur != NIL) {
  624. php_error_docref(NULL, E_NOTICE, "%s", acur->LTEXT);
  625. acur = acur->next;
  626. }
  627. } zend_end_try();
  628. }
  629. mail_free_stringlist(&IMAPG(imap_alertstack));
  630. IMAPG(imap_alertstack) = NIL;
  631. }
  632. return SUCCESS;
  633. }
  634. /* }}} */
  635. #ifndef CCLIENTVERSION
  636. # if defined(HAVE_IMAP2007e)
  637. # define CCLIENTVERSION "2007e"
  638. # elif defined(HAVE_IMAP2007d)
  639. # define CCLIENTVERSION "2007d"
  640. # elif defined(HAVE_IMAP2007b)
  641. # define CCLIENTVERSION "2007b"
  642. # elif defined(HAVE_IMAP2007a)
  643. # define CCLIENTVERSION "2007a"
  644. # elif defined(HAVE_IMAP2004)
  645. # define CCLIENTVERSION "2004"
  646. # elif defined(HAVE_IMAP2001)
  647. # define CCLIENTVERSION "2001"
  648. # elif defined(HAVE_IMAP2000)
  649. # define CCLIENTVERSION "2000"
  650. # elif defined(IMAP41)
  651. # define CCLIENTVERSION "4.1"
  652. # else
  653. # define CCLIENTVERSION "4.0"
  654. # endif
  655. #endif
  656. /* {{{ PHP_MINFO_FUNCTION */
  657. PHP_MINFO_FUNCTION(imap)
  658. {
  659. php_info_print_table_start();
  660. php_info_print_table_row(2, "IMAP c-Client Version", CCLIENTVERSION);
  661. #ifdef HAVE_IMAP_SSL
  662. php_info_print_table_row(2, "SSL Support", "enabled");
  663. #endif
  664. #if defined(HAVE_IMAP_KRB) && defined(HAVE_IMAP_AUTH_GSS)
  665. php_info_print_table_row(2, "Kerberos Support", "enabled");
  666. #endif
  667. php_info_print_table_end();
  668. DISPLAY_INI_ENTRIES();
  669. }
  670. /* }}} */
  671. /* {{{ Open an IMAP stream to a mailbox */
  672. PHP_FUNCTION(imap_open)
  673. {
  674. zend_string *mailbox, *user, *passwd;
  675. zend_long retries = 0, flags = 0, cl_flags = 0;
  676. MAILSTREAM *imap_stream;
  677. HashTable *params = NULL;
  678. if (zend_parse_parameters(ZEND_NUM_ARGS(), "PSS|llh", &mailbox, &user, &passwd, &flags, &retries, &params) == FAILURE) {
  679. RETURN_THROWS();
  680. }
  681. /* Check for PHP_EXPUNGE and not CL_EXPUNGE as the user land facing CL_EXPUNGE constant is defined
  682. * to something different to prevent clashes between CL_EXPUNGE and an OP_* constant allowing setting
  683. * the CL_EXPUNGE flag which will expunge when the mailbox is closed (be that manually, or via the
  684. * IMAP\Connection object being destroyed naturally at the end of the PHP script */
  685. if (flags && ((flags & ~(OP_READONLY | OP_ANONYMOUS | OP_HALFOPEN | PHP_EXPUNGE | OP_DEBUG | OP_SHORTCACHE
  686. | OP_SILENT | OP_PROTOTYPE | OP_SECURE)) != 0)) {
  687. zend_argument_value_error(4, "must be a bitmask of the OP_* constants, and CL_EXPUNGE");
  688. RETURN_THROWS();
  689. }
  690. if (retries < 0) {
  691. zend_argument_value_error(5, "must be greater than or equal to 0");
  692. RETURN_THROWS();
  693. }
  694. if (flags) {
  695. if (flags & PHP_EXPUNGE) {
  696. cl_flags = CL_EXPUNGE;
  697. flags ^= PHP_EXPUNGE;
  698. }
  699. if (flags & OP_PROTOTYPE) {
  700. cl_flags |= OP_PROTOTYPE;
  701. }
  702. }
  703. if (params) {
  704. zval *disabled_auth_method;
  705. if ((disabled_auth_method = zend_hash_str_find(params, "DISABLE_AUTHENTICATOR", sizeof("DISABLE_AUTHENTICATOR") - 1)) != NULL) {
  706. switch (Z_TYPE_P(disabled_auth_method)) {
  707. case IS_STRING:
  708. if (Z_STRLEN_P(disabled_auth_method) > 1) {
  709. mail_parameters(NIL, DISABLE_AUTHENTICATOR, (void *)Z_STRVAL_P(disabled_auth_method));
  710. }
  711. break;
  712. case IS_ARRAY:
  713. {
  714. zval *z_auth_method;
  715. int i;
  716. int nelems = zend_hash_num_elements(Z_ARRVAL_P(disabled_auth_method));
  717. if (nelems == 0 ) {
  718. break;
  719. }
  720. for (i = 0; i < nelems; i++) {
  721. if ((z_auth_method = zend_hash_index_find(Z_ARRVAL_P(disabled_auth_method), i)) != NULL) {
  722. if (Z_TYPE_P(z_auth_method) == IS_STRING) {
  723. if (Z_STRLEN_P(z_auth_method) > 1) {
  724. mail_parameters(NIL, DISABLE_AUTHENTICATOR, (void *)Z_STRVAL_P(z_auth_method));
  725. }
  726. } else {
  727. zend_argument_type_error(6, "option \"DISABLE_AUTHENTICATOR\" must be a string or an array of strings");
  728. RETURN_THROWS();
  729. }
  730. }
  731. }
  732. }
  733. break;
  734. default:
  735. zend_argument_type_error(6, "option \"DISABLE_AUTHENTICATOR\" must be a string or an array of strings");
  736. RETURN_THROWS();
  737. }
  738. }
  739. }
  740. if (IMAPG(imap_user)) {
  741. efree(IMAPG(imap_user));
  742. IMAPG(imap_user) = 0;
  743. }
  744. if (IMAPG(imap_password)) {
  745. efree(IMAPG(imap_password));
  746. IMAPG(imap_password) = 0;
  747. }
  748. /* local filename, need to perform open_basedir check */
  749. if (ZSTR_VAL(mailbox)[0] != '{' && php_check_open_basedir(ZSTR_VAL(mailbox))) {
  750. RETURN_FALSE;
  751. }
  752. IMAPG(imap_user) = estrndup(ZSTR_VAL(user), ZSTR_LEN(user));
  753. IMAPG(imap_password) = estrndup(ZSTR_VAL(passwd), ZSTR_LEN(passwd));
  754. #ifdef SET_MAXLOGINTRIALS
  755. if (retries) {
  756. mail_parameters(NIL, SET_MAXLOGINTRIALS, (void *) retries);
  757. }
  758. #endif
  759. ZEND_IGNORE_LEAKS_BEGIN();
  760. imap_stream = mail_open(NIL, ZSTR_VAL(mailbox), flags);
  761. ZEND_IGNORE_LEAKS_END();
  762. if (imap_stream == NIL) {
  763. php_error_docref(NULL, E_WARNING, "Couldn't open stream %s", ZSTR_VAL(mailbox));
  764. efree(IMAPG(imap_user)); IMAPG(imap_user) = 0;
  765. efree(IMAPG(imap_password)); IMAPG(imap_password) = 0;
  766. RETURN_FALSE;
  767. }
  768. object_init_ex(return_value, php_imap_ce);
  769. imap_object_from_zend_object(Z_OBJ_P(return_value))->imap_stream = imap_stream;
  770. imap_object_from_zend_object(Z_OBJ_P(return_value))->flags = cl_flags;
  771. }
  772. /* }}} */
  773. /* {{{ Reopen an IMAP stream to a new mailbox */
  774. PHP_FUNCTION(imap_reopen)
  775. {
  776. zval *imap_conn_obj;
  777. zend_string *mailbox;
  778. zend_long options = 0, retries = 0;
  779. php_imap_object *imap_conn_struct;
  780. long flags = 0;
  781. long cl_flags = 0;
  782. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS|ll", &imap_conn_obj, php_imap_ce, &mailbox, &options, &retries) == FAILURE) {
  783. RETURN_THROWS();
  784. }
  785. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  786. /* TODO Verify these are the only options available as they are pulled from the php.net documentation */
  787. /* Check for PHP_EXPUNGE and not CL_EXPUNGE as the user land facing CL_EXPUNGE constant is defined
  788. * to something different to prevent clashes between CL_EXPUNGE and an OP_* constant allowing setting
  789. * the CL_EXPUNGE flag which will expunge when the mailbox is closed (be that manually, or via the
  790. * IMAP\Connection object being destroyed naturally at the end of the PHP script */
  791. if (options && ((options & ~(OP_READONLY | OP_ANONYMOUS | OP_HALFOPEN | OP_EXPUNGE | PHP_EXPUNGE)) != 0)) {
  792. zend_argument_value_error(3, "must be a bitmask of OP_READONLY, OP_ANONYMOUS, OP_HALFOPEN, "
  793. "OP_EXPUNGE, and CL_EXPUNGE");
  794. RETURN_THROWS();
  795. }
  796. if (retries < 0) {
  797. zend_argument_value_error(4, "must be greater than or equal to 0");
  798. RETURN_THROWS();
  799. }
  800. if (options) {
  801. flags = options;
  802. if (flags & PHP_EXPUNGE) {
  803. cl_flags = CL_EXPUNGE;
  804. flags ^= PHP_EXPUNGE;
  805. }
  806. imap_conn_struct->flags = cl_flags;
  807. }
  808. #ifdef SET_MAXLOGINTRIALS
  809. if (retries) {
  810. mail_parameters(NIL, SET_MAXLOGINTRIALS, (void *) retries);
  811. }
  812. #endif
  813. /* local filename, need to perform open_basedir check */
  814. if (ZSTR_VAL(mailbox)[0] != '{' && php_check_open_basedir(ZSTR_VAL(mailbox))) {
  815. RETURN_FALSE;
  816. }
  817. imap_conn_struct->imap_stream = mail_open(imap_conn_struct->imap_stream, ZSTR_VAL(mailbox), flags);
  818. if (imap_conn_struct->imap_stream == NIL) {
  819. /* IMAP\Connection object will release it self. */
  820. php_error_docref(NULL, E_WARNING, "Couldn't re-open stream");
  821. RETURN_FALSE;
  822. }
  823. RETURN_TRUE;
  824. }
  825. /* }}} */
  826. /* {{{ Append a new message to a specified mailbox */
  827. PHP_FUNCTION(imap_append)
  828. {
  829. zval *imap_conn_obj;
  830. zend_string *folder, *message, *internal_date = NULL, *flags = NULL;
  831. php_imap_object *imap_conn_struct;
  832. STRING st;
  833. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS|S!S!", &imap_conn_obj, php_imap_ce, &folder, &message, &flags, &internal_date) == FAILURE) {
  834. RETURN_THROWS();
  835. }
  836. if (internal_date) {
  837. zend_string *regex = zend_string_init("/[0-3][0-9]-((Jan)|(Feb)|(Mar)|(Apr)|(May)|(Jun)|(Jul)|(Aug)|(Sep)|(Oct)|(Nov)|(Dec))-[0-9]{4} [0-2][0-9]:[0-5][0-9]:[0-5][0-9] [+-][0-9]{4}/", sizeof("/[0-3][0-9]-((Jan)|(Feb)|(Mar)|(Apr)|(May)|(Jun)|(Jul)|(Aug)|(Sep)|(Oct)|(Nov)|(Dec))-[0-9]{4} [0-2][0-9]:[0-5][0-9]:[0-5][0-9] [+-][0-9]{4}/") - 1, 0);
  838. pcre_cache_entry *pce; /* Compiled regex */
  839. zval *subpats = NULL; /* Parts (not used) */
  840. int global = 0;
  841. /* Make sure the given internal_date string matches the RFC specifiedformat */
  842. if ((pce = pcre_get_compiled_regex_cache(regex))== NULL) {
  843. zend_string_release(regex);
  844. RETURN_FALSE;
  845. }
  846. zend_string_release(regex);
  847. php_pcre_match_impl(pce, internal_date, return_value, subpats, global,
  848. 0, Z_L(0), Z_L(0));
  849. if (!Z_LVAL_P(return_value)) {
  850. // TODO Promoto to error?
  851. php_error_docref(NULL, E_WARNING, "Internal date not correctly formatted");
  852. internal_date = NULL;
  853. }
  854. }
  855. /* TODO Check if flags are valid (documentation is not present on php.net so need to check this first) */
  856. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  857. INIT (&st, mail_string, (void *) ZSTR_VAL(message), ZSTR_LEN(message));
  858. if (mail_append_full(imap_conn_struct->imap_stream, ZSTR_VAL(folder), (flags ? ZSTR_VAL(flags) : NIL), (internal_date ? ZSTR_VAL(internal_date) : NIL), &st)) {
  859. RETURN_TRUE;
  860. } else {
  861. RETURN_FALSE;
  862. }
  863. }
  864. /* }}} */
  865. /* {{{ Gives the number of messages in the current mailbox */
  866. PHP_FUNCTION(imap_num_msg)
  867. {
  868. zval *imap_conn_obj;
  869. php_imap_object *imap_conn_struct;
  870. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &imap_conn_obj, php_imap_ce) == FAILURE) {
  871. RETURN_THROWS();
  872. }
  873. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  874. RETURN_LONG(imap_conn_struct->imap_stream->nmsgs);
  875. }
  876. /* }}} */
  877. /* {{{ Check if the IMAP stream is still active */
  878. PHP_FUNCTION(imap_ping)
  879. {
  880. zval *imap_conn_obj;
  881. php_imap_object *imap_conn_struct;
  882. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &imap_conn_obj, php_imap_ce) == FAILURE) {
  883. RETURN_THROWS();
  884. }
  885. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  886. RETURN_BOOL(mail_ping(imap_conn_struct->imap_stream));
  887. }
  888. /* }}} */
  889. /* {{{ Gives the number of recent messages in current mailbox */
  890. PHP_FUNCTION(imap_num_recent)
  891. {
  892. zval *imap_conn_obj;
  893. php_imap_object *imap_conn_struct;
  894. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &imap_conn_obj, php_imap_ce) == FAILURE) {
  895. RETURN_THROWS();
  896. }
  897. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  898. RETURN_LONG(imap_conn_struct->imap_stream->recent);
  899. }
  900. /* }}} */
  901. #if defined(HAVE_IMAP2000) || defined(HAVE_IMAP2001)
  902. /* {{{ Returns the quota set to the mailbox account qroot */
  903. PHP_FUNCTION(imap_get_quota)
  904. {
  905. zval *imap_conn_obj;
  906. zend_string *qroot;
  907. php_imap_object *imap_conn_struct;
  908. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &imap_conn_obj, php_imap_ce, &qroot) == FAILURE) {
  909. RETURN_THROWS();
  910. }
  911. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  912. array_init(return_value);
  913. IMAPG(quota_return) = &return_value;
  914. /* set the callback for the GET_QUOTA function */
  915. mail_parameters(NIL, SET_QUOTA, (void *) mail_getquota);
  916. if (!imap_getquota(imap_conn_struct->imap_stream, ZSTR_VAL(qroot))) {
  917. php_error_docref(NULL, E_WARNING, "C-client imap_getquota failed");
  918. zend_array_destroy(Z_ARR_P(return_value));
  919. RETURN_FALSE;
  920. }
  921. }
  922. /* }}} */
  923. /* {{{ Returns the quota set to the mailbox account mbox */
  924. PHP_FUNCTION(imap_get_quotaroot)
  925. {
  926. zval *imap_conn_obj;
  927. zend_string *mbox;
  928. php_imap_object *imap_conn_struct;
  929. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &imap_conn_obj, php_imap_ce, &mbox) == FAILURE) {
  930. RETURN_THROWS();
  931. }
  932. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  933. array_init(return_value);
  934. IMAPG(quota_return) = &return_value;
  935. /* set the callback for the GET_QUOTAROOT function */
  936. mail_parameters(NIL, SET_QUOTA, (void *) mail_getquota);
  937. if (!imap_getquotaroot(imap_conn_struct->imap_stream, ZSTR_VAL(mbox))) {
  938. php_error_docref(NULL, E_WARNING, "C-client imap_getquotaroot failed");
  939. zend_array_destroy(Z_ARR_P(return_value));
  940. RETURN_FALSE;
  941. }
  942. }
  943. /* }}} */
  944. /* {{{ Will set the quota for qroot mailbox */
  945. PHP_FUNCTION(imap_set_quota)
  946. {
  947. zval *imap_conn_obj;
  948. zend_string *qroot;
  949. zend_long mailbox_size;
  950. php_imap_object *imap_conn_struct;
  951. STRINGLIST limits;
  952. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSl", &imap_conn_obj, php_imap_ce, &qroot, &mailbox_size) == FAILURE) {
  953. RETURN_THROWS();
  954. }
  955. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  956. limits.text.data = (unsigned char*)"STORAGE";
  957. limits.text.size = mailbox_size;
  958. limits.next = NIL;
  959. RETURN_BOOL(imap_setquota(imap_conn_struct->imap_stream, ZSTR_VAL(qroot), &limits));
  960. }
  961. /* }}} */
  962. /* {{{ Sets the ACL for a given mailbox */
  963. PHP_FUNCTION(imap_setacl)
  964. {
  965. zval *imap_conn_obj;
  966. zend_string *mailbox, *id, *rights;
  967. php_imap_object *imap_conn_struct;
  968. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSSS", &imap_conn_obj, php_imap_ce, &mailbox, &id, &rights) == FAILURE) {
  969. RETURN_THROWS();
  970. }
  971. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  972. RETURN_BOOL(imap_setacl(imap_conn_struct->imap_stream, ZSTR_VAL(mailbox), ZSTR_VAL(id), ZSTR_VAL(rights)));
  973. }
  974. /* }}} */
  975. /* {{{ Gets the ACL for a given mailbox */
  976. PHP_FUNCTION(imap_getacl)
  977. {
  978. zval *imap_conn_obj;
  979. zend_string *mailbox;
  980. php_imap_object *imap_conn_struct;
  981. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &imap_conn_obj, php_imap_ce, &mailbox) == FAILURE) {
  982. RETURN_THROWS();
  983. }
  984. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  985. /* initializing the special array for the return values */
  986. array_init(return_value);
  987. IMAPG(imap_acl_list) = return_value;
  988. /* set the callback for the GET_ACL function */
  989. mail_parameters(NIL, SET_ACL, (void *) mail_getacl);
  990. if (!imap_getacl(imap_conn_struct->imap_stream, ZSTR_VAL(mailbox))) {
  991. php_error(E_WARNING, "c-client imap_getacl failed");
  992. zend_array_destroy(Z_ARR_P(return_value));
  993. RETURN_FALSE;
  994. }
  995. IMAPG(imap_acl_list) = NIL;
  996. }
  997. /* }}} */
  998. #endif /* HAVE_IMAP2000 || HAVE_IMAP2001 */
  999. /* {{{ Permanently delete all messages marked for deletion */
  1000. PHP_FUNCTION(imap_expunge)
  1001. {
  1002. zval *imap_conn_obj;
  1003. php_imap_object *imap_conn_struct;
  1004. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &imap_conn_obj, php_imap_ce) == FAILURE) {
  1005. RETURN_THROWS();
  1006. }
  1007. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1008. mail_expunge (imap_conn_struct->imap_stream);
  1009. RETURN_TRUE;
  1010. }
  1011. /* }}} */
  1012. /* {{{ This function garbage collects (purges) the cache of entries of a specific type. */
  1013. PHP_FUNCTION(imap_gc)
  1014. {
  1015. zval *imap_conn_obj;
  1016. php_imap_object *imap_conn_struct;
  1017. zend_long flags;
  1018. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &imap_conn_obj, php_imap_ce, &flags) == FAILURE) {
  1019. RETURN_THROWS();
  1020. }
  1021. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1022. if (flags && ((flags & ~(GC_TEXTS | GC_ELT | GC_ENV)) != 0)) {
  1023. zend_argument_value_error(2, "must be a bitmask of IMAP_GC_TEXTS, IMAP_GC_ELT, and IMAP_GC_ENV");
  1024. RETURN_THROWS();
  1025. }
  1026. mail_gc(imap_conn_struct->imap_stream, flags);
  1027. // TODO Return void?
  1028. RETURN_TRUE;
  1029. }
  1030. /* }}} */
  1031. /* {{{ Close an IMAP stream */
  1032. PHP_FUNCTION(imap_close)
  1033. {
  1034. zval *imap_conn_obj;
  1035. php_imap_object *imap_conn_struct = NULL;
  1036. zend_long options = 0;
  1037. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|l", &imap_conn_obj, php_imap_ce, &options) == FAILURE) {
  1038. RETURN_THROWS();
  1039. }
  1040. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1041. if (options) {
  1042. /* Check that flags is exactly equal to PHP_EXPUNGE or zero */
  1043. if (options && ((options & ~PHP_EXPUNGE) != 0)) {
  1044. zend_argument_value_error(2, "must be CL_EXPUNGE or 0");
  1045. RETURN_THROWS();
  1046. }
  1047. /* Do the translation from PHP's internal PHP_EXPUNGE define to c-client's CL_EXPUNGE */
  1048. if (options & PHP_EXPUNGE) {
  1049. options ^= PHP_EXPUNGE;
  1050. options |= CL_EXPUNGE;
  1051. }
  1052. imap_conn_struct->flags = options;
  1053. }
  1054. /* Do not try to close prototype streams */
  1055. if (!(imap_conn_struct->flags & OP_PROTOTYPE)) {
  1056. mail_close_full(imap_conn_struct->imap_stream, imap_conn_struct->flags);
  1057. imap_conn_struct->imap_stream = NULL;
  1058. }
  1059. // TODO Return void?
  1060. RETURN_TRUE;
  1061. }
  1062. /* }}} */
  1063. /* {{{ Returns headers for all messages in a mailbox */
  1064. PHP_FUNCTION(imap_headers)
  1065. {
  1066. zval *imap_conn_obj;
  1067. php_imap_object *imap_conn_struct;
  1068. unsigned long i;
  1069. char *t;
  1070. unsigned int msgno;
  1071. char tmp[MAILTMPLEN];
  1072. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &imap_conn_obj, php_imap_ce) == FAILURE) {
  1073. RETURN_THROWS();
  1074. }
  1075. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1076. /* Initialize return array */
  1077. array_init(return_value);
  1078. for (msgno = 1; msgno <= imap_conn_struct->imap_stream->nmsgs; msgno++) {
  1079. MESSAGECACHE * cache = mail_elt (imap_conn_struct->imap_stream, msgno);
  1080. mail_fetchstructure(imap_conn_struct->imap_stream, msgno, NIL);
  1081. tmp[0] = cache->recent ? (cache->seen ? 'R': 'N') : ' ';
  1082. tmp[1] = (cache->recent | cache->seen) ? ' ' : 'U';
  1083. tmp[2] = cache->flagged ? 'F' : ' ';
  1084. tmp[3] = cache->answered ? 'A' : ' ';
  1085. tmp[4] = cache->deleted ? 'D' : ' ';
  1086. tmp[5] = cache->draft ? 'X' : ' ';
  1087. snprintf(tmp + 6, sizeof(tmp) - 6, "%4ld) ", cache->msgno);
  1088. mail_date(tmp+11, cache);
  1089. tmp[22] = ' ';
  1090. tmp[23] = '\0';
  1091. mail_fetchfrom(tmp+23, imap_conn_struct->imap_stream, msgno, (long)20);
  1092. strcat(tmp, " ");
  1093. if ((i = cache->user_flags)) {
  1094. strcat(tmp, "{");
  1095. while (i) {
  1096. strlcat(tmp, imap_conn_struct->imap_stream->user_flags[find_rightmost_bit (&i)], sizeof(tmp));
  1097. if (i) strlcat(tmp, " ", sizeof(tmp));
  1098. }
  1099. strlcat(tmp, "} ", sizeof(tmp));
  1100. }
  1101. mail_fetchsubject(t = tmp + strlen(tmp), imap_conn_struct->imap_stream, msgno, (long)25);
  1102. snprintf(t += strlen(t), sizeof(tmp) - strlen(tmp), " (%ld chars)", cache->rfc822_size);
  1103. add_next_index_string(return_value, tmp);
  1104. }
  1105. }
  1106. /* }}} */
  1107. /* {{{ Read the message body */
  1108. PHP_FUNCTION(imap_body)
  1109. {
  1110. zval *imap_conn_obj;
  1111. zend_long msgno, flags = 0;
  1112. php_imap_object *imap_conn_struct;
  1113. char *body;
  1114. unsigned long body_len = 0;
  1115. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol|l", &imap_conn_obj, php_imap_ce, &msgno, &flags) == FAILURE) {
  1116. RETURN_THROWS();
  1117. }
  1118. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1119. PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgno, 2);
  1120. if (flags && ((flags & ~(FT_UID|FT_PEEK|FT_INTERNAL)) != 0)) {
  1121. zend_argument_value_error(3, "must be a bitmask of FT_UID, FT_PEEK, and FT_INTERNAL");
  1122. RETURN_THROWS();
  1123. }
  1124. PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgno, 2, flags, FT_UID);
  1125. body = mail_fetchtext_full (imap_conn_struct->imap_stream, msgno, &body_len, flags);
  1126. if (body_len == 0) {
  1127. RETVAL_EMPTY_STRING();
  1128. } else {
  1129. RETVAL_STRINGL(body, body_len);
  1130. }
  1131. }
  1132. /* }}} */
  1133. /* TODO UID Tests */
  1134. /* {{{ Copy specified message to a mailbox */
  1135. PHP_FUNCTION(imap_mail_copy)
  1136. {
  1137. zval *imap_conn_obj;
  1138. zend_long options = 0;
  1139. zend_string *seq, *folder;
  1140. php_imap_object *imap_conn_struct;
  1141. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS|l", &imap_conn_obj, php_imap_ce, &seq, &folder, &options) == FAILURE) {
  1142. RETURN_THROWS();
  1143. }
  1144. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1145. if (options && ((options & ~(CP_UID | CP_MOVE)) != 0)) {
  1146. zend_argument_value_error(4, "must be a bitmask of CP_UID, and CP_MOVE");
  1147. RETURN_THROWS();
  1148. }
  1149. if (mail_copy_full(imap_conn_struct->imap_stream, ZSTR_VAL(seq), ZSTR_VAL(folder), options) == T) {
  1150. RETURN_TRUE;
  1151. } else {
  1152. RETURN_FALSE;
  1153. }
  1154. }
  1155. /* }}} */
  1156. /* TODO UID Tests */
  1157. /* {{{ Move specified message to a mailbox */
  1158. PHP_FUNCTION(imap_mail_move)
  1159. {
  1160. zval *imap_conn_obj;
  1161. zend_string *seq, *folder;
  1162. zend_long options = 0;
  1163. php_imap_object *imap_conn_struct;
  1164. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS|l", &imap_conn_obj, php_imap_ce, &seq, &folder, &options) == FAILURE) {
  1165. RETURN_THROWS();
  1166. }
  1167. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1168. if (options && ((options & ~CP_UID) != 0)) {
  1169. zend_argument_value_error(4, "must be CP_UID or 0");
  1170. RETURN_THROWS();
  1171. }
  1172. /* Add CP_MOVE flag */
  1173. options = (options | CP_MOVE);
  1174. if (mail_copy_full(imap_conn_struct->imap_stream, ZSTR_VAL(seq), ZSTR_VAL(folder), options) == T) {
  1175. RETURN_TRUE;
  1176. } else {
  1177. RETURN_FALSE;
  1178. }
  1179. }
  1180. /* }}} */
  1181. /* {{{ Create a new mailbox */
  1182. PHP_FUNCTION(imap_createmailbox)
  1183. {
  1184. zval *imap_conn_obj;
  1185. zend_string *folder;
  1186. php_imap_object *imap_conn_struct;
  1187. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &imap_conn_obj, php_imap_ce, &folder) == FAILURE) {
  1188. RETURN_THROWS();
  1189. }
  1190. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1191. if (mail_create(imap_conn_struct->imap_stream, ZSTR_VAL(folder)) == T) {
  1192. RETURN_TRUE;
  1193. } else {
  1194. RETURN_FALSE;
  1195. }
  1196. }
  1197. /* }}} */
  1198. /* {{{ Rename a mailbox */
  1199. PHP_FUNCTION(imap_renamemailbox)
  1200. {
  1201. zval *imap_conn_obj;
  1202. zend_string *old_mailbox, *new_mailbox;
  1203. php_imap_object *imap_conn_struct;
  1204. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS", &imap_conn_obj, php_imap_ce, &old_mailbox, &new_mailbox) == FAILURE) {
  1205. RETURN_THROWS();
  1206. }
  1207. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1208. if (mail_rename(imap_conn_struct->imap_stream, ZSTR_VAL(old_mailbox), ZSTR_VAL(new_mailbox)) == T) {
  1209. RETURN_TRUE;
  1210. } else {
  1211. RETURN_FALSE;
  1212. }
  1213. }
  1214. /* }}} */
  1215. /* {{{ Delete a mailbox */
  1216. PHP_FUNCTION(imap_deletemailbox)
  1217. {
  1218. zval *imap_conn_obj;
  1219. zend_string *folder;
  1220. php_imap_object *imap_conn_struct;
  1221. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &imap_conn_obj, php_imap_ce, &folder) == FAILURE) {
  1222. RETURN_THROWS();
  1223. }
  1224. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1225. if (mail_delete(imap_conn_struct->imap_stream, ZSTR_VAL(folder)) == T) {
  1226. RETURN_TRUE;
  1227. } else {
  1228. RETURN_FALSE;
  1229. }
  1230. }
  1231. /* }}} */
  1232. /* {{{ Read the list of mailboxes */
  1233. PHP_FUNCTION(imap_list)
  1234. {
  1235. zval *imap_conn_obj;
  1236. zend_string *ref, *pat;
  1237. php_imap_object *imap_conn_struct;
  1238. STRINGLIST *cur=NIL;
  1239. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS", &imap_conn_obj, php_imap_ce, &ref, &pat) == FAILURE) {
  1240. RETURN_THROWS();
  1241. }
  1242. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1243. /* set flag for normal, old mailbox list */
  1244. IMAPG(folderlist_style) = FLIST_ARRAY;
  1245. IMAPG(imap_folders) = IMAPG(imap_folders_tail) = NIL;
  1246. mail_list(imap_conn_struct->imap_stream, ZSTR_VAL(ref), ZSTR_VAL(pat));
  1247. if (IMAPG(imap_folders) == NIL) {
  1248. RETURN_FALSE;
  1249. }
  1250. array_init(return_value);
  1251. cur=IMAPG(imap_folders);
  1252. while (cur != NIL) {
  1253. add_next_index_string(return_value, (char*)cur->LTEXT);
  1254. cur=cur->next;
  1255. }
  1256. mail_free_stringlist (&IMAPG(imap_folders));
  1257. IMAPG(imap_folders) = IMAPG(imap_folders_tail) = NIL;
  1258. }
  1259. /* }}} */
  1260. /* {{{ Reads the list of mailboxes and returns a full array of objects containing name, attributes, and delimiter */
  1261. /* Author: CJH */
  1262. PHP_FUNCTION(imap_getmailboxes)
  1263. {
  1264. zval *imap_conn_obj, mboxob;
  1265. zend_string *ref, *pat;
  1266. php_imap_object *imap_conn_struct;
  1267. FOBJECTLIST *cur=NIL;
  1268. char *delim=NIL;
  1269. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS", &imap_conn_obj, php_imap_ce, &ref, &pat) == FAILURE) {
  1270. RETURN_THROWS();
  1271. }
  1272. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1273. /* set flag for new, improved array of objects mailbox list */
  1274. IMAPG(folderlist_style) = FLIST_OBJECT;
  1275. IMAPG(imap_folder_objects) = IMAPG(imap_folder_objects_tail) = NIL;
  1276. mail_list(imap_conn_struct->imap_stream, ZSTR_VAL(ref), ZSTR_VAL(pat));
  1277. if (IMAPG(imap_folder_objects) == NIL) {
  1278. RETURN_FALSE;
  1279. }
  1280. array_init(return_value);
  1281. delim = safe_emalloc(2, sizeof(char), 0);
  1282. cur=IMAPG(imap_folder_objects);
  1283. while (cur != NIL) {
  1284. object_init(&mboxob);
  1285. add_property_string(&mboxob, "name", (char*)cur->LTEXT);
  1286. add_property_long(&mboxob, "attributes", cur->attributes);
  1287. #ifdef IMAP41
  1288. delim[0] = (char)cur->delimiter;
  1289. delim[1] = 0;
  1290. add_property_string(&mboxob, "delimiter", delim);
  1291. #else
  1292. add_property_string(&mboxob, "delimiter", cur->delimiter);
  1293. #endif
  1294. php_imap_list_add_object(return_value, &mboxob);
  1295. cur=cur->next;
  1296. }
  1297. mail_free_foblist(&IMAPG(imap_folder_objects), &IMAPG(imap_folder_objects_tail));
  1298. efree(delim);
  1299. IMAPG(folderlist_style) = FLIST_ARRAY; /* reset to default */
  1300. }
  1301. /* }}} */
  1302. /* {{{ Read list of mailboxes containing a certain string */
  1303. PHP_FUNCTION(imap_listscan)
  1304. {
  1305. zval *imap_conn_obj;
  1306. zend_string *ref, *pat, *content;
  1307. php_imap_object *imap_conn_struct;
  1308. STRINGLIST *cur=NIL;
  1309. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSSS", &imap_conn_obj, php_imap_ce, &ref, &pat, &content) == FAILURE) {
  1310. RETURN_THROWS();
  1311. }
  1312. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1313. IMAPG(imap_folders) = NIL;
  1314. mail_scan(imap_conn_struct->imap_stream, ZSTR_VAL(ref), ZSTR_VAL(pat), ZSTR_VAL(content));
  1315. if (IMAPG(imap_folders) == NIL) {
  1316. RETURN_FALSE;
  1317. }
  1318. array_init(return_value);
  1319. cur=IMAPG(imap_folders);
  1320. while (cur != NIL) {
  1321. add_next_index_string(return_value, (char*)cur->LTEXT);
  1322. cur=cur->next;
  1323. }
  1324. mail_free_stringlist (&IMAPG(imap_folders));
  1325. IMAPG(imap_folders) = IMAPG(imap_folders_tail) = NIL;
  1326. }
  1327. /* }}} */
  1328. /* {{{ Get mailbox properties */
  1329. PHP_FUNCTION(imap_check)
  1330. {
  1331. zval *imap_conn_obj;
  1332. php_imap_object *imap_conn_struct;
  1333. char date[100];
  1334. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &imap_conn_obj, php_imap_ce) == FAILURE) {
  1335. RETURN_THROWS();
  1336. }
  1337. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1338. if (mail_ping (imap_conn_struct->imap_stream) == NIL) {
  1339. RETURN_FALSE;
  1340. }
  1341. if (imap_conn_struct->imap_stream && imap_conn_struct->imap_stream->mailbox) {
  1342. rfc822_date(date);
  1343. object_init(return_value);
  1344. add_property_string(return_value, "Date", date);
  1345. add_property_string(return_value, "Driver", imap_conn_struct->imap_stream->dtb->name);
  1346. add_property_string(return_value, "Mailbox", imap_conn_struct->imap_stream->mailbox);
  1347. add_property_long(return_value, "Nmsgs", imap_conn_struct->imap_stream->nmsgs);
  1348. add_property_long(return_value, "Recent", imap_conn_struct->imap_stream->recent);
  1349. } else {
  1350. RETURN_FALSE;
  1351. }
  1352. }
  1353. /* }}} */
  1354. /* {{{ Mark a message for deletion */
  1355. PHP_FUNCTION(imap_delete)
  1356. {
  1357. zval *imap_conn_obj;
  1358. php_imap_object *imap_conn_struct;
  1359. zend_string *sequence;
  1360. zend_long flags = 0;
  1361. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS|l", &imap_conn_obj, php_imap_ce, &sequence, &flags) == FAILURE) {
  1362. RETURN_THROWS();
  1363. }
  1364. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1365. // TODO Check sequence validity?
  1366. if (flags && ((flags & ~FT_UID) != 0)) {
  1367. zend_argument_value_error(3, "must be FT_UID or 0");
  1368. RETURN_THROWS();
  1369. }
  1370. mail_setflag_full(imap_conn_struct->imap_stream, ZSTR_VAL(sequence), "\\DELETED", flags);
  1371. // TODO Return void?
  1372. RETURN_TRUE;
  1373. }
  1374. /* }}} */
  1375. /* {{{ Remove the delete flag from a message */
  1376. PHP_FUNCTION(imap_undelete)
  1377. {
  1378. zval *imap_conn_obj;
  1379. zend_string *sequence;
  1380. zend_long flags = 0;
  1381. php_imap_object *imap_conn_struct;
  1382. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS|l", &imap_conn_obj, php_imap_ce, &sequence, &flags) == FAILURE) {
  1383. RETURN_THROWS();
  1384. }
  1385. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1386. /* TODO Check if flags are valid (documentation is not present on php.net so need to check this first) */
  1387. mail_clearflag_full(imap_conn_struct->imap_stream, ZSTR_VAL(sequence), "\\DELETED", flags);
  1388. // TODO Return void?
  1389. RETURN_TRUE;
  1390. }
  1391. /* }}} */
  1392. /* {{{ Read the headers of the message */
  1393. PHP_FUNCTION(imap_headerinfo)
  1394. {
  1395. zval *imap_conn_obj;
  1396. zend_long msgno, fromlength = 0, subjectlength = 0;
  1397. php_imap_object *imap_conn_struct;
  1398. MESSAGECACHE *cache;
  1399. ENVELOPE *en;
  1400. char dummy[2000], fulladdress[MAILTMPLEN + 1];
  1401. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol|ll", &imap_conn_obj, php_imap_ce, &msgno, &fromlength, &subjectlength) == FAILURE) {
  1402. RETURN_THROWS();
  1403. }
  1404. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1405. PHP_IMAP_CHECK_MSGNO(msgno, 2);
  1406. if (fromlength < 0 || fromlength > MAILTMPLEN) {
  1407. zend_argument_value_error(3, "must be between 0 and %d", MAILTMPLEN);
  1408. RETURN_THROWS();
  1409. }
  1410. if (subjectlength < 0 || subjectlength > MAILTMPLEN) {
  1411. zend_argument_value_error(4, "must be between 0 and %d", MAILTMPLEN);
  1412. RETURN_THROWS();
  1413. }
  1414. if (mail_fetchstructure(imap_conn_struct->imap_stream, msgno, NIL)) {
  1415. cache = mail_elt(imap_conn_struct->imap_stream, msgno);
  1416. } else {
  1417. RETURN_FALSE;
  1418. }
  1419. en = mail_fetchenvelope(imap_conn_struct->imap_stream, msgno);
  1420. /* call a function to parse all the text, so that we can use the
  1421. same function to parse text from other sources */
  1422. _php_make_header_object(return_value, en);
  1423. /* now run through properties that are only going to be returned
  1424. from a server, not text headers */
  1425. add_property_string(return_value, "Recent", cache->recent ? (cache->seen ? "R": "N") : " ");
  1426. add_property_string(return_value, "Unseen", (cache->recent | cache->seen) ? " " : "U");
  1427. add_property_string(return_value, "Flagged", cache->flagged ? "F" : " ");
  1428. add_property_string(return_value, "Answered", cache->answered ? "A" : " ");
  1429. add_property_string(return_value, "Deleted", cache->deleted ? "D" : " ");
  1430. add_property_string(return_value, "Draft", cache->draft ? "X" : " ");
  1431. snprintf(dummy, sizeof(dummy), "%4ld", cache->msgno);
  1432. add_property_string(return_value, "Msgno", dummy);
  1433. mail_date(dummy, cache);
  1434. add_property_string(return_value, "MailDate", dummy);
  1435. snprintf(dummy, sizeof(dummy), "%ld", cache->rfc822_size);
  1436. add_property_string(return_value, "Size", dummy);
  1437. add_property_long(return_value, "udate", mail_longdate(cache));
  1438. if (en->from && fromlength) {
  1439. fulladdress[0] = 0x00;
  1440. mail_fetchfrom(fulladdress, imap_conn_struct->imap_stream, msgno, fromlength);
  1441. add_property_string(return_value, "fetchfrom", fulladdress);
  1442. }
  1443. if (en->subject && subjectlength) {
  1444. fulladdress[0] = 0x00;
  1445. mail_fetchsubject(fulladdress, imap_conn_struct->imap_stream, msgno, subjectlength);
  1446. add_property_string(return_value, "fetchsubject", fulladdress);
  1447. }
  1448. }
  1449. /* }}} */
  1450. /* {{{ Parse a set of mail headers contained in a string, and return an object similar to imap_headerinfo() */
  1451. PHP_FUNCTION(imap_rfc822_parse_headers)
  1452. {
  1453. zend_string *headers, *defaulthost = NULL;
  1454. ENVELOPE *en;
  1455. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|S", &headers, &defaulthost) == FAILURE) {
  1456. RETURN_THROWS();
  1457. }
  1458. if (defaulthost) {
  1459. rfc822_parse_msg(&en, NULL, ZSTR_VAL(headers), ZSTR_LEN(headers), NULL, ZSTR_VAL(defaulthost), NIL);
  1460. } else {
  1461. rfc822_parse_msg(&en, NULL, ZSTR_VAL(headers), ZSTR_LEN(headers), NULL, "UNKNOWN", NIL);
  1462. }
  1463. /* call a function to parse all the text, so that we can use the
  1464. same function no matter where the headers are from */
  1465. _php_make_header_object(return_value, en);
  1466. mail_free_envelope(&en);
  1467. }
  1468. /* }}} */
  1469. /* KMLANG */
  1470. /* {{{ Return a list of subscribed mailboxes */
  1471. PHP_FUNCTION(imap_lsub)
  1472. {
  1473. zval *imap_conn_obj;
  1474. zend_string *ref, *pat;
  1475. php_imap_object *imap_conn_struct;
  1476. STRINGLIST *cur=NIL;
  1477. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS", &imap_conn_obj, php_imap_ce, &ref, &pat) == FAILURE) {
  1478. RETURN_THROWS();
  1479. }
  1480. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1481. /* set flag for normal, old mailbox list */
  1482. IMAPG(folderlist_style) = FLIST_ARRAY;
  1483. IMAPG(imap_sfolders) = NIL;
  1484. ZEND_IGNORE_LEAKS_BEGIN();
  1485. mail_lsub(imap_conn_struct->imap_stream, ZSTR_VAL(ref), ZSTR_VAL(pat));
  1486. ZEND_IGNORE_LEAKS_END();
  1487. if (IMAPG(imap_sfolders) == NIL) {
  1488. RETURN_FALSE;
  1489. }
  1490. array_init(return_value);
  1491. cur=IMAPG(imap_sfolders);
  1492. while (cur != NIL) {
  1493. add_next_index_string(return_value, (char*)cur->LTEXT);
  1494. cur=cur->next;
  1495. }
  1496. mail_free_stringlist (&IMAPG(imap_sfolders));
  1497. IMAPG(imap_sfolders) = IMAPG(imap_sfolders_tail) = NIL;
  1498. }
  1499. /* }}} */
  1500. /* {{{ Return a list of subscribed mailboxes, in the same format as imap_getmailboxes() */
  1501. /* Author: CJH */
  1502. PHP_FUNCTION(imap_getsubscribed)
  1503. {
  1504. zval *imap_conn_obj, mboxob;
  1505. zend_string *ref, *pat;
  1506. php_imap_object *imap_conn_struct;
  1507. FOBJECTLIST *cur=NIL;
  1508. char *delim=NIL;
  1509. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS", &imap_conn_obj, php_imap_ce, &ref, &pat) == FAILURE) {
  1510. RETURN_THROWS();
  1511. }
  1512. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1513. /* set flag for new, improved array of objects list */
  1514. IMAPG(folderlist_style) = FLIST_OBJECT;
  1515. IMAPG(imap_sfolder_objects) = IMAPG(imap_sfolder_objects_tail) = NIL;
  1516. ZEND_IGNORE_LEAKS_BEGIN();
  1517. mail_lsub(imap_conn_struct->imap_stream, ZSTR_VAL(ref), ZSTR_VAL(pat));
  1518. ZEND_IGNORE_LEAKS_END();
  1519. if (IMAPG(imap_sfolder_objects) == NIL) {
  1520. RETURN_FALSE;
  1521. }
  1522. array_init(return_value);
  1523. delim = safe_emalloc(2, sizeof(char), 0);
  1524. cur=IMAPG(imap_sfolder_objects);
  1525. while (cur != NIL) {
  1526. object_init(&mboxob);
  1527. add_property_string(&mboxob, "name", (char*)cur->LTEXT);
  1528. add_property_long(&mboxob, "attributes", cur->attributes);
  1529. #ifdef IMAP41
  1530. delim[0] = (char)cur->delimiter;
  1531. delim[1] = 0;
  1532. add_property_string(&mboxob, "delimiter", delim);
  1533. #else
  1534. add_property_string(&mboxob, "delimiter", cur->delimiter);
  1535. #endif
  1536. php_imap_list_add_object(return_value, &mboxob);
  1537. cur=cur->next;
  1538. }
  1539. mail_free_foblist (&IMAPG(imap_sfolder_objects), &IMAPG(imap_sfolder_objects_tail));
  1540. efree(delim);
  1541. IMAPG(folderlist_style) = FLIST_ARRAY; /* reset to default */
  1542. }
  1543. /* }}} */
  1544. /* {{{ Subscribe to a mailbox */
  1545. PHP_FUNCTION(imap_subscribe)
  1546. {
  1547. zval *imap_conn_obj;
  1548. zend_string *folder;
  1549. php_imap_object *imap_conn_struct;
  1550. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &imap_conn_obj, php_imap_ce, &folder) == FAILURE) {
  1551. RETURN_THROWS();
  1552. }
  1553. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1554. if (mail_subscribe(imap_conn_struct->imap_stream, ZSTR_VAL(folder)) == T) {
  1555. RETURN_TRUE;
  1556. } else {
  1557. RETURN_FALSE;
  1558. }
  1559. }
  1560. /* }}} */
  1561. /* {{{ Unsubscribe from a mailbox */
  1562. PHP_FUNCTION(imap_unsubscribe)
  1563. {
  1564. zval *imap_conn_obj;
  1565. zend_string *folder;
  1566. php_imap_object *imap_conn_struct;
  1567. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &imap_conn_obj, php_imap_ce, &folder) == FAILURE) {
  1568. RETURN_THROWS();
  1569. }
  1570. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1571. if (mail_unsubscribe(imap_conn_struct->imap_stream, ZSTR_VAL(folder)) == T) {
  1572. RETURN_TRUE;
  1573. } else {
  1574. RETURN_FALSE;
  1575. }
  1576. }
  1577. /* }}} */
  1578. /* {{{ Read the full structure of a message */
  1579. PHP_FUNCTION(imap_fetchstructure)
  1580. {
  1581. zval *imap_conn_obj;
  1582. zend_long msgno, flags = 0;
  1583. php_imap_object *imap_conn_struct;
  1584. BODY *body;
  1585. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol|l", &imap_conn_obj, php_imap_ce, &msgno, &flags) == FAILURE) {
  1586. RETURN_THROWS();
  1587. }
  1588. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1589. PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgno, 2);
  1590. if (flags && ((flags & ~FT_UID) != 0)) {
  1591. zend_argument_value_error(3, "must be FT_UID or 0");
  1592. RETURN_THROWS();
  1593. }
  1594. PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgno, 2, flags, FT_UID);
  1595. object_init(return_value);
  1596. mail_fetchstructure_full(imap_conn_struct->imap_stream, msgno, &body , flags);
  1597. if (!body) {
  1598. php_error_docref(NULL, E_WARNING, "No body information available");
  1599. RETURN_FALSE;
  1600. }
  1601. _php_imap_add_body(return_value, body);
  1602. }
  1603. /* }}} */
  1604. /* {{{ Get a specific body section */
  1605. PHP_FUNCTION(imap_fetchbody)
  1606. {
  1607. zval *imap_conn_obj;
  1608. zend_long msgno, flags = 0;
  1609. php_imap_object *imap_conn_struct;
  1610. char *body;
  1611. zend_string *sec;
  1612. unsigned long len;
  1613. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OlS|l", &imap_conn_obj, php_imap_ce, &msgno, &sec, &flags) == FAILURE) {
  1614. RETURN_THROWS();
  1615. }
  1616. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1617. PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgno, 2);
  1618. if (flags && ((flags & ~(FT_UID|FT_PEEK|FT_INTERNAL)) != 0)) {
  1619. zend_argument_value_error(4, "must be a bitmask of FT_UID, FT_PEEK, and FT_INTERNAL");
  1620. RETURN_THROWS();
  1621. }
  1622. PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgno, 2, flags, FT_UID);
  1623. body = mail_fetchbody_full(imap_conn_struct->imap_stream, msgno, ZSTR_VAL(sec), &len, flags);
  1624. if (!body) {
  1625. php_error_docref(NULL, E_WARNING, "No body information available");
  1626. RETURN_FALSE;
  1627. }
  1628. RETVAL_STRINGL(body, len);
  1629. }
  1630. /* }}} */
  1631. /* {{{ Get a specific body section's MIME headers */
  1632. PHP_FUNCTION(imap_fetchmime)
  1633. {
  1634. zval *imap_conn_obj;
  1635. zend_long msgno, flags = 0;
  1636. php_imap_object *imap_conn_struct;
  1637. char *body;
  1638. zend_string *sec;
  1639. unsigned long len;
  1640. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OlS|l", &imap_conn_obj, php_imap_ce, &msgno, &sec, &flags) == FAILURE) {
  1641. RETURN_THROWS();
  1642. }
  1643. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1644. PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgno, 2);
  1645. if (flags && ((flags & ~(FT_UID|FT_PEEK|FT_INTERNAL)) != 0)) {
  1646. zend_argument_value_error(4, "must be a bitmask of FT_UID, FT_PEEK, and FT_INTERNAL");
  1647. RETURN_THROWS();
  1648. }
  1649. PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgno, 2, flags, FT_UID);
  1650. body = mail_fetch_mime(imap_conn_struct->imap_stream, msgno, ZSTR_VAL(sec), &len, flags);
  1651. if (!body) {
  1652. php_error_docref(NULL, E_WARNING, "No body MIME information available");
  1653. RETURN_FALSE;
  1654. }
  1655. RETVAL_STRINGL(body, len);
  1656. }
  1657. /* }}} */
  1658. /* {{{ Save a specific body section to a file */
  1659. PHP_FUNCTION(imap_savebody)
  1660. {
  1661. zval *imap_conn_obj;
  1662. zval *out;
  1663. php_imap_object *imap_conn_struct = NULL;
  1664. php_stream *writer = NULL;
  1665. zend_string *section = NULL;
  1666. int close_stream = 1;
  1667. zend_long msgno, flags = 0;
  1668. if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "Ozl|Sl", &imap_conn_obj, php_imap_ce, &out, &msgno, &section, &flags)) {
  1669. RETURN_THROWS();
  1670. }
  1671. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1672. PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgno, 3)
  1673. if (flags && ((flags & ~(FT_UID|FT_PEEK|FT_INTERNAL)) != 0)) {
  1674. zend_argument_value_error(5, "must be a bitmask of FT_UID, FT_PEEK, and FT_INTERNAL");
  1675. RETURN_THROWS();
  1676. }
  1677. PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgno, 3, flags, FT_UID);
  1678. switch (Z_TYPE_P(out))
  1679. {
  1680. case IS_LONG:
  1681. case IS_RESOURCE:
  1682. close_stream = 0;
  1683. php_stream_from_zval(writer, out);
  1684. break;
  1685. default:
  1686. if (!try_convert_to_string(out)) {
  1687. RETURN_THROWS();
  1688. }
  1689. // TODO Need to check for null bytes?
  1690. writer = php_stream_open_wrapper(Z_STRVAL_P(out), "wb", REPORT_ERRORS, NULL);
  1691. break;
  1692. }
  1693. if (!writer) {
  1694. RETURN_FALSE;
  1695. }
  1696. IMAPG(gets_stream) = writer;
  1697. mail_parameters(NIL, SET_GETS, (void *) php_mail_gets);
  1698. mail_fetchbody_full(imap_conn_struct->imap_stream, msgno, section?ZSTR_VAL(section):"", NULL, flags);
  1699. mail_parameters(NIL, SET_GETS, (void *) NULL);
  1700. IMAPG(gets_stream) = NULL;
  1701. if (close_stream) {
  1702. php_stream_close(writer);
  1703. }
  1704. RETURN_TRUE;
  1705. }
  1706. /* }}} */
  1707. /* {{{ Decode BASE64 encoded text */
  1708. PHP_FUNCTION(imap_base64)
  1709. {
  1710. zend_string *text;
  1711. char *decode;
  1712. unsigned long newlength;
  1713. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &text) == FAILURE) {
  1714. RETURN_THROWS();
  1715. }
  1716. decode = (char *) rfc822_base64((unsigned char *) ZSTR_VAL(text), ZSTR_LEN(text), &newlength);
  1717. if (decode == NULL) {
  1718. RETURN_FALSE;
  1719. }
  1720. RETVAL_STRINGL(decode, newlength);
  1721. fs_give((void**) &decode);
  1722. }
  1723. /* }}} */
  1724. /* {{{ Convert a quoted-printable string to an 8-bit string */
  1725. PHP_FUNCTION(imap_qprint)
  1726. {
  1727. zend_string *text;
  1728. char *decode;
  1729. unsigned long newlength;
  1730. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &text) == FAILURE) {
  1731. RETURN_THROWS();
  1732. }
  1733. decode = (char *) rfc822_qprint((unsigned char *) ZSTR_VAL(text), ZSTR_LEN(text), &newlength);
  1734. if (decode == NULL) {
  1735. RETURN_FALSE;
  1736. }
  1737. RETVAL_STRINGL(decode, newlength);
  1738. fs_give((void**) &decode);
  1739. }
  1740. /* }}} */
  1741. /* {{{ Convert an 8-bit string to a quoted-printable string */
  1742. PHP_FUNCTION(imap_8bit)
  1743. {
  1744. zend_string *text;
  1745. char *decode;
  1746. unsigned long newlength;
  1747. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &text) == FAILURE) {
  1748. RETURN_THROWS();
  1749. }
  1750. decode = (char *) rfc822_8bit((unsigned char *) ZSTR_VAL(text), ZSTR_LEN(text), &newlength);
  1751. if (decode == NULL) {
  1752. RETURN_FALSE;
  1753. }
  1754. RETVAL_STRINGL(decode, newlength);
  1755. fs_give((void**) &decode);
  1756. }
  1757. /* }}} */
  1758. /* {{{ Convert an 8bit string to a base64 string */
  1759. PHP_FUNCTION(imap_binary)
  1760. {
  1761. zend_string *text;
  1762. char *decode;
  1763. unsigned long newlength;
  1764. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &text) == FAILURE) {
  1765. RETURN_THROWS();
  1766. }
  1767. decode = (char*)rfc822_binary(ZSTR_VAL(text), ZSTR_LEN(text), &newlength);
  1768. if (decode == NULL) {
  1769. RETURN_FALSE;
  1770. }
  1771. RETVAL_STRINGL(decode, newlength);
  1772. fs_give((void**) &decode);
  1773. }
  1774. /* }}} */
  1775. /* {{{ Returns info about the current mailbox */
  1776. PHP_FUNCTION(imap_mailboxmsginfo)
  1777. {
  1778. zval *imap_conn_obj;
  1779. php_imap_object *imap_conn_struct;
  1780. char date[100];
  1781. unsigned long msgno;
  1782. zend_ulong unreadmsg = 0, deletedmsg = 0, msize = 0;
  1783. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &imap_conn_obj, php_imap_ce) == FAILURE) {
  1784. RETURN_THROWS();
  1785. }
  1786. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  1787. /* Initialize return object */
  1788. object_init(return_value);
  1789. for (msgno = 1; msgno <= imap_conn_struct->imap_stream->nmsgs; msgno++) {
  1790. MESSAGECACHE * cache = mail_elt (imap_conn_struct->imap_stream, msgno);
  1791. mail_fetchstructure (imap_conn_struct->imap_stream, msgno, NIL);
  1792. if (!cache->seen || cache->recent) {
  1793. unreadmsg++;
  1794. }
  1795. if (cache->deleted) {
  1796. deletedmsg++;
  1797. }
  1798. msize = msize + cache->rfc822_size;
  1799. }
  1800. add_property_long(return_value, "Unread", unreadmsg);
  1801. add_property_long(return_value, "Deleted", deletedmsg);
  1802. add_property_long(return_value, "Nmsgs", imap_conn_struct->imap_stream->nmsgs);
  1803. add_property_long(return_value, "Size", msize);
  1804. rfc822_date(date);
  1805. add_property_string(return_value, "Date", date);
  1806. add_property_string(return_value, "Driver", imap_conn_struct->imap_stream->dtb->name);
  1807. add_property_string(return_value, "Mailbox", imap_conn_struct->imap_stream->mailbox);
  1808. add_property_long(return_value, "Recent", imap_conn_struct->imap_stream->recent);
  1809. }
  1810. /* }}} */
  1811. /* {{{ Returns a properly formatted email address given the mailbox, host, and personal info */
  1812. PHP_FUNCTION(imap_rfc822_write_address)
  1813. {
  1814. zend_string *mailbox, *host, *personal;
  1815. ADDRESS *addr;
  1816. zend_string *string;
  1817. if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSS", &mailbox, &host, &personal) == FAILURE) {
  1818. RETURN_THROWS();
  1819. }
  1820. addr=mail_newaddr();
  1821. if (mailbox) {
  1822. addr->mailbox = cpystr(ZSTR_VAL(mailbox));
  1823. }
  1824. if (host) {
  1825. addr->host = cpystr(ZSTR_VAL(host));
  1826. }
  1827. if (personal) {
  1828. addr->personal = cpystr(ZSTR_VAL(personal));
  1829. }
  1830. addr->next=NIL;
  1831. addr->error=NIL;
  1832. addr->adl=NIL;
  1833. string = _php_rfc822_write_address(addr);
  1834. if (string) {
  1835. RETVAL_STR(string);
  1836. } else {
  1837. RETVAL_FALSE;
  1838. }
  1839. mail_free_address(&addr);
  1840. }
  1841. /* }}} */
  1842. /* {{{ Parses an address string */
  1843. PHP_FUNCTION(imap_rfc822_parse_adrlist)
  1844. {
  1845. zval tovals;
  1846. zend_string *str, *defaulthost;
  1847. char *str_copy;
  1848. ADDRESS *addresstmp;
  1849. ENVELOPE *env;
  1850. if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &str, &defaulthost) == FAILURE) {
  1851. RETURN_THROWS();
  1852. }
  1853. env = mail_newenvelope();
  1854. /* rfc822_parse_adrlist() modifies passed string. Copy it. */
  1855. str_copy = estrndup(ZSTR_VAL(str), ZSTR_LEN(str));
  1856. rfc822_parse_adrlist(&env->to, str_copy, ZSTR_VAL(defaulthost));
  1857. efree(str_copy);
  1858. array_init(return_value);
  1859. addresstmp = env->to;
  1860. if (addresstmp) do {
  1861. object_init(&tovals);
  1862. if (addresstmp->mailbox) {
  1863. add_property_string(&tovals, "mailbox", addresstmp->mailbox);
  1864. }
  1865. if (addresstmp->host) {
  1866. add_property_string(&tovals, "host", addresstmp->host);
  1867. }
  1868. if (addresstmp->personal) {
  1869. add_property_string(&tovals, "personal", addresstmp->personal);
  1870. }
  1871. if (addresstmp->adl) {
  1872. add_property_string(&tovals, "adl", addresstmp->adl);
  1873. }
  1874. php_imap_list_add_object(return_value, &tovals);
  1875. } while ((addresstmp = addresstmp->next));
  1876. mail_free_envelope(&env);
  1877. }
  1878. /* }}} */
  1879. /* {{{ Convert a mime-encoded text to UTF-8 */
  1880. PHP_FUNCTION(imap_utf8)
  1881. {
  1882. zend_string *str;
  1883. SIZEDTEXT src, dest;
  1884. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
  1885. RETURN_THROWS();
  1886. }
  1887. src.data = NULL;
  1888. src.size = 0;
  1889. dest.data = NULL;
  1890. dest.size = 0;
  1891. cpytxt(&src, ZSTR_VAL(str), ZSTR_LEN(str));
  1892. #ifndef HAVE_NEW_MIME2TEXT
  1893. utf8_mime2text(&src, &dest);
  1894. #else
  1895. utf8_mime2text(&src, &dest, U8T_DECOMPOSE);
  1896. #endif
  1897. RETVAL_STRINGL((char*)dest.data, dest.size);
  1898. if (dest.data) {
  1899. free(dest.data);
  1900. }
  1901. if (src.data && src.data != dest.data) {
  1902. free(src.data);
  1903. }
  1904. }
  1905. /* }}} */
  1906. /* {{{ macros for the modified utf7 conversion functions
  1907. *
  1908. * author: Andrew Skalski <askalski@chek.com>
  1909. */
  1910. /* tests `c' and returns true if it is a special character */
  1911. #define SPECIAL(c) ((c) <= 0x1f || (c) >= 0x7f)
  1912. /* validate a modified-base64 character */
  1913. #define B64CHAR(c) (isalnum(c) || (c) == '+' || (c) == ',')
  1914. /* map the low 64 bits of `n' to the modified-base64 characters */
  1915. #define B64(n) ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
  1916. "abcdefghijklmnopqrstuvwxyz0123456789+,"[(n) & 0x3f])
  1917. /* map the modified-base64 character `c' to its 64 bit value */
  1918. #define UNB64(c) ((c) == '+' ? 62 : (c) == ',' ? 63 : (c) >= 'a' ? \
  1919. (c) - 71 : (c) >= 'A' ? (c) - 65 : (c) + 4)
  1920. /* }}} */
  1921. /* {{{ Decode a modified UTF-7 string */
  1922. PHP_FUNCTION(imap_utf7_decode)
  1923. {
  1924. /* author: Andrew Skalski <askalski@chek.com> */
  1925. zend_string *arg;
  1926. const unsigned char *in, *inp, *endp;
  1927. unsigned char *out, *outp;
  1928. unsigned char c;
  1929. int inlen, outlen;
  1930. enum {
  1931. ST_NORMAL, /* printable text */
  1932. ST_DECODE0, /* encoded text rotation... */
  1933. ST_DECODE1,
  1934. ST_DECODE2,
  1935. ST_DECODE3
  1936. } state;
  1937. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &arg) == FAILURE) {
  1938. RETURN_THROWS();
  1939. }
  1940. in = (const unsigned char *) ZSTR_VAL(arg);
  1941. inlen = ZSTR_LEN(arg);
  1942. /* validate and compute length of output string */
  1943. outlen = 0;
  1944. state = ST_NORMAL;
  1945. for (endp = (inp = in) + inlen; inp < endp; inp++) {
  1946. if (state == ST_NORMAL) {
  1947. /* process printable character */
  1948. if (SPECIAL(*inp)) {
  1949. php_error_docref(NULL, E_WARNING, "Invalid modified UTF-7 character: `%c'", *inp);
  1950. RETURN_FALSE;
  1951. } else if (*inp != '&') {
  1952. outlen++;
  1953. } else if (inp + 1 == endp) {
  1954. php_error_docref(NULL, E_WARNING, "Unexpected end of string");
  1955. RETURN_FALSE;
  1956. } else if (inp[1] != '-') {
  1957. state = ST_DECODE0;
  1958. } else {
  1959. outlen++;
  1960. inp++;
  1961. }
  1962. } else if (*inp == '-') {
  1963. /* return to NORMAL mode */
  1964. if (state == ST_DECODE1) {
  1965. php_error_docref(NULL, E_WARNING, "Stray modified base64 character: `%c'", *--inp);
  1966. RETURN_FALSE;
  1967. }
  1968. state = ST_NORMAL;
  1969. } else if (!B64CHAR(*inp)) {
  1970. php_error_docref(NULL, E_WARNING, "Invalid modified base64 character: `%c'", *inp);
  1971. RETURN_FALSE;
  1972. } else {
  1973. switch (state) {
  1974. case ST_DECODE3:
  1975. outlen++;
  1976. state = ST_DECODE0;
  1977. break;
  1978. case ST_DECODE2:
  1979. case ST_DECODE1:
  1980. outlen++;
  1981. ZEND_FALLTHROUGH;
  1982. case ST_DECODE0:
  1983. state++;
  1984. case ST_NORMAL:
  1985. break;
  1986. }
  1987. }
  1988. }
  1989. /* enforce end state */
  1990. if (state != ST_NORMAL) {
  1991. php_error_docref(NULL, E_WARNING, "Unexpected end of string");
  1992. RETURN_FALSE;
  1993. }
  1994. /* allocate output buffer */
  1995. out = emalloc(outlen + 1);
  1996. /* decode input string */
  1997. outp = out;
  1998. state = ST_NORMAL;
  1999. for (endp = (inp = in) + inlen; inp < endp; inp++) {
  2000. if (state == ST_NORMAL) {
  2001. if (*inp == '&' && inp[1] != '-') {
  2002. state = ST_DECODE0;
  2003. }
  2004. else if ((*outp++ = *inp) == '&') {
  2005. inp++;
  2006. }
  2007. }
  2008. else if (*inp == '-') {
  2009. state = ST_NORMAL;
  2010. }
  2011. else {
  2012. /* decode input character */
  2013. switch (state) {
  2014. case ST_DECODE0:
  2015. *outp = UNB64(*inp) << 2;
  2016. state = ST_DECODE1;
  2017. break;
  2018. case ST_DECODE1:
  2019. outp[1] = UNB64(*inp);
  2020. c = outp[1] >> 4;
  2021. *outp++ |= c;
  2022. *outp <<= 4;
  2023. state = ST_DECODE2;
  2024. break;
  2025. case ST_DECODE2:
  2026. outp[1] = UNB64(*inp);
  2027. c = outp[1] >> 2;
  2028. *outp++ |= c;
  2029. *outp <<= 6;
  2030. state = ST_DECODE3;
  2031. break;
  2032. case ST_DECODE3:
  2033. *outp++ |= UNB64(*inp);
  2034. state = ST_DECODE0;
  2035. case ST_NORMAL:
  2036. break;
  2037. }
  2038. }
  2039. }
  2040. *outp = 0;
  2041. #if PHP_DEBUG
  2042. /* warn if we computed outlen incorrectly */
  2043. if (outp - out != outlen) {
  2044. php_error_docref(NULL, E_WARNING, "outp - out [%zd] != outlen [%d]", outp - out, outlen);
  2045. }
  2046. #endif
  2047. RETURN_STRINGL((char*)out, outlen);
  2048. }
  2049. /* }}} */
  2050. /* {{{ Encode a string in modified UTF-7 */
  2051. PHP_FUNCTION(imap_utf7_encode)
  2052. {
  2053. /* author: Andrew Skalski <askalski@chek.com> */
  2054. zend_string *arg;
  2055. const unsigned char *in, *inp, *endp;
  2056. zend_string *out;
  2057. unsigned char *outp;
  2058. unsigned char c;
  2059. int inlen, outlen;
  2060. enum {
  2061. ST_NORMAL, /* printable text */
  2062. ST_ENCODE0, /* encoded text rotation... */
  2063. ST_ENCODE1,
  2064. ST_ENCODE2
  2065. } state;
  2066. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &arg) == FAILURE) {
  2067. RETURN_THROWS();
  2068. }
  2069. in = (const unsigned char *) ZSTR_VAL(arg);
  2070. inlen = ZSTR_LEN(arg);
  2071. /* compute the length of the result string */
  2072. outlen = 0;
  2073. state = ST_NORMAL;
  2074. endp = (inp = in) + inlen;
  2075. while (inp < endp) {
  2076. if (state == ST_NORMAL) {
  2077. if (SPECIAL(*inp)) {
  2078. state = ST_ENCODE0;
  2079. outlen++;
  2080. } else if (*inp++ == '&') {
  2081. outlen++;
  2082. }
  2083. outlen++;
  2084. } else if (!SPECIAL(*inp)) {
  2085. state = ST_NORMAL;
  2086. } else {
  2087. /* ST_ENCODE0 -> ST_ENCODE1 - two chars
  2088. * ST_ENCODE1 -> ST_ENCODE2 - one char
  2089. * ST_ENCODE2 -> ST_ENCODE0 - one char
  2090. */
  2091. if (state == ST_ENCODE2) {
  2092. state = ST_ENCODE0;
  2093. }
  2094. else if (state++ == ST_ENCODE0) {
  2095. outlen++;
  2096. }
  2097. outlen++;
  2098. inp++;
  2099. }
  2100. }
  2101. /* allocate output buffer */
  2102. out = zend_string_safe_alloc(1, outlen, 0, 0);
  2103. /* encode input string */
  2104. outp = (unsigned char*)ZSTR_VAL(out);
  2105. state = ST_NORMAL;
  2106. endp = (inp = in) + inlen;
  2107. while (inp < endp || state != ST_NORMAL) {
  2108. if (state == ST_NORMAL) {
  2109. if (SPECIAL(*inp)) {
  2110. /* begin encoding */
  2111. *outp++ = '&';
  2112. state = ST_ENCODE0;
  2113. } else if ((*outp++ = *inp++) == '&') {
  2114. *outp++ = '-';
  2115. }
  2116. } else if (inp == endp || !SPECIAL(*inp)) {
  2117. /* flush overflow and terminate region */
  2118. if (state != ST_ENCODE0) {
  2119. c = B64(*outp);
  2120. *outp++ = c;
  2121. }
  2122. *outp++ = '-';
  2123. state = ST_NORMAL;
  2124. } else {
  2125. /* encode input character */
  2126. switch (state) {
  2127. case ST_ENCODE0:
  2128. *outp++ = B64(*inp >> 2);
  2129. *outp = *inp++ << 4;
  2130. state = ST_ENCODE1;
  2131. break;
  2132. case ST_ENCODE1:
  2133. c = B64(*outp | *inp >> 4);
  2134. *outp++ = c;
  2135. *outp = *inp++ << 2;
  2136. state = ST_ENCODE2;
  2137. break;
  2138. case ST_ENCODE2:
  2139. c = B64(*outp | *inp >> 6);
  2140. *outp++ = c;
  2141. *outp++ = B64(*inp++);
  2142. state = ST_ENCODE0;
  2143. case ST_NORMAL:
  2144. break;
  2145. }
  2146. }
  2147. }
  2148. *outp = 0;
  2149. RETURN_STR(out);
  2150. }
  2151. /* }}} */
  2152. #undef SPECIAL
  2153. #undef B64CHAR
  2154. #undef B64
  2155. #undef UNB64
  2156. #ifdef HAVE_IMAP_MUTF7
  2157. static void php_imap_mutf7(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
  2158. {
  2159. zend_string *in;
  2160. unsigned char *out;
  2161. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &in) == FAILURE) {
  2162. RETURN_THROWS();
  2163. }
  2164. if (ZSTR_LEN(in) < 1) {
  2165. RETURN_EMPTY_STRING();
  2166. }
  2167. if (mode == 0) {
  2168. out = utf8_to_mutf7((unsigned char *) ZSTR_VAL(in));
  2169. } else {
  2170. out = utf8_from_mutf7((unsigned char *) ZSTR_VAL(in));
  2171. }
  2172. if (out == NIL) {
  2173. RETURN_FALSE;
  2174. } else {
  2175. RETVAL_STRING((char *)out);
  2176. fs_give((void**) &out);
  2177. }
  2178. }
  2179. /* }}} */
  2180. /* {{{ Encode a UTF-8 string to modified UTF-7 */
  2181. PHP_FUNCTION(imap_utf8_to_mutf7)
  2182. {
  2183. php_imap_mutf7(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  2184. }
  2185. /* }}} */
  2186. /* {{{ Decode a modified UTF-7 string to UTF-8 */
  2187. PHP_FUNCTION(imap_mutf7_to_utf8)
  2188. {
  2189. php_imap_mutf7(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  2190. }
  2191. /* }}} */
  2192. #endif
  2193. /* {{{ Sets flags on messages */
  2194. PHP_FUNCTION(imap_setflag_full)
  2195. {
  2196. zval *imap_conn_obj;
  2197. zend_string *sequence, *flag;
  2198. zend_long flags = 0;
  2199. php_imap_object *imap_conn_struct;
  2200. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS|l", &imap_conn_obj, php_imap_ce, &sequence, &flag, &flags) == FAILURE) {
  2201. RETURN_THROWS();
  2202. }
  2203. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  2204. if (flags && ((flags & ~ST_UID) != 0)) {
  2205. zend_argument_value_error(4, "must be ST_UID or 0");
  2206. RETURN_THROWS();
  2207. }
  2208. mail_setflag_full(imap_conn_struct->imap_stream, ZSTR_VAL(sequence), ZSTR_VAL(flag), (flags ? flags : NIL));
  2209. RETURN_TRUE;
  2210. }
  2211. /* }}} */
  2212. /* {{{ Clears flags on messages */
  2213. PHP_FUNCTION(imap_clearflag_full)
  2214. {
  2215. zval *imap_conn_obj;
  2216. zend_string *sequence, *flag;
  2217. zend_long flags = 0;
  2218. php_imap_object *imap_conn_struct;
  2219. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS|l", &imap_conn_obj, php_imap_ce, &sequence, &flag, &flags) ==FAILURE) {
  2220. RETURN_THROWS();
  2221. }
  2222. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  2223. if (flags && ((flags & ~ST_UID) != 0)) {
  2224. zend_argument_value_error(4, "must be ST_UID or 0");
  2225. RETURN_THROWS();
  2226. }
  2227. mail_clearflag_full(imap_conn_struct->imap_stream, ZSTR_VAL(sequence), ZSTR_VAL(flag), flags);
  2228. RETURN_TRUE;
  2229. }
  2230. /* }}} */
  2231. /* {{{ Sort an array of message headers, optionally including only messages that meet specified criteria. */
  2232. PHP_FUNCTION(imap_sort)
  2233. {
  2234. zval *imap_conn_obj;
  2235. zend_string *criteria = NULL, *charset = NULL;
  2236. zend_long sort, flags = 0;
  2237. bool rev;
  2238. php_imap_object *imap_conn_struct;
  2239. unsigned long *slst, *sl;
  2240. char *search_criteria;
  2241. SORTPGM *mypgm=NIL;
  2242. SEARCHPGM *spg=NIL;
  2243. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Olb|lS!S!", &imap_conn_obj, php_imap_ce, &sort, &rev, &flags, &criteria, &charset) == FAILURE) {
  2244. RETURN_THROWS();
  2245. }
  2246. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  2247. if (!(sort == SORTDATE || sort == SORTARRIVAL || sort == SORTFROM || sort == SORTSUBJECT || sort == SORTTO ||
  2248. sort == SORTCC || sort == SORTSIZE) ) {
  2249. zend_argument_value_error(2, "must be one of the SORT* constants");
  2250. RETURN_THROWS();
  2251. }
  2252. if (flags && ((flags & ~(SE_UID|SE_NOPREFETCH )) != 0)) {
  2253. zend_argument_value_error(4, "must be a bitmask of SE_UID, and SE_NOPREFETCH");
  2254. RETURN_THROWS();
  2255. }
  2256. if (criteria) {
  2257. search_criteria = estrndup(ZSTR_VAL(criteria), ZSTR_LEN(criteria));
  2258. spg = mail_criteria(search_criteria);
  2259. efree(search_criteria);
  2260. } else {
  2261. spg = mail_newsearchpgm();
  2262. }
  2263. if (spg == NIL) {
  2264. RETURN_FALSE;
  2265. }
  2266. mypgm = mail_newsortpgm();
  2267. mypgm->reverse = rev;
  2268. mypgm->function = (short) sort;
  2269. mypgm->next = NIL;
  2270. slst = mail_sort(imap_conn_struct->imap_stream, (charset ? ZSTR_VAL(charset) : NIL), spg, mypgm, flags);
  2271. mail_free_sortpgm(&mypgm);
  2272. if (spg && !(flags & SE_FREE)) {
  2273. mail_free_searchpgm(&spg);
  2274. }
  2275. array_init(return_value);
  2276. if (slst != NULL) {
  2277. for (sl = slst; *sl; sl++) {
  2278. add_next_index_long(return_value, *sl);
  2279. }
  2280. fs_give ((void **) &slst);
  2281. }
  2282. }
  2283. /* }}} */
  2284. /* {{{ Get the full unfiltered header for a message */
  2285. PHP_FUNCTION(imap_fetchheader)
  2286. {
  2287. zval *imap_conn_obj;
  2288. zend_long msgno, flags = 0;
  2289. php_imap_object *imap_conn_struct;
  2290. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol|l", &imap_conn_obj, php_imap_ce, &msgno, &flags) == FAILURE) {
  2291. RETURN_THROWS();
  2292. }
  2293. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  2294. PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgno, 2);
  2295. if (flags && ((flags & ~(FT_UID|FT_INTERNAL|FT_PREFETCHTEXT)) != 0)) {
  2296. zend_argument_value_error(3, "must be a bitmask of FT_UID, FT_PREFETCHTEXT, and FT_INTERNAL");
  2297. RETURN_THROWS();
  2298. }
  2299. PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgno, 2, flags, FT_UID);
  2300. RETVAL_STRING(mail_fetchheader_full(imap_conn_struct->imap_stream, msgno, NIL, NIL, flags));
  2301. }
  2302. /* }}} */
  2303. /* {{{ Get the unique message id associated with a standard sequential message number */
  2304. PHP_FUNCTION(imap_uid)
  2305. {
  2306. zval *imap_conn_obj;
  2307. zend_long msgno;
  2308. php_imap_object *imap_conn_struct;
  2309. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &imap_conn_obj, php_imap_ce, &msgno) == FAILURE) {
  2310. RETURN_THROWS();
  2311. }
  2312. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  2313. PHP_IMAP_CHECK_MSGNO(msgno, 2);
  2314. RETURN_LONG(mail_uid(imap_conn_struct->imap_stream, msgno));
  2315. }
  2316. /* }}} */
  2317. /* {{{ Get the sequence number associated with a UID */
  2318. PHP_FUNCTION(imap_msgno)
  2319. {
  2320. zval *imap_conn_obj;
  2321. zend_long msg_uid;
  2322. php_imap_object *imap_conn_struct;
  2323. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &imap_conn_obj, php_imap_ce, &msg_uid) == FAILURE) {
  2324. RETURN_THROWS();
  2325. }
  2326. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  2327. /* Do NOT use the PHP_IMAP_CHECK_MSGNO() macro as UID cannot be checked for their upper bound. */
  2328. if (msg_uid < 1) {
  2329. zend_argument_value_error(2, "must be greater than 0");
  2330. RETURN_THROWS();
  2331. }
  2332. RETURN_LONG(mail_msgno(imap_conn_struct->imap_stream, msg_uid));
  2333. }
  2334. /* }}} */
  2335. /* {{{ Get status info from a mailbox */
  2336. PHP_FUNCTION(imap_status)
  2337. {
  2338. zval *imap_conn_obj;
  2339. zend_string *mbx;
  2340. zend_long flags;
  2341. php_imap_object *imap_conn_struct;
  2342. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSl", &imap_conn_obj, php_imap_ce, &mbx, &flags) == FAILURE) {
  2343. RETURN_THROWS();
  2344. }
  2345. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  2346. if (flags && ((flags & ~(SA_MESSAGES | SA_RECENT | SA_UNSEEN | SA_UIDNEXT | SA_UIDVALIDITY /*| SA_ALL*/)) != 0)) {
  2347. zend_argument_value_error(3, "must be a bitmask of SA_* constants");
  2348. RETURN_THROWS();
  2349. }
  2350. object_init(return_value);
  2351. if (mail_status(imap_conn_struct->imap_stream, ZSTR_VAL(mbx), flags)) {
  2352. add_property_long(return_value, "flags", IMAPG(status_flags));
  2353. if (IMAPG(status_flags) & SA_MESSAGES) {
  2354. add_property_long(return_value, "messages", IMAPG(status_messages));
  2355. }
  2356. if (IMAPG(status_flags) & SA_RECENT) {
  2357. add_property_long(return_value, "recent", IMAPG(status_recent));
  2358. }
  2359. if (IMAPG(status_flags) & SA_UNSEEN) {
  2360. add_property_long(return_value, "unseen", IMAPG(status_unseen));
  2361. }
  2362. if (IMAPG(status_flags) & SA_UIDNEXT) {
  2363. add_property_long(return_value, "uidnext", IMAPG(status_uidnext));
  2364. }
  2365. if (IMAPG(status_flags) & SA_UIDVALIDITY) {
  2366. add_property_long(return_value, "uidvalidity", IMAPG(status_uidvalidity));
  2367. }
  2368. } else {
  2369. RETURN_FALSE;
  2370. }
  2371. }
  2372. /* }}} */
  2373. /* {{{ Read the structure of a specified body section of a specific message */
  2374. PHP_FUNCTION(imap_bodystruct)
  2375. {
  2376. zval *imap_conn_obj;
  2377. zend_long msgno;
  2378. zend_string *section;
  2379. php_imap_object *imap_conn_struct;
  2380. zval parametres, param, dparametres, dparam;
  2381. PARAMETER *par, *dpar;
  2382. BODY *body;
  2383. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OlS", &imap_conn_obj, php_imap_ce, &msgno, &section) == FAILURE) {
  2384. RETURN_THROWS();
  2385. }
  2386. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  2387. PHP_IMAP_CHECK_MSGNO(msgno, 2);
  2388. body=mail_body(imap_conn_struct->imap_stream, msgno, (unsigned char*)ZSTR_VAL(section));
  2389. if (body == NULL) {
  2390. RETURN_FALSE;
  2391. }
  2392. object_init(return_value);
  2393. if (body->type <= TYPEMAX) {
  2394. add_property_long(return_value, "type", body->type);
  2395. }
  2396. if (body->encoding <= ENCMAX) {
  2397. add_property_long(return_value, "encoding", body->encoding);
  2398. }
  2399. if (body->subtype) {
  2400. add_property_long(return_value, "ifsubtype", 1);
  2401. add_property_string(return_value, "subtype", body->subtype);
  2402. } else {
  2403. add_property_long(return_value, "ifsubtype", 0);
  2404. }
  2405. if (body->description) {
  2406. add_property_long(return_value, "ifdescription", 1);
  2407. add_property_string(return_value, "description", body->description);
  2408. } else {
  2409. add_property_long(return_value, "ifdescription", 0);
  2410. }
  2411. if (body->id) {
  2412. add_property_long(return_value, "ifid", 1);
  2413. add_property_string(return_value, "id", body->id);
  2414. } else {
  2415. add_property_long(return_value, "ifid", 0);
  2416. }
  2417. if (body->size.lines) {
  2418. add_property_long(return_value, "lines", body->size.lines);
  2419. }
  2420. if (body->size.bytes) {
  2421. add_property_long(return_value, "bytes", body->size.bytes);
  2422. }
  2423. #ifdef IMAP41
  2424. if (body->disposition.type) {
  2425. add_property_long(return_value, "ifdisposition", 1);
  2426. add_property_string(return_value, "disposition", body->disposition.type);
  2427. } else {
  2428. add_property_long(return_value, "ifdisposition", 0);
  2429. }
  2430. if (body->disposition.parameter) {
  2431. dpar = body->disposition.parameter;
  2432. add_property_long(return_value, "ifdparameters", 1);
  2433. array_init(&dparametres);
  2434. do {
  2435. object_init(&dparam);
  2436. add_property_string(&dparam, "attribute", dpar->attribute);
  2437. add_property_string(&dparam, "value", dpar->value);
  2438. php_imap_list_add_object(&dparametres, &dparam);
  2439. } while ((dpar = dpar->next));
  2440. php_imap_hash_add_object(return_value, "dparameters", &dparametres);
  2441. } else {
  2442. add_property_long(return_value, "ifdparameters", 0);
  2443. }
  2444. #endif
  2445. if ((par = body->parameter)) {
  2446. add_property_long(return_value, "ifparameters", 1);
  2447. array_init(&parametres);
  2448. do {
  2449. object_init(&param);
  2450. if (par->attribute) {
  2451. add_property_string(&param, "attribute", par->attribute);
  2452. }
  2453. if (par->value) {
  2454. add_property_string(&param, "value", par->value);
  2455. }
  2456. php_imap_list_add_object(&parametres, &param);
  2457. } while ((par = par->next));
  2458. } else {
  2459. object_init(&parametres);
  2460. add_property_long(return_value, "ifparameters", 0);
  2461. }
  2462. php_imap_hash_add_object(return_value, "parameters", &parametres);
  2463. }
  2464. /* }}} */
  2465. /* {{{ Read an overview of the information in the headers of the given message sequence */
  2466. PHP_FUNCTION(imap_fetch_overview)
  2467. {
  2468. zval *imap_conn_obj;
  2469. zend_string *sequence;
  2470. php_imap_object *imap_conn_struct;
  2471. zval myoverview;
  2472. zend_string *address;
  2473. zend_long status, flags = 0L;
  2474. if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS|l", &imap_conn_obj, php_imap_ce, &sequence, &flags) == FAILURE) {
  2475. RETURN_THROWS();
  2476. }
  2477. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  2478. if (flags && ((flags & ~FT_UID) != 0)) {
  2479. zend_argument_value_error(3, "must be FT_UID or 0");
  2480. RETURN_THROWS();
  2481. }
  2482. array_init(return_value);
  2483. status = (flags & FT_UID)
  2484. ? mail_uid_sequence(imap_conn_struct->imap_stream, (unsigned char*)ZSTR_VAL(sequence))
  2485. : mail_sequence(imap_conn_struct->imap_stream, (unsigned char*)ZSTR_VAL(sequence));
  2486. if (status) {
  2487. MESSAGECACHE *elt;
  2488. ENVELOPE *env;
  2489. unsigned long i;
  2490. for (i = 1; i <= imap_conn_struct->imap_stream->nmsgs; i++) {
  2491. if (((elt = mail_elt (imap_conn_struct->imap_stream, i))->sequence) &&
  2492. (env = mail_fetch_structure (imap_conn_struct->imap_stream, i, NIL, NIL))) {
  2493. object_init(&myoverview);
  2494. if (env->subject) {
  2495. add_property_string(&myoverview, "subject", env->subject);
  2496. }
  2497. if (env->from) {
  2498. env->from->next=NULL;
  2499. address =_php_rfc822_write_address(env->from);
  2500. if (address) {
  2501. add_property_str(&myoverview, "from", address);
  2502. }
  2503. }
  2504. if (env->to) {
  2505. env->to->next = NULL;
  2506. address = _php_rfc822_write_address(env->to);
  2507. if (address) {
  2508. add_property_str(&myoverview, "to", address);
  2509. }
  2510. }
  2511. if (env->date) {
  2512. add_property_string(&myoverview, "date", (char*)env->date);
  2513. }
  2514. if (env->message_id) {
  2515. add_property_string(&myoverview, "message_id", env->message_id);
  2516. }
  2517. if (env->references) {
  2518. add_property_string(&myoverview, "references", env->references);
  2519. }
  2520. if (env->in_reply_to) {
  2521. add_property_string(&myoverview, "in_reply_to", env->in_reply_to);
  2522. }
  2523. add_property_long(&myoverview, "size", elt->rfc822_size);
  2524. add_property_long(&myoverview, "uid", mail_uid(imap_conn_struct->imap_stream, i));
  2525. add_property_long(&myoverview, "msgno", i);
  2526. add_property_long(&myoverview, "recent", elt->recent);
  2527. add_property_long(&myoverview, "flagged", elt->flagged);
  2528. add_property_long(&myoverview, "answered", elt->answered);
  2529. add_property_long(&myoverview, "deleted", elt->deleted);
  2530. add_property_long(&myoverview, "seen", elt->seen);
  2531. add_property_long(&myoverview, "draft", elt->draft);
  2532. add_property_long(&myoverview, "udate", mail_longdate(elt));
  2533. php_imap_list_add_object(return_value, &myoverview);
  2534. }
  2535. }
  2536. }
  2537. }
  2538. /* }}} */
  2539. static bool header_injection(zend_string *str, bool adrlist)
  2540. {
  2541. char *p = ZSTR_VAL(str);
  2542. while ((p = strpbrk(p, "\r\n")) != NULL) {
  2543. if (!(p[0] == '\r' && p[1] == '\n')
  2544. /* adrlists do not support folding, but swallow trailing line breaks */
  2545. && !((adrlist && p[1] == '\0')
  2546. /* other headers support folding */
  2547. || (!adrlist && (p[1] == ' ' || p[1] == '\t')))) {
  2548. return 1;
  2549. }
  2550. p++;
  2551. }
  2552. return 0;
  2553. }
  2554. /* {{{ Create a MIME message based on given envelope and body sections */
  2555. PHP_FUNCTION(imap_mail_compose)
  2556. {
  2557. HashTable *envelope, *body;
  2558. zend_string *key;
  2559. zval *data, *pvalue, *disp_data, *env_data;
  2560. char *cookie = NIL;
  2561. ENVELOPE *env;
  2562. BODY *bod=NULL, *topbod=NULL;
  2563. PART *mypart=NULL, *part;
  2564. PARAMETER *param, *disp_param = NULL, *custom_headers_param = NULL, *tmp_param = NULL;
  2565. char *tmp=NULL, *mystring=NULL, *t=NULL, *tempstring=NULL, *str_copy = NULL;
  2566. int toppart = 0;
  2567. int first;
  2568. if (zend_parse_parameters(ZEND_NUM_ARGS(), "h/h/", &envelope, &body) == FAILURE) {
  2569. RETURN_THROWS();
  2570. }
  2571. if (zend_hash_num_elements(body) == 0) {
  2572. zend_argument_value_error(2, "cannot be empty");
  2573. }
  2574. #define CHECK_HEADER_INJECTION(zstr, adrlist, header) \
  2575. if (header_injection(zstr, adrlist)) { \
  2576. php_error_docref(NULL, E_WARNING, "header injection attempt in " header); \
  2577. RETVAL_FALSE; \
  2578. goto done; \
  2579. }
  2580. #define PHP_RFC822_PARSE_ADRLIST(target, value) \
  2581. str_copy = estrndup(Z_STRVAL_P(value), Z_STRLEN_P(value)); \
  2582. rfc822_parse_adrlist(target, str_copy, "NO HOST"); \
  2583. efree(str_copy);
  2584. env = mail_newenvelope();
  2585. if ((pvalue = zend_hash_str_find(envelope, "remail", sizeof("remail") - 1)) != NULL) {
  2586. convert_to_string(pvalue);
  2587. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "remail");
  2588. env->remail = cpystr(Z_STRVAL_P(pvalue));
  2589. }
  2590. if ((pvalue = zend_hash_str_find(envelope, "return_path", sizeof("return_path") - 1)) != NULL) {
  2591. convert_to_string(pvalue);
  2592. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "return_path");
  2593. PHP_RFC822_PARSE_ADRLIST(&env->return_path, pvalue);
  2594. }
  2595. if ((pvalue = zend_hash_str_find(envelope, "date", sizeof("date") - 1)) != NULL) {
  2596. convert_to_string(pvalue);
  2597. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "date");
  2598. env->date = (unsigned char*)cpystr(Z_STRVAL_P(pvalue));
  2599. }
  2600. if ((pvalue = zend_hash_str_find(envelope, "from", sizeof("from") - 1)) != NULL) {
  2601. convert_to_string(pvalue);
  2602. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "from");
  2603. PHP_RFC822_PARSE_ADRLIST(&env->from, pvalue);
  2604. }
  2605. if ((pvalue = zend_hash_str_find(envelope, "reply_to", sizeof("reply_to") - 1)) != NULL) {
  2606. convert_to_string(pvalue);
  2607. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "reply_to");
  2608. PHP_RFC822_PARSE_ADRLIST(&env->reply_to, pvalue);
  2609. }
  2610. if ((pvalue = zend_hash_str_find(envelope, "in_reply_to", sizeof("in_reply_to") - 1)) != NULL) {
  2611. convert_to_string(pvalue);
  2612. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "in_reply_to");
  2613. env->in_reply_to = cpystr(Z_STRVAL_P(pvalue));
  2614. }
  2615. if ((pvalue = zend_hash_str_find(envelope, "subject", sizeof("subject") - 1)) != NULL) {
  2616. convert_to_string(pvalue);
  2617. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "subject");
  2618. env->subject = cpystr(Z_STRVAL_P(pvalue));
  2619. }
  2620. if ((pvalue = zend_hash_str_find(envelope, "to", sizeof("to") - 1)) != NULL) {
  2621. convert_to_string(pvalue);
  2622. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "to");
  2623. PHP_RFC822_PARSE_ADRLIST(&env->to, pvalue);
  2624. }
  2625. if ((pvalue = zend_hash_str_find(envelope, "cc", sizeof("cc") - 1)) != NULL) {
  2626. convert_to_string(pvalue);
  2627. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "cc");
  2628. PHP_RFC822_PARSE_ADRLIST(&env->cc, pvalue);
  2629. }
  2630. if ((pvalue = zend_hash_str_find(envelope, "bcc", sizeof("bcc") - 1)) != NULL) {
  2631. convert_to_string(pvalue);
  2632. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "bcc");
  2633. PHP_RFC822_PARSE_ADRLIST(&env->bcc, pvalue);
  2634. }
  2635. if ((pvalue = zend_hash_str_find(envelope, "message_id", sizeof("message_id") - 1)) != NULL) {
  2636. convert_to_string(pvalue);
  2637. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "message_id");
  2638. env->message_id=cpystr(Z_STRVAL_P(pvalue));
  2639. }
  2640. if ((pvalue = zend_hash_str_find(envelope, "custom_headers", sizeof("custom_headers") - 1)) != NULL) {
  2641. if (Z_TYPE_P(pvalue) == IS_ARRAY) {
  2642. custom_headers_param = tmp_param = NULL;
  2643. SEPARATE_ARRAY(pvalue);
  2644. ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pvalue), env_data) {
  2645. custom_headers_param = mail_newbody_parameter();
  2646. convert_to_string(env_data);
  2647. CHECK_HEADER_INJECTION(Z_STR_P(env_data), 0, "custom_headers");
  2648. custom_headers_param->value = (char *) fs_get(Z_STRLEN_P(env_data) + 1);
  2649. custom_headers_param->attribute = NULL;
  2650. memcpy(custom_headers_param->value, Z_STRVAL_P(env_data), Z_STRLEN_P(env_data) + 1);
  2651. custom_headers_param->next = tmp_param;
  2652. tmp_param = custom_headers_param;
  2653. } ZEND_HASH_FOREACH_END();
  2654. }
  2655. }
  2656. first = 1;
  2657. ZEND_HASH_FOREACH_VAL(body, data) {
  2658. if (first) {
  2659. first = 0;
  2660. if (Z_TYPE_P(data) != IS_ARRAY) {
  2661. zend_argument_type_error(2, "individual body must be of type array, %s given",
  2662. zend_zval_type_name(data));
  2663. goto done;
  2664. }
  2665. if (zend_hash_num_elements(Z_ARRVAL_P(data)) == 0) {
  2666. zend_argument_value_error(2, "individual body cannot be empty");
  2667. goto done;
  2668. }
  2669. SEPARATE_ARRAY(data);
  2670. bod = mail_newbody();
  2671. topbod = bod;
  2672. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "type", sizeof("type") - 1)) != NULL) {
  2673. zend_long type = zval_get_long(pvalue);
  2674. if (type >= 0 && type <= TYPEMAX && body_types[type] != NULL) {
  2675. bod->type = (short) type;
  2676. }
  2677. }
  2678. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "encoding", sizeof("encoding") - 1)) != NULL) {
  2679. zend_long encoding = zval_get_long(pvalue);
  2680. if (encoding >= 0 && encoding <= ENCMAX && body_encodings[encoding] != NULL) {
  2681. bod->encoding = (short) encoding;
  2682. }
  2683. }
  2684. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "charset", sizeof("charset") - 1)) != NULL) {
  2685. convert_to_string(pvalue);
  2686. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body charset");
  2687. tmp_param = mail_newbody_parameter();
  2688. tmp_param->value = cpystr(Z_STRVAL_P(pvalue));
  2689. tmp_param->attribute = cpystr("CHARSET");
  2690. tmp_param->next = bod->parameter;
  2691. bod->parameter = tmp_param;
  2692. }
  2693. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "type.parameters", sizeof("type.parameters") - 1)) != NULL) {
  2694. if(Z_TYPE_P(pvalue) == IS_ARRAY) {
  2695. disp_param = tmp_param = NULL;
  2696. SEPARATE_ARRAY(pvalue);
  2697. ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
  2698. if (key == NULL) continue;
  2699. CHECK_HEADER_INJECTION(key, 0, "body disposition key");
  2700. disp_param = mail_newbody_parameter();
  2701. disp_param->attribute = cpystr(ZSTR_VAL(key));
  2702. convert_to_string(disp_data);
  2703. CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body disposition value");
  2704. disp_param->value = (char *) fs_get(Z_STRLEN_P(disp_data) + 1);
  2705. memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
  2706. disp_param->next = tmp_param;
  2707. tmp_param = disp_param;
  2708. } ZEND_HASH_FOREACH_END();
  2709. bod->parameter = disp_param;
  2710. }
  2711. }
  2712. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "subtype", sizeof("subtype") - 1)) != NULL) {
  2713. convert_to_string_ex(pvalue);
  2714. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body subtype");
  2715. bod->subtype = cpystr(Z_STRVAL_P(pvalue));
  2716. }
  2717. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "id", sizeof("id") - 1)) != NULL) {
  2718. convert_to_string(pvalue);
  2719. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body id");
  2720. bod->id = cpystr(Z_STRVAL_P(pvalue));
  2721. }
  2722. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "description", sizeof("description") - 1)) != NULL) {
  2723. convert_to_string(pvalue);
  2724. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body description");
  2725. bod->description = cpystr(Z_STRVAL_P(pvalue));
  2726. }
  2727. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "disposition.type", sizeof("disposition.type") - 1)) != NULL) {
  2728. convert_to_string(pvalue);
  2729. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body disposition.type");
  2730. bod->disposition.type = (char *) fs_get(Z_STRLEN_P(pvalue) + 1);
  2731. memcpy(bod->disposition.type, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue)+1);
  2732. }
  2733. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "disposition", sizeof("disposition") - 1)) != NULL) {
  2734. if (Z_TYPE_P(pvalue) == IS_ARRAY) {
  2735. disp_param = tmp_param = NULL;
  2736. SEPARATE_ARRAY(pvalue);
  2737. ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
  2738. if (key == NULL) continue;
  2739. CHECK_HEADER_INJECTION(key, 0, "body type.parameters key");
  2740. disp_param = mail_newbody_parameter();
  2741. disp_param->attribute = cpystr(ZSTR_VAL(key));
  2742. convert_to_string(disp_data);
  2743. CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body type.parameters value");
  2744. disp_param->value = (char *) fs_get(Z_STRLEN_P(disp_data) + 1);
  2745. memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
  2746. disp_param->next = tmp_param;
  2747. tmp_param = disp_param;
  2748. } ZEND_HASH_FOREACH_END();
  2749. bod->disposition.parameter = disp_param;
  2750. }
  2751. }
  2752. if (bod->type == TYPEMESSAGE && bod->subtype && !strcmp(bod->subtype, "RFC822")) {
  2753. bod->nested.msg = mail_newmsg();
  2754. } else {
  2755. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "contents.data", sizeof("contents.data") - 1)) != NULL) {
  2756. convert_to_string(pvalue);
  2757. bod->contents.text.data = fs_get(Z_STRLEN_P(pvalue) + 1);
  2758. memcpy(bod->contents.text.data, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue)+1);
  2759. bod->contents.text.size = Z_STRLEN_P(pvalue);
  2760. } else {
  2761. bod->contents.text.data = fs_get(1);
  2762. memcpy(bod->contents.text.data, "", 1);
  2763. bod->contents.text.size = 0;
  2764. }
  2765. }
  2766. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "lines", sizeof("lines") - 1)) != NULL) {
  2767. bod->size.lines = zval_get_long(pvalue);
  2768. }
  2769. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "bytes", sizeof("bytes") - 1)) != NULL) {
  2770. bod->size.bytes = zval_get_long(pvalue);
  2771. }
  2772. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "md5", sizeof("md5") - 1)) != NULL) {
  2773. convert_to_string(pvalue);
  2774. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body md5");
  2775. bod->md5 = cpystr(Z_STRVAL_P(pvalue));
  2776. }
  2777. } else if (Z_TYPE_P(data) == IS_ARRAY && topbod->type == TYPEMULTIPART) {
  2778. short type = 0;
  2779. SEPARATE_ARRAY(data);
  2780. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "type", sizeof("type") - 1)) != NULL) {
  2781. zend_long tmp_type = zval_get_long(pvalue);
  2782. if (tmp_type >= 0 && tmp_type <= TYPEMAX && tmp_type != TYPEMULTIPART && body_types[tmp_type] != NULL) {
  2783. type = (short) tmp_type;
  2784. }
  2785. }
  2786. if (!toppart) {
  2787. bod->nested.part = mail_newbody_part();
  2788. mypart = bod->nested.part;
  2789. toppart = 1;
  2790. } else {
  2791. mypart->next = mail_newbody_part();
  2792. mypart = mypart->next;
  2793. }
  2794. bod = &mypart->body;
  2795. bod->type = type;
  2796. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "encoding", sizeof("encoding") - 1)) != NULL) {
  2797. zend_long encoding = zval_get_long(pvalue);
  2798. if (encoding >= 0 && encoding <= ENCMAX && body_encodings[encoding] != NULL) {
  2799. bod->encoding = (short) encoding;
  2800. }
  2801. }
  2802. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "charset", sizeof("charset") - 1)) != NULL) {
  2803. convert_to_string_ex(pvalue);
  2804. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body charset");
  2805. tmp_param = mail_newbody_parameter();
  2806. tmp_param->value = (char *) fs_get(Z_STRLEN_P(pvalue) + 1);
  2807. memcpy(tmp_param->value, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue) + 1);
  2808. tmp_param->attribute = cpystr("CHARSET");
  2809. tmp_param->next = bod->parameter;
  2810. bod->parameter = tmp_param;
  2811. }
  2812. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "type.parameters", sizeof("type.parameters") - 1)) != NULL) {
  2813. if (Z_TYPE_P(pvalue) == IS_ARRAY) {
  2814. disp_param = tmp_param = NULL;
  2815. SEPARATE_ARRAY(pvalue);
  2816. ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
  2817. if (key == NULL) continue;
  2818. CHECK_HEADER_INJECTION(key, 0, "body type.parameters key");
  2819. disp_param = mail_newbody_parameter();
  2820. disp_param->attribute = cpystr(ZSTR_VAL(key));
  2821. convert_to_string_ex(disp_data);
  2822. CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body type.parameters value");
  2823. disp_param->value = (char *)fs_get(Z_STRLEN_P(disp_data) + 1);
  2824. memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
  2825. disp_param->next = tmp_param;
  2826. tmp_param = disp_param;
  2827. } ZEND_HASH_FOREACH_END();
  2828. bod->parameter = disp_param;
  2829. }
  2830. }
  2831. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "subtype", sizeof("subtype") - 1)) != NULL) {
  2832. convert_to_string_ex(pvalue);
  2833. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body subtype");
  2834. bod->subtype = cpystr(Z_STRVAL_P(pvalue));
  2835. }
  2836. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "id", sizeof("id") - 1)) != NULL) {
  2837. convert_to_string_ex(pvalue);
  2838. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body id");
  2839. bod->id = cpystr(Z_STRVAL_P(pvalue));
  2840. }
  2841. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "description", sizeof("description") - 1)) != NULL) {
  2842. convert_to_string_ex(pvalue);
  2843. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body description");
  2844. bod->description = cpystr(Z_STRVAL_P(pvalue));
  2845. }
  2846. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "disposition.type", sizeof("disposition.type") - 1)) != NULL) {
  2847. convert_to_string_ex(pvalue);
  2848. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body disposition.type");
  2849. bod->disposition.type = (char *) fs_get(Z_STRLEN_P(pvalue) + 1);
  2850. memcpy(bod->disposition.type, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue)+1);
  2851. }
  2852. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "disposition", sizeof("disposition") - 1)) != NULL) {
  2853. if (Z_TYPE_P(pvalue) == IS_ARRAY) {
  2854. disp_param = tmp_param = NULL;
  2855. SEPARATE_ARRAY(pvalue);
  2856. ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
  2857. if (key == NULL) continue;
  2858. CHECK_HEADER_INJECTION(key, 0, "body disposition key");
  2859. disp_param = mail_newbody_parameter();
  2860. disp_param->attribute = cpystr(ZSTR_VAL(key));
  2861. convert_to_string_ex(disp_data);
  2862. CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body disposition value");
  2863. disp_param->value = (char *) fs_get(Z_STRLEN_P(disp_data) + 1);
  2864. memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
  2865. disp_param->next = tmp_param;
  2866. tmp_param = disp_param;
  2867. } ZEND_HASH_FOREACH_END();
  2868. bod->disposition.parameter = disp_param;
  2869. }
  2870. }
  2871. if (bod->type == TYPEMESSAGE && bod->subtype && !strcmp(bod->subtype, "RFC822")) {
  2872. bod->nested.msg = mail_newmsg();
  2873. } else {
  2874. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "contents.data", sizeof("contents.data") - 1)) != NULL) {
  2875. convert_to_string(pvalue);
  2876. bod->contents.text.data = fs_get(Z_STRLEN_P(pvalue) + 1);
  2877. memcpy(bod->contents.text.data, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue) + 1);
  2878. bod->contents.text.size = Z_STRLEN_P(pvalue);
  2879. } else {
  2880. bod->contents.text.data = fs_get(1);
  2881. memcpy(bod->contents.text.data, "", 1);
  2882. bod->contents.text.size = 0;
  2883. }
  2884. }
  2885. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "lines", sizeof("lines") - 1)) != NULL) {
  2886. bod->size.lines = zval_get_long(pvalue);
  2887. }
  2888. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "bytes", sizeof("bytes") - 1)) != NULL) {
  2889. bod->size.bytes = zval_get_long(pvalue);
  2890. }
  2891. if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "md5", sizeof("md5") - 1)) != NULL) {
  2892. convert_to_string_ex(pvalue);
  2893. CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body md5");
  2894. bod->md5 = cpystr(Z_STRVAL_P(pvalue));
  2895. }
  2896. }
  2897. } ZEND_HASH_FOREACH_END();
  2898. if (bod && bod->type == TYPEMULTIPART && (!bod->nested.part || !bod->nested.part->next)) {
  2899. php_error_docref(NULL, E_WARNING, "Cannot generate multipart e-mail without components.");
  2900. RETVAL_FALSE;
  2901. goto done;
  2902. }
  2903. rfc822_encode_body_7bit(env, topbod);
  2904. tmp = emalloc(SENDBUFLEN + 1);
  2905. rfc822_header(tmp, env, topbod);
  2906. /* add custom envelope headers */
  2907. if (custom_headers_param) {
  2908. int l = strlen(tmp) - 2, l2;
  2909. PARAMETER *tp = custom_headers_param;
  2910. /* remove last CRLF from tmp */
  2911. tmp[l] = '\0';
  2912. tempstring = emalloc(l);
  2913. memcpy(tempstring, tmp, l);
  2914. do {
  2915. l2 = strlen(custom_headers_param->value);
  2916. tempstring = erealloc(tempstring, l + l2 + CRLF_LEN + 1);
  2917. memcpy(tempstring + l, custom_headers_param->value, l2);
  2918. memcpy(tempstring + l + l2, CRLF, CRLF_LEN);
  2919. l += l2 + CRLF_LEN;
  2920. } while ((custom_headers_param = custom_headers_param->next));
  2921. mail_free_body_parameter(&tp);
  2922. mystring = emalloc(l + CRLF_LEN + 1);
  2923. memcpy(mystring, tempstring, l);
  2924. memcpy(mystring + l , CRLF, CRLF_LEN);
  2925. mystring[l + CRLF_LEN] = '\0';
  2926. efree(tempstring);
  2927. } else {
  2928. mystring = estrdup(tmp);
  2929. }
  2930. bod = topbod;
  2931. if (bod && bod->type == TYPEMULTIPART) {
  2932. /* first body part */
  2933. part = bod->nested.part;
  2934. /* find cookie */
  2935. for (param = bod->parameter; param && !cookie; param = param->next) {
  2936. if (!strcmp (param->attribute, "BOUNDARY")) {
  2937. cookie = param->value;
  2938. }
  2939. }
  2940. /* yucky default */
  2941. if (!cookie) {
  2942. cookie = "-";
  2943. } else if (strlen(cookie) > (SENDBUFLEN - 2 - 2 - 2)) { /* validate cookie length -- + CRLF * 2 */
  2944. php_error_docref(NULL, E_WARNING, "The boundary should be no longer than 4kb");
  2945. RETVAL_FALSE;
  2946. goto done;
  2947. }
  2948. /* for each part */
  2949. do {
  2950. t = tmp;
  2951. /* append mini-header */
  2952. *t = '\0';
  2953. rfc822_write_body_header(&t, &part->body);
  2954. /* output cookie, mini-header, and contents */
  2955. spprintf(&tempstring, 0, "%s--%s%s%s%s", mystring, cookie, CRLF, tmp, CRLF);
  2956. efree(mystring);
  2957. mystring=tempstring;
  2958. bod=&part->body;
  2959. spprintf(&tempstring, 0, "%s%s%s", mystring, bod->contents.text.data ? (char *) bod->contents.text.data : "", CRLF);
  2960. efree(mystring);
  2961. mystring=tempstring;
  2962. } while ((part = part->next)); /* until done */
  2963. /* output trailing cookie */
  2964. spprintf(&tempstring, 0, "%s--%s--%s", mystring, cookie, CRLF);
  2965. efree(mystring);
  2966. mystring=tempstring;
  2967. } else if (bod) {
  2968. spprintf(&tempstring, 0, "%s%s%s", mystring, bod->contents.text.data ? (char *) bod->contents.text.data : "", CRLF);
  2969. efree(mystring);
  2970. mystring=tempstring;
  2971. } else {
  2972. efree(mystring);
  2973. RETVAL_FALSE;
  2974. goto done;
  2975. }
  2976. RETVAL_STRING(tempstring);
  2977. efree(tempstring);
  2978. done:
  2979. if (tmp) {
  2980. efree(tmp);
  2981. }
  2982. mail_free_body(&topbod);
  2983. mail_free_envelope(&env);
  2984. }
  2985. /* }}} */
  2986. /* {{{ _php_imap_mail */
  2987. bool _php_imap_mail(zend_string *to, zend_string *subject, zend_string *message, zend_string *headers,
  2988. zend_string *cc, zend_string *bcc, zend_string* rpath)
  2989. {
  2990. #ifdef PHP_WIN32
  2991. int tsm_err;
  2992. #else
  2993. FILE *sendmail;
  2994. int ret;
  2995. #endif
  2996. ZEND_ASSERT(to && ZSTR_LEN(to) != 0);
  2997. ZEND_ASSERT(subject && ZSTR_LEN(subject) != 0);
  2998. ZEND_ASSERT(message);
  2999. #ifdef PHP_WIN32
  3000. char *tempMailTo;
  3001. char *tsm_errmsg = NULL;
  3002. ADDRESS *addr;
  3003. char *bufferTo = NULL, *bufferCc = NULL, *bufferBcc = NULL, *bufferHeader = NULL;
  3004. size_t offset, bufferLen = 0;
  3005. size_t bt_len;
  3006. /* Add "To" field's necessary buffer length */
  3007. bufferLen += ZSTR_LEN(to) + 6;
  3008. if (headers) {
  3009. bufferLen += ZSTR_LEN(headers);
  3010. }
  3011. if (cc) {
  3012. bufferLen += ZSTR_LEN(cc) + 6;
  3013. }
  3014. #define PHP_IMAP_CLEAN if (bufferTo) efree(bufferTo); if (bufferCc) efree(bufferCc); if (bufferBcc) efree(bufferBcc); if (bufferHeader) efree(bufferHeader);
  3015. #define PHP_IMAP_BAD_DEST PHP_IMAP_CLEAN; efree(tempMailTo); return (BAD_MSG_DESTINATION);
  3016. bufferHeader = (char *)safe_emalloc(bufferLen, 1, 1);
  3017. memset(bufferHeader, 0, bufferLen);
  3018. /* Handle "To" Field */
  3019. strlcat(bufferHeader, "To: ", bufferLen + 1);
  3020. strlcat(bufferHeader, ZSTR_VAL(to), bufferLen + 1);
  3021. strlcat(bufferHeader, "\r\n", bufferLen + 1);
  3022. tempMailTo = estrdup(ZSTR_VAL(to));
  3023. bt_len = ZSTR_LEN(to);
  3024. bufferTo = (char *)safe_emalloc(bt_len, 1, 1);
  3025. bt_len++;
  3026. offset = 0;
  3027. addr = NULL;
  3028. rfc822_parse_adrlist(&addr, tempMailTo, "NO HOST");
  3029. while (addr) {
  3030. if (addr->host == NULL || strcmp(addr->host, ERRHOST) == 0) {
  3031. PHP_IMAP_BAD_DEST;
  3032. } else {
  3033. bufferTo = safe_erealloc(bufferTo, bt_len, 1, strlen(addr->mailbox));
  3034. bt_len += strlen(addr->mailbox);
  3035. bufferTo = safe_erealloc(bufferTo, bt_len, 1, strlen(addr->host));
  3036. bt_len += strlen(addr->host);
  3037. offset += slprintf(bufferTo + offset, bt_len - offset, "%s@%s,", addr->mailbox, addr->host);
  3038. }
  3039. addr = addr->next;
  3040. }
  3041. efree(tempMailTo);
  3042. if (offset>0) {
  3043. bufferTo[offset-1] = 0;
  3044. }
  3045. if (cc && ZSTR_LEN(cc) != 0) {
  3046. strlcat(bufferHeader, "Cc: ", bufferLen + 1);
  3047. strlcat(bufferHeader, ZSTR_VAL(cc), bufferLen + 1);
  3048. strlcat(bufferHeader, "\r\n", bufferLen + 1);
  3049. tempMailTo = estrdup(ZSTR_VAL(cc));
  3050. bt_len = ZSTR_LEN(cc);
  3051. bufferCc = (char *)safe_emalloc(bt_len, 1, 1);
  3052. bt_len++;
  3053. offset = 0;
  3054. addr = NULL;
  3055. rfc822_parse_adrlist(&addr, tempMailTo, "NO HOST");
  3056. while (addr) {
  3057. if (addr->host == NULL || strcmp(addr->host, ERRHOST) == 0) {
  3058. PHP_IMAP_BAD_DEST;
  3059. } else {
  3060. bufferCc = safe_erealloc(bufferCc, bt_len, 1, strlen(addr->mailbox));
  3061. bt_len += strlen(addr->mailbox);
  3062. bufferCc = safe_erealloc(bufferCc, bt_len, 1, strlen(addr->host));
  3063. bt_len += strlen(addr->host);
  3064. offset += slprintf(bufferCc + offset, bt_len - offset, "%s@%s,", addr->mailbox, addr->host);
  3065. }
  3066. addr = addr->next;
  3067. }
  3068. efree(tempMailTo);
  3069. if (offset>0) {
  3070. bufferCc[offset-1] = 0;
  3071. }
  3072. }
  3073. if (bcc && ZSTR_LEN(bcc)) {
  3074. tempMailTo = estrdup(ZSTR_VAL(bcc));
  3075. bt_len = ZSTR_LEN(bcc);
  3076. bufferBcc = (char *)safe_emalloc(bt_len, 1, 1);
  3077. bt_len++;
  3078. offset = 0;
  3079. addr = NULL;
  3080. rfc822_parse_adrlist(&addr, tempMailTo, "NO HOST");
  3081. while (addr) {
  3082. if (addr->host == NULL || strcmp(addr->host, ERRHOST) == 0) {
  3083. PHP_IMAP_BAD_DEST;
  3084. } else {
  3085. bufferBcc = safe_erealloc(bufferBcc, bt_len, 1, strlen(addr->mailbox));
  3086. bt_len += strlen(addr->mailbox);
  3087. bufferBcc = safe_erealloc(bufferBcc, bt_len, 1, strlen(addr->host));
  3088. bt_len += strlen(addr->host);
  3089. offset += slprintf(bufferBcc + offset, bt_len - offset, "%s@%s,", addr->mailbox, addr->host);
  3090. }
  3091. addr = addr->next;
  3092. }
  3093. efree(tempMailTo);
  3094. if (offset>0) {
  3095. bufferBcc[offset-1] = 0;
  3096. }
  3097. }
  3098. if (headers && ZSTR_LEN(headers)) {
  3099. strlcat(bufferHeader, ZSTR_VAL(headers), bufferLen + 1);
  3100. }
  3101. if (TSendMail(INI_STR("SMTP"), &tsm_err, &tsm_errmsg, bufferHeader, ZSTR_VAL(subject),
  3102. bufferTo, ZSTR_VAL(message), bufferCc, bufferBcc, rpath ? ZSTR_VAL(rpath) : NULL) != SUCCESS) {
  3103. if (tsm_errmsg) {
  3104. php_error_docref(NULL, E_WARNING, "%s", tsm_errmsg);
  3105. efree(tsm_errmsg);
  3106. } else {
  3107. php_error_docref(NULL, E_WARNING, "%s", GetSMErrorText(tsm_err));
  3108. }
  3109. PHP_IMAP_CLEAN;
  3110. return 0;
  3111. }
  3112. PHP_IMAP_CLEAN;
  3113. #else
  3114. if (!INI_STR("sendmail_path")) {
  3115. return 0;
  3116. }
  3117. sendmail = popen(INI_STR("sendmail_path"), "w");
  3118. if (sendmail) {
  3119. if (rpath && ZSTR_LEN(rpath) != 0) {
  3120. fprintf(sendmail, "From: %s\n", ZSTR_VAL(rpath));
  3121. }
  3122. /* to cannot be a null pointer, asserted earlier on */
  3123. fprintf(sendmail, "To: %s\n", ZSTR_VAL(to));
  3124. if (cc && ZSTR_LEN(cc) != 0) {
  3125. fprintf(sendmail, "Cc: %s\n", ZSTR_VAL(cc));
  3126. }
  3127. if (bcc && ZSTR_LEN(bcc) != 0) {
  3128. fprintf(sendmail, "Bcc: %s\n", ZSTR_VAL(bcc));
  3129. }
  3130. /* subject cannot be a null pointer, asserted earlier on */
  3131. fprintf(sendmail, "Subject: %s\n", ZSTR_VAL(subject));
  3132. if (headers && ZSTR_LEN(headers) != 0) {
  3133. fprintf(sendmail, "%s\n", ZSTR_VAL(headers));
  3134. }
  3135. /* message cannot be a null pointer, asserted earlier on */
  3136. fprintf(sendmail, "\n%s\n", ZSTR_VAL(message));
  3137. ret = pclose(sendmail);
  3138. return ret != -1;
  3139. } else {
  3140. php_error_docref(NULL, E_WARNING, "Could not execute mail delivery program");
  3141. return 0;
  3142. }
  3143. #endif
  3144. return 1;
  3145. }
  3146. /* }}} */
  3147. /* {{{ Send an email message */
  3148. PHP_FUNCTION(imap_mail)
  3149. {
  3150. zend_string *to=NULL, *message=NULL, *headers=NULL, *subject=NULL, *cc=NULL, *bcc=NULL, *rpath=NULL;
  3151. if (zend_parse_parameters(ZEND_NUM_ARGS(), "PPP|P!P!P!P!", &to, &subject, &message,
  3152. &headers, &cc, &bcc, &rpath) == FAILURE) {
  3153. RETURN_THROWS();
  3154. }
  3155. /* To: */
  3156. if (ZSTR_LEN(to) == 0) {
  3157. zend_argument_value_error(1, "cannot be empty");
  3158. RETURN_THROWS();
  3159. }
  3160. /* Subject: */
  3161. if (ZSTR_LEN(subject) == 0) {
  3162. zend_argument_value_error(2, "cannot be empty");
  3163. RETURN_THROWS();
  3164. }
  3165. /* message body */
  3166. if (ZSTR_LEN(message) == 0) {
  3167. /* this is not really an error, so it is allowed. */
  3168. // TODO Drop warning or emit ValueError?
  3169. php_error_docref(NULL, E_WARNING, "No message string in mail command");
  3170. }
  3171. if (_php_imap_mail(to, subject, message, headers, cc, bcc, rpath)) {
  3172. RETURN_TRUE;
  3173. } else {
  3174. RETURN_FALSE;
  3175. }
  3176. }
  3177. /* }}} */
  3178. /* {{{ Return a list of messages matching the given criteria */
  3179. PHP_FUNCTION(imap_search)
  3180. {
  3181. zval *imap_conn_obj;
  3182. zend_string *criteria, *charset = NULL;
  3183. zend_long flags = SE_FREE;
  3184. php_imap_object *imap_conn_struct;
  3185. char *search_criteria;
  3186. MESSAGELIST *cur;
  3187. int argc = ZEND_NUM_ARGS();
  3188. SEARCHPGM *pgm = NIL;
  3189. if (zend_parse_parameters(argc, "OS|lS", &imap_conn_obj, php_imap_ce, &criteria, &flags, &charset) == FAILURE) {
  3190. RETURN_THROWS();
  3191. }
  3192. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  3193. /* TODO Update docs to allow SE_FREE as an option */
  3194. if (flags && ((flags & ~(SE_FREE | SE_UID)) != 0)) {
  3195. zend_argument_value_error(3, "must be a bitmask of SE_FREE, and SE_UID");
  3196. RETURN_THROWS();
  3197. }
  3198. search_criteria = estrndup(ZSTR_VAL(criteria), ZSTR_LEN(criteria));
  3199. IMAPG(imap_messages) = IMAPG(imap_messages_tail) = NIL;
  3200. pgm = mail_criteria(search_criteria);
  3201. mail_search_full(imap_conn_struct->imap_stream, (argc == 4 ? ZSTR_VAL(charset) : NIL), pgm, flags);
  3202. if (pgm && !(flags & SE_FREE)) {
  3203. mail_free_searchpgm(&pgm);
  3204. }
  3205. if (IMAPG(imap_messages) == NIL) {
  3206. efree(search_criteria);
  3207. RETURN_FALSE;
  3208. }
  3209. array_init(return_value);
  3210. cur = IMAPG(imap_messages);
  3211. while (cur != NIL) {
  3212. add_next_index_long(return_value, cur->msgid);
  3213. cur = cur->next;
  3214. }
  3215. mail_free_messagelist(&IMAPG(imap_messages), &IMAPG(imap_messages_tail));
  3216. efree(search_criteria);
  3217. }
  3218. /* }}} */
  3219. /* {{{ Returns an array of all IMAP alerts that have been generated since the last page load or since the last imap_alerts() call, whichever came last. The alert stack is cleared after imap_alerts() is called. */
  3220. /* Author: CJH */
  3221. PHP_FUNCTION(imap_alerts)
  3222. {
  3223. STRINGLIST *cur=NIL;
  3224. if (zend_parse_parameters_none() == FAILURE) {
  3225. RETURN_THROWS();
  3226. }
  3227. if (IMAPG(imap_alertstack) == NIL) {
  3228. RETURN_FALSE;
  3229. }
  3230. array_init(return_value);
  3231. cur = IMAPG(imap_alertstack);
  3232. while (cur != NIL) {
  3233. add_next_index_string(return_value, (char*)cur->LTEXT);
  3234. cur = cur->next;
  3235. }
  3236. mail_free_stringlist(&IMAPG(imap_alertstack));
  3237. IMAPG(imap_alertstack) = NIL;
  3238. }
  3239. /* }}} */
  3240. /* {{{ Returns an array of all IMAP errors generated since the last page load, or since the last imap_errors() call, whichever came last. The error stack is cleared after imap_errors() is called. */
  3241. /* Author: CJH */
  3242. PHP_FUNCTION(imap_errors)
  3243. {
  3244. ERRORLIST *cur=NIL;
  3245. if (zend_parse_parameters_none() == FAILURE) {
  3246. RETURN_THROWS();
  3247. }
  3248. if (IMAPG(imap_errorstack) == NIL) {
  3249. RETURN_FALSE;
  3250. }
  3251. array_init(return_value);
  3252. cur = IMAPG(imap_errorstack);
  3253. while (cur != NIL) {
  3254. add_next_index_string(return_value, (char*)cur->LTEXT);
  3255. cur = cur->next;
  3256. }
  3257. mail_free_errorlist(&IMAPG(imap_errorstack));
  3258. IMAPG(imap_errorstack) = NIL;
  3259. }
  3260. /* }}} */
  3261. /* {{{ Returns the last error that was generated by an IMAP function. The error stack is NOT cleared after this call. */
  3262. /* Author: CJH */
  3263. PHP_FUNCTION(imap_last_error)
  3264. {
  3265. ERRORLIST *cur=NIL;
  3266. if (zend_parse_parameters_none() == FAILURE) {
  3267. RETURN_THROWS();
  3268. }
  3269. if (IMAPG(imap_errorstack) == NIL) {
  3270. RETURN_FALSE;
  3271. }
  3272. cur = IMAPG(imap_errorstack);
  3273. while (cur != NIL) {
  3274. if (cur->next == NIL) {
  3275. RETURN_STRING((char*)cur->LTEXT);
  3276. }
  3277. cur = cur->next;
  3278. }
  3279. }
  3280. /* }}} */
  3281. /* {{{ Decode mime header element in accordance with RFC 2047 and return array of objects containing 'charset' encoding and decoded 'text' */
  3282. PHP_FUNCTION(imap_mime_header_decode)
  3283. {
  3284. /* Author: Ted Parnefors <ted@mtv.se> */
  3285. zval myobject;
  3286. zend_string *str;
  3287. char *string, *charset, encoding, *text, *decode;
  3288. zend_long charset_token, encoding_token, end_token, end, offset=0, i;
  3289. unsigned long newlength;
  3290. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
  3291. RETURN_THROWS();
  3292. }
  3293. array_init(return_value);
  3294. string = ZSTR_VAL(str);
  3295. end = ZSTR_LEN(str);
  3296. charset = (char *) safe_emalloc((end + 1), 2, 0);
  3297. text = &charset[end + 1];
  3298. while (offset < end) { /* Reached end of the string? */
  3299. if ((charset_token = (zend_long)php_memnstr(&string[offset], "=?", 2, string + end))) { /* Is there anything encoded in the string? */
  3300. charset_token -= (zend_long)string;
  3301. if (offset != charset_token) { /* Is there anything before the encoded data? */
  3302. /* Retrieve unencoded data that is found before encoded data */
  3303. memcpy(text, &string[offset], charset_token-offset);
  3304. text[charset_token - offset] = 0x00;
  3305. object_init(&myobject);
  3306. add_property_string(&myobject, "charset", "default");
  3307. add_property_string(&myobject, "text", text);
  3308. zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &myobject);
  3309. }
  3310. if ((encoding_token = (zend_long)php_memnstr(&string[charset_token+2], "?", 1, string+end))) { /* Find token for encoding */
  3311. encoding_token -= (zend_long)string;
  3312. if ((end_token = (zend_long)php_memnstr(&string[encoding_token+3], "?=", 2, string+end))) { /* Find token for end of encoded data */
  3313. end_token -= (zend_long)string;
  3314. memcpy(charset, &string[charset_token + 2], encoding_token - (charset_token + 2)); /* Extract charset encoding */
  3315. charset[encoding_token-(charset_token + 2)] = 0x00;
  3316. encoding=string[encoding_token + 1]; /* Extract encoding from string */
  3317. memcpy(text, &string[encoding_token + 3], end_token - (encoding_token + 3)); /* Extract text */
  3318. text[end_token - (encoding_token + 3)] = 0x00;
  3319. decode = text;
  3320. if (encoding == 'q' || encoding == 'Q') { /* Decode 'q' encoded data */
  3321. for(i=0; text[i] != 0x00; i++) if (text[i] == '_') text[i] = ' '; /* Replace all *_' with space. */
  3322. decode = (char *)rfc822_qprint((unsigned char *) text, strlen(text), &newlength);
  3323. } else if (encoding == 'b' || encoding == 'B') {
  3324. decode = (char *)rfc822_base64((unsigned char *) text, strlen(text), &newlength); /* Decode 'B' encoded data */
  3325. }
  3326. if (decode == NULL) {
  3327. efree(charset);
  3328. zend_array_destroy(Z_ARR_P(return_value));
  3329. RETURN_FALSE;
  3330. }
  3331. object_init(&myobject);
  3332. add_property_string(&myobject, "charset", charset);
  3333. add_property_string(&myobject, "text", decode);
  3334. zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &myobject);
  3335. /* only free decode if it was allocated by rfc822_qprint or rfc822_base64 */
  3336. if (decode != text) {
  3337. fs_give((void**)&decode);
  3338. }
  3339. offset = end_token+2;
  3340. for (i = 0; (string[offset + i] == ' ') || (string[offset + i] == 0x0a) || (string[offset + i] == 0x0d) || (string[offset + i] == '\t'); i++);
  3341. if ((string[offset + i] == '=') && (string[offset + i + 1] == '?') && (offset + i < end)) {
  3342. offset += i;
  3343. }
  3344. continue; /*/ Iterate the loop again please. */
  3345. }
  3346. }
  3347. } else {
  3348. /* Just some tweaking to optimize the code, and get the end statements work in a general manner.
  3349. * If we end up here we didn't find a position for "charset_token",
  3350. * so we need to set it to the start of the yet unextracted data.
  3351. */
  3352. charset_token = offset;
  3353. }
  3354. /* Return the rest of the data as unencoded, as it was either unencoded or was missing separators
  3355. which rendered the remainder of the string impossible for us to decode. */
  3356. memcpy(text, &string[charset_token], end - charset_token); /* Extract unencoded text from string */
  3357. text[end - charset_token] = 0x00;
  3358. object_init(&myobject);
  3359. add_property_string(&myobject, "charset", "default");
  3360. add_property_string(&myobject, "text", text);
  3361. zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &myobject);
  3362. offset = end; /* We have reached the end of the string. */
  3363. }
  3364. efree(charset);
  3365. }
  3366. /* }}} */
  3367. /* Support Functions */
  3368. #ifdef HAVE_RFC822_OUTPUT_ADDRESS_LIST
  3369. /* {{{ _php_rfc822_soutr */
  3370. static long _php_rfc822_soutr (void *stream, char *string)
  3371. {
  3372. smart_str *ret = (smart_str*)stream;
  3373. int len = strlen(string);
  3374. smart_str_appendl(ret, string, len);
  3375. return LONGT;
  3376. }
  3377. /* }}} */
  3378. /* {{{ _php_rfc822_write_address */
  3379. static zend_string* _php_rfc822_write_address(ADDRESS *addresslist)
  3380. {
  3381. char address[MAILTMPLEN];
  3382. smart_str ret = {0};
  3383. RFC822BUFFER buf;
  3384. buf.beg = address;
  3385. buf.cur = buf.beg;
  3386. buf.end = buf.beg + sizeof(address) - 1;
  3387. buf.s = &ret;
  3388. buf.f = _php_rfc822_soutr;
  3389. rfc822_output_address_list(&buf, addresslist, 0, NULL);
  3390. rfc822_output_flush(&buf);
  3391. smart_str_0(&ret);
  3392. return ret.s;
  3393. }
  3394. /* }}} */
  3395. #else
  3396. /* {{{ _php_rfc822_len
  3397. * Calculate string length based on imap's rfc822_cat function.
  3398. */
  3399. static int _php_rfc822_len(char *str)
  3400. {
  3401. int len;
  3402. char *p;
  3403. if (!str || !*str) {
  3404. return 0;
  3405. }
  3406. /* strings with special characters will need to be quoted, as a safety measure we
  3407. * add 2 bytes for the quotes just in case.
  3408. */
  3409. len = strlen(str) + 2;
  3410. p = str;
  3411. /* rfc822_cat() will escape all " and \ characters, therefore we need to increase
  3412. * our buffer length to account for these characters.
  3413. */
  3414. while ((p = strpbrk(p, "\\\""))) {
  3415. p++;
  3416. len++;
  3417. }
  3418. return len;
  3419. }
  3420. /* }}} */
  3421. /* {{{ _php_imap_get_address_size */
  3422. static int _php_imap_address_size (ADDRESS *addresslist)
  3423. {
  3424. ADDRESS *tmp;
  3425. int ret=0, num_ent=0;
  3426. tmp = addresslist;
  3427. if (tmp) do {
  3428. ret += _php_rfc822_len(tmp->personal);
  3429. ret += _php_rfc822_len(tmp->adl);
  3430. ret += _php_rfc822_len(tmp->mailbox);
  3431. ret += _php_rfc822_len(tmp->host);
  3432. num_ent++;
  3433. } while ((tmp = tmp->next));
  3434. /*
  3435. * rfc822_write_address_full() needs some extra space for '<>,', etc.
  3436. * for this perpouse we allocate additional PHP_IMAP_ADDRESS_SIZE_BUF bytes
  3437. * by default this buffer is 10 bytes long
  3438. */
  3439. ret += (ret) ? num_ent*PHP_IMAP_ADDRESS_SIZE_BUF : 0;
  3440. return ret;
  3441. }
  3442. /* }}} */
  3443. /* {{{ _php_rfc822_write_address */
  3444. static zend_string* _php_rfc822_write_address(ADDRESS *addresslist)
  3445. {
  3446. char address[SENDBUFLEN];
  3447. if (_php_imap_address_size(addresslist) >= SENDBUFLEN) {
  3448. zend_throw_error(NULL, "Address buffer overflow");
  3449. return NULL;
  3450. }
  3451. address[0] = 0;
  3452. rfc822_write_address(address, addresslist);
  3453. return zend_string_init(address, strlen(address), 0);
  3454. }
  3455. /* }}} */
  3456. #endif
  3457. /* {{{ _php_imap_parse_address */
  3458. static zend_string* _php_imap_parse_address (ADDRESS *addresslist, zval *paddress)
  3459. {
  3460. zend_string *fulladdress;
  3461. ADDRESS *addresstmp;
  3462. zval tmpvals;
  3463. addresstmp = addresslist;
  3464. fulladdress = _php_rfc822_write_address(addresstmp);
  3465. addresstmp = addresslist;
  3466. do {
  3467. object_init(&tmpvals);
  3468. if (addresstmp->personal) add_property_string(&tmpvals, "personal", addresstmp->personal);
  3469. if (addresstmp->adl) add_property_string(&tmpvals, "adl", addresstmp->adl);
  3470. if (addresstmp->mailbox) add_property_string(&tmpvals, "mailbox", addresstmp->mailbox);
  3471. if (addresstmp->host) add_property_string(&tmpvals, "host", addresstmp->host);
  3472. php_imap_list_add_object(paddress, &tmpvals);
  3473. } while ((addresstmp = addresstmp->next));
  3474. return fulladdress;
  3475. }
  3476. /* }}} */
  3477. /* {{{ _php_make_header_object */
  3478. static void _php_make_header_object(zval *myzvalue, ENVELOPE *en)
  3479. {
  3480. zval paddress;
  3481. zend_string *fulladdress=NULL;
  3482. object_init(myzvalue);
  3483. if (en->remail) add_property_string(myzvalue, "remail", en->remail);
  3484. if (en->date) add_property_string(myzvalue, "date", (char*)en->date);
  3485. if (en->date) add_property_string(myzvalue, "Date", (char*)en->date);
  3486. if (en->subject) add_property_string(myzvalue, "subject", en->subject);
  3487. if (en->subject) add_property_string(myzvalue, "Subject", en->subject);
  3488. if (en->in_reply_to) add_property_string(myzvalue, "in_reply_to", en->in_reply_to);
  3489. if (en->message_id) add_property_string(myzvalue, "message_id", en->message_id);
  3490. if (en->newsgroups) add_property_string(myzvalue, "newsgroups", en->newsgroups);
  3491. if (en->followup_to) add_property_string(myzvalue, "followup_to", en->followup_to);
  3492. if (en->references) add_property_string(myzvalue, "references", en->references);
  3493. if (en->to) {
  3494. array_init(&paddress);
  3495. fulladdress = _php_imap_parse_address(en->to, &paddress);
  3496. if (fulladdress) {
  3497. add_property_str(myzvalue, "toaddress", fulladdress);
  3498. }
  3499. php_imap_hash_add_object(myzvalue, "to", &paddress);
  3500. }
  3501. if (en->from) {
  3502. array_init(&paddress);
  3503. fulladdress = _php_imap_parse_address(en->from, &paddress);
  3504. if (fulladdress) {
  3505. add_property_str(myzvalue, "fromaddress", fulladdress);
  3506. }
  3507. php_imap_hash_add_object(myzvalue, "from", &paddress);
  3508. }
  3509. if (en->cc) {
  3510. array_init(&paddress);
  3511. fulladdress = _php_imap_parse_address(en->cc, &paddress);
  3512. if (fulladdress) {
  3513. add_property_str(myzvalue, "ccaddress", fulladdress);
  3514. }
  3515. php_imap_hash_add_object(myzvalue, "cc", &paddress);
  3516. }
  3517. if (en->bcc) {
  3518. array_init(&paddress);
  3519. fulladdress = _php_imap_parse_address(en->bcc, &paddress);
  3520. if (fulladdress) {
  3521. add_property_str(myzvalue, "bccaddress", fulladdress);
  3522. }
  3523. php_imap_hash_add_object(myzvalue, "bcc", &paddress);
  3524. }
  3525. if (en->reply_to) {
  3526. array_init(&paddress);
  3527. fulladdress = _php_imap_parse_address(en->reply_to, &paddress);
  3528. if (fulladdress) {
  3529. add_property_str(myzvalue, "reply_toaddress", fulladdress);
  3530. }
  3531. php_imap_hash_add_object(myzvalue, "reply_to", &paddress);
  3532. }
  3533. if (en->sender) {
  3534. array_init(&paddress);
  3535. fulladdress = _php_imap_parse_address(en->sender, &paddress);
  3536. if (fulladdress) {
  3537. add_property_str(myzvalue, "senderaddress", fulladdress);
  3538. }
  3539. php_imap_hash_add_object(myzvalue, "sender", &paddress);
  3540. }
  3541. if (en->return_path) {
  3542. array_init(&paddress);
  3543. fulladdress = _php_imap_parse_address(en->return_path, &paddress);
  3544. if (fulladdress) {
  3545. add_property_str(myzvalue, "return_pathaddress", fulladdress);
  3546. }
  3547. php_imap_hash_add_object(myzvalue, "return_path", &paddress);
  3548. // From rebase might need?
  3549. //add_assoc_object(myzvalue, "return_path", &paddress);
  3550. }
  3551. }
  3552. /* }}} */
  3553. /* {{{ _php_imap_add_body */
  3554. void _php_imap_add_body(zval *arg, BODY *body)
  3555. {
  3556. zval parametres, param, dparametres, dparam;
  3557. PARAMETER *par, *dpar;
  3558. PART *part;
  3559. if (body->type <= TYPEMAX) {
  3560. add_property_long(arg, "type", body->type);
  3561. }
  3562. if (body->encoding <= ENCMAX) {
  3563. add_property_long(arg, "encoding", body->encoding);
  3564. }
  3565. if (body->subtype) {
  3566. add_property_long(arg, "ifsubtype", 1);
  3567. add_property_string(arg, "subtype", body->subtype);
  3568. } else {
  3569. add_property_long(arg, "ifsubtype", 0);
  3570. }
  3571. if (body->description) {
  3572. add_property_long(arg, "ifdescription", 1);
  3573. add_property_string(arg, "description", body->description);
  3574. } else {
  3575. add_property_long(arg, "ifdescription", 0);
  3576. }
  3577. if (body->id) {
  3578. add_property_long(arg, "ifid", 1);
  3579. add_property_string(arg, "id", body->id);
  3580. } else {
  3581. add_property_long(arg, "ifid", 0);
  3582. }
  3583. if (body->size.lines) {
  3584. add_property_long(arg, "lines", body->size.lines);
  3585. }
  3586. if (body->size.bytes) {
  3587. add_property_long(arg, "bytes", body->size.bytes);
  3588. }
  3589. #ifdef IMAP41
  3590. if (body->disposition.type) {
  3591. add_property_long(arg, "ifdisposition", 1);
  3592. add_property_string(arg, "disposition", body->disposition.type);
  3593. } else {
  3594. add_property_long(arg, "ifdisposition", 0);
  3595. }
  3596. if (body->disposition.parameter) {
  3597. dpar = body->disposition.parameter;
  3598. add_property_long(arg, "ifdparameters", 1);
  3599. array_init(&dparametres);
  3600. do {
  3601. object_init(&dparam);
  3602. add_property_string(&dparam, "attribute", dpar->attribute);
  3603. add_property_string(&dparam, "value", dpar->value);
  3604. php_imap_list_add_object(&dparametres, &dparam);
  3605. } while ((dpar = dpar->next));
  3606. php_imap_hash_add_object(arg, "dparameters", &dparametres);
  3607. } else {
  3608. add_property_long(arg, "ifdparameters", 0);
  3609. }
  3610. #endif
  3611. if ((par = body->parameter)) {
  3612. add_property_long(arg, "ifparameters", 1);
  3613. array_init(&parametres);
  3614. do {
  3615. object_init(&param);
  3616. if (par->attribute) {
  3617. add_property_string(&param, "attribute", par->attribute);
  3618. }
  3619. if (par->value) {
  3620. add_property_string(&param, "value", par->value);
  3621. }
  3622. php_imap_list_add_object(&parametres, &param);
  3623. } while ((par = par->next));
  3624. } else {
  3625. object_init(&parametres);
  3626. add_property_long(arg, "ifparameters", 0);
  3627. }
  3628. php_imap_hash_add_object(arg, "parameters", &parametres);
  3629. /* multipart message ? */
  3630. if (body->type == TYPEMULTIPART) {
  3631. array_init(&parametres);
  3632. for (part = body->CONTENT_PART; part; part = part->next) {
  3633. object_init(&param);
  3634. _php_imap_add_body(&param, &part->body);
  3635. php_imap_list_add_object(&parametres, &param);
  3636. }
  3637. php_imap_hash_add_object(arg, "parts", &parametres);
  3638. }
  3639. /* encapsulated message ? */
  3640. if ((body->type == TYPEMESSAGE) && (!strcasecmp(body->subtype, "rfc822"))) {
  3641. body = body->CONTENT_MSG_BODY;
  3642. array_init(&parametres);
  3643. object_init(&param);
  3644. _php_imap_add_body(&param, body);
  3645. php_imap_list_add_object(&parametres, &param);
  3646. php_imap_hash_add_object(arg, "parts", &parametres);
  3647. }
  3648. }
  3649. /* }}} */
  3650. /* imap_thread, stealing this from header cclient -rjs3 */
  3651. /* {{{ build_thread_tree_helper */
  3652. static void build_thread_tree_helper(THREADNODE *cur, zval *tree, long *numNodes, char *buf)
  3653. {
  3654. unsigned long thisNode = *numNodes;
  3655. /* define "#.num" */
  3656. snprintf(buf, 25, "%ld.num", thisNode);
  3657. add_assoc_long(tree, buf, cur->num);
  3658. snprintf(buf, 25, "%ld.next", thisNode);
  3659. if(cur->next) {
  3660. (*numNodes)++;
  3661. add_assoc_long(tree, buf, *numNodes);
  3662. build_thread_tree_helper(cur->next, tree, numNodes, buf);
  3663. } else { /* "null pointer" */
  3664. add_assoc_long(tree, buf, 0);
  3665. }
  3666. snprintf(buf, 25, "%ld.branch", thisNode);
  3667. if(cur->branch) {
  3668. (*numNodes)++;
  3669. add_assoc_long(tree, buf, *numNodes);
  3670. build_thread_tree_helper(cur->branch, tree, numNodes, buf);
  3671. } else { /* "null pointer" */
  3672. add_assoc_long(tree, buf, 0);
  3673. }
  3674. }
  3675. /* }}} */
  3676. /* {{{ build_thread_tree */
  3677. static int build_thread_tree(THREADNODE *top, zval **tree)
  3678. {
  3679. long numNodes = 0;
  3680. char buf[25];
  3681. array_init(*tree);
  3682. build_thread_tree_helper(top, *tree, &numNodes, buf);
  3683. return SUCCESS;
  3684. }
  3685. /* }}} */
  3686. /* {{{ Return threaded by REFERENCES tree */
  3687. PHP_FUNCTION(imap_thread)
  3688. {
  3689. zval *imap_conn_obj;
  3690. php_imap_object *imap_conn_struct;
  3691. zend_long flags = SE_FREE;
  3692. char criteria[] = "ALL";
  3693. THREADNODE *top;
  3694. SEARCHPGM *pgm = NIL;
  3695. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|l", &imap_conn_obj, php_imap_ce, &flags) == FAILURE) {
  3696. RETURN_THROWS();
  3697. }
  3698. GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
  3699. /* TODO Check if flags are valid (documentation is not present on php.net so need to check this first) */
  3700. pgm = mail_criteria(criteria);
  3701. top = mail_thread(imap_conn_struct->imap_stream, "REFERENCES", NIL, pgm, flags);
  3702. if (pgm && !(flags & SE_FREE)) {
  3703. mail_free_searchpgm(&pgm);
  3704. }
  3705. if (top == NIL) {
  3706. php_error_docref(NULL, E_WARNING, "Function returned an empty tree");
  3707. RETURN_FALSE;
  3708. }
  3709. /* Populate our return value data structure here. */
  3710. if (build_thread_tree(top, &return_value) == FAILURE) {
  3711. mail_free_threadnode(&top);
  3712. RETURN_FALSE;
  3713. }
  3714. mail_free_threadnode(&top);
  3715. }
  3716. /* }}} */
  3717. /* {{{ Set or fetch imap timeout */
  3718. PHP_FUNCTION(imap_timeout)
  3719. {
  3720. zend_long ttype, timeout=-1;
  3721. int timeout_type;
  3722. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &ttype, &timeout) == FAILURE) {
  3723. RETURN_THROWS();
  3724. }
  3725. if (timeout == -1) {
  3726. switch (ttype) {
  3727. case 1:
  3728. timeout_type = GET_OPENTIMEOUT;
  3729. break;
  3730. case 2:
  3731. timeout_type = GET_READTIMEOUT;
  3732. break;
  3733. case 3:
  3734. timeout_type = GET_WRITETIMEOUT;
  3735. break;
  3736. case 4:
  3737. timeout_type = GET_CLOSETIMEOUT;
  3738. break;
  3739. default:
  3740. RETURN_FALSE;
  3741. break;
  3742. }
  3743. timeout = (zend_long) mail_parameters(NIL, timeout_type, NIL);
  3744. RETURN_LONG(timeout);
  3745. } else if (timeout >= 0) {
  3746. switch (ttype) {
  3747. case 1:
  3748. timeout_type = SET_OPENTIMEOUT;
  3749. break;
  3750. case 2:
  3751. timeout_type = SET_READTIMEOUT;
  3752. break;
  3753. case 3:
  3754. timeout_type = SET_WRITETIMEOUT;
  3755. break;
  3756. case 4:
  3757. timeout_type = SET_CLOSETIMEOUT;
  3758. break;
  3759. default:
  3760. RETURN_FALSE;
  3761. break;
  3762. }
  3763. timeout = (zend_long) mail_parameters(NIL, timeout_type, (void *) timeout);
  3764. RETURN_TRUE;
  3765. } else {
  3766. RETURN_FALSE;
  3767. }
  3768. }
  3769. /* }}} */
  3770. #define GETS_FETCH_SIZE 8196LU
  3771. static char *php_mail_gets(readfn_t f, void *stream, unsigned long size, GETS_DATA *md) /* {{{ */
  3772. {
  3773. /* write to the gets stream if it is set,
  3774. otherwise forward to c-clients gets */
  3775. if (IMAPG(gets_stream)) {
  3776. char buf[GETS_FETCH_SIZE];
  3777. while (size) {
  3778. unsigned long read;
  3779. if (size > GETS_FETCH_SIZE) {
  3780. read = GETS_FETCH_SIZE;
  3781. size -=GETS_FETCH_SIZE;
  3782. } else {
  3783. read = size;
  3784. size = 0;
  3785. }
  3786. if (!f(stream, read, buf)) {
  3787. php_error_docref(NULL, E_WARNING, "Failed to read from socket");
  3788. break;
  3789. } else if (read != php_stream_write(IMAPG(gets_stream), buf, read)) {
  3790. php_error_docref(NULL, E_WARNING, "Failed to write to stream");
  3791. break;
  3792. }
  3793. }
  3794. return NULL;
  3795. } else {
  3796. char *buf = pemalloc(size + 1, 1);
  3797. if (f(stream, size, buf)) {
  3798. buf[size] = '\0';
  3799. } else {
  3800. php_error_docref(NULL, E_WARNING, "Failed to read from socket");
  3801. free(buf);
  3802. buf = NULL;
  3803. }
  3804. return buf;
  3805. }
  3806. }
  3807. /* }}} */
  3808. /* {{{ Interfaces to C-client */
  3809. PHP_IMAP_EXPORT void mm_searched(MAILSTREAM *stream, unsigned long number)
  3810. {
  3811. MESSAGELIST *cur = NIL;
  3812. if (IMAPG(imap_messages) == NIL) {
  3813. IMAPG(imap_messages) = mail_newmessagelist();
  3814. IMAPG(imap_messages)->msgid = number;
  3815. IMAPG(imap_messages)->next = NIL;
  3816. IMAPG(imap_messages_tail) = IMAPG(imap_messages);
  3817. } else {
  3818. cur = IMAPG(imap_messages_tail);
  3819. cur->next = mail_newmessagelist();
  3820. cur = cur->next;
  3821. cur->msgid = number;
  3822. cur->next = NIL;
  3823. IMAPG(imap_messages_tail) = cur;
  3824. }
  3825. }
  3826. PHP_IMAP_EXPORT void mm_exists(MAILSTREAM *stream, unsigned long number)
  3827. {
  3828. }
  3829. PHP_IMAP_EXPORT void mm_expunged(MAILSTREAM *stream, unsigned long number)
  3830. {
  3831. }
  3832. PHP_IMAP_EXPORT void mm_flags(MAILSTREAM *stream, unsigned long number)
  3833. {
  3834. }
  3835. /* Author: CJH */
  3836. PHP_IMAP_EXPORT void mm_notify(MAILSTREAM *stream, char *str, long errflg)
  3837. {
  3838. STRINGLIST *cur = NIL;
  3839. if (strncmp(str, "[ALERT] ", 8) == 0) {
  3840. if (IMAPG(imap_alertstack) == NIL) {
  3841. IMAPG(imap_alertstack) = mail_newstringlist();
  3842. IMAPG(imap_alertstack)->LSIZE = strlen((char*)(IMAPG(imap_alertstack)->LTEXT = (unsigned char*)cpystr(str)));
  3843. IMAPG(imap_alertstack)->next = NIL;
  3844. } else {
  3845. cur = IMAPG(imap_alertstack);
  3846. while (cur->next != NIL) {
  3847. cur = cur->next;
  3848. }
  3849. cur->next = mail_newstringlist ();
  3850. cur = cur->next;
  3851. cur->LSIZE = strlen((char*)(cur->LTEXT = (unsigned char*)cpystr(str)));
  3852. cur->next = NIL;
  3853. }
  3854. }
  3855. }
  3856. PHP_IMAP_EXPORT void mm_list(MAILSTREAM *stream, DTYPE delimiter, char *mailbox, long attributes)
  3857. {
  3858. STRINGLIST *cur=NIL;
  3859. FOBJECTLIST *ocur=NIL;
  3860. if (IMAPG(folderlist_style) == FLIST_OBJECT) {
  3861. /* build up a the new array of objects */
  3862. /* Author: CJH */
  3863. if (IMAPG(imap_folder_objects) == NIL) {
  3864. IMAPG(imap_folder_objects) = mail_newfolderobjectlist();
  3865. IMAPG(imap_folder_objects)->LSIZE=strlen((char*)(IMAPG(imap_folder_objects)->LTEXT = (unsigned char*)cpystr(mailbox)));
  3866. IMAPG(imap_folder_objects)->delimiter = delimiter;
  3867. IMAPG(imap_folder_objects)->attributes = attributes;
  3868. IMAPG(imap_folder_objects)->next = NIL;
  3869. IMAPG(imap_folder_objects_tail) = IMAPG(imap_folder_objects);
  3870. } else {
  3871. ocur=IMAPG(imap_folder_objects_tail);
  3872. ocur->next=mail_newfolderobjectlist();
  3873. ocur=ocur->next;
  3874. ocur->LSIZE = strlen((char*)(ocur->LTEXT = (unsigned char*)cpystr(mailbox)));
  3875. ocur->delimiter = delimiter;
  3876. ocur->attributes = attributes;
  3877. ocur->next = NIL;
  3878. IMAPG(imap_folder_objects_tail) = ocur;
  3879. }
  3880. } else {
  3881. /* build the old IMAPG(imap_folders) variable to allow old imap_listmailbox() to work */
  3882. if (!(attributes & LATT_NOSELECT)) {
  3883. if (IMAPG(imap_folders) == NIL) {
  3884. IMAPG(imap_folders)=mail_newstringlist();
  3885. IMAPG(imap_folders)->LSIZE=strlen((char*)(IMAPG(imap_folders)->LTEXT = (unsigned char*)cpystr(mailbox)));
  3886. IMAPG(imap_folders)->next=NIL;
  3887. IMAPG(imap_folders_tail) = IMAPG(imap_folders);
  3888. } else {
  3889. cur=IMAPG(imap_folders_tail);
  3890. cur->next=mail_newstringlist ();
  3891. cur=cur->next;
  3892. cur->LSIZE = strlen((char*)(cur->LTEXT = (unsigned char*)cpystr(mailbox)));
  3893. cur->next = NIL;
  3894. IMAPG(imap_folders_tail) = cur;
  3895. }
  3896. }
  3897. }
  3898. }
  3899. PHP_IMAP_EXPORT void mm_lsub(MAILSTREAM *stream, DTYPE delimiter, char *mailbox, long attributes)
  3900. {
  3901. STRINGLIST *cur=NIL;
  3902. FOBJECTLIST *ocur=NIL;
  3903. if (IMAPG(folderlist_style) == FLIST_OBJECT) {
  3904. /* build the array of objects */
  3905. /* Author: CJH */
  3906. if (IMAPG(imap_sfolder_objects) == NIL) {
  3907. IMAPG(imap_sfolder_objects) = mail_newfolderobjectlist();
  3908. IMAPG(imap_sfolder_objects)->LSIZE = strlen((char*)(IMAPG(imap_sfolder_objects)->LTEXT = (unsigned char*)cpystr(mailbox)));
  3909. IMAPG(imap_sfolder_objects)->delimiter = delimiter;
  3910. IMAPG(imap_sfolder_objects)->attributes = attributes;
  3911. IMAPG(imap_sfolder_objects)->next = NIL;
  3912. IMAPG(imap_sfolder_objects_tail) = IMAPG(imap_sfolder_objects);
  3913. } else {
  3914. ocur=IMAPG(imap_sfolder_objects_tail);
  3915. ocur->next=mail_newfolderobjectlist();
  3916. ocur=ocur->next;
  3917. ocur->LSIZE=strlen((char*)(ocur->LTEXT = (unsigned char*)cpystr(mailbox)));
  3918. ocur->delimiter = delimiter;
  3919. ocur->attributes = attributes;
  3920. ocur->next = NIL;
  3921. IMAPG(imap_sfolder_objects_tail) = ocur;
  3922. }
  3923. } else {
  3924. /* build the old simple array for imap_listsubscribed() */
  3925. if (IMAPG(imap_sfolders) == NIL) {
  3926. IMAPG(imap_sfolders)=mail_newstringlist();
  3927. IMAPG(imap_sfolders)->LSIZE=strlen((char*)(IMAPG(imap_sfolders)->LTEXT = (unsigned char*)cpystr(mailbox)));
  3928. IMAPG(imap_sfolders)->next=NIL;
  3929. IMAPG(imap_sfolders_tail) = IMAPG(imap_sfolders);
  3930. } else {
  3931. cur=IMAPG(imap_sfolders_tail);
  3932. cur->next=mail_newstringlist ();
  3933. cur=cur->next;
  3934. cur->LSIZE = strlen((char*)(cur->LTEXT = (unsigned char*)cpystr(mailbox)));
  3935. cur->next = NIL;
  3936. IMAPG(imap_sfolders_tail) = cur;
  3937. }
  3938. }
  3939. }
  3940. PHP_IMAP_EXPORT void mm_status(MAILSTREAM *stream, char *mailbox, MAILSTATUS *status)
  3941. {
  3942. IMAPG(status_flags)=status->flags;
  3943. if (IMAPG(status_flags) & SA_MESSAGES) {
  3944. IMAPG(status_messages)=status->messages;
  3945. }
  3946. if (IMAPG(status_flags) & SA_RECENT) {
  3947. IMAPG(status_recent)=status->recent;
  3948. }
  3949. if (IMAPG(status_flags) & SA_UNSEEN) {
  3950. IMAPG(status_unseen)=status->unseen;
  3951. }
  3952. if (IMAPG(status_flags) & SA_UIDNEXT) {
  3953. IMAPG(status_uidnext)=status->uidnext;
  3954. }
  3955. if (IMAPG(status_flags) & SA_UIDVALIDITY) {
  3956. IMAPG(status_uidvalidity)=status->uidvalidity;
  3957. }
  3958. }
  3959. PHP_IMAP_EXPORT void mm_log(char *str, long errflg)
  3960. {
  3961. ERRORLIST *cur = NIL;
  3962. /* Author: CJH */
  3963. if (errflg != NIL) { /* CJH: maybe put these into a more comprehensive log for debugging purposes? */
  3964. if (IMAPG(imap_errorstack) == NIL) {
  3965. IMAPG(imap_errorstack) = mail_newerrorlist();
  3966. IMAPG(imap_errorstack)->LSIZE = strlen((char*)(IMAPG(imap_errorstack)->LTEXT = (unsigned char*)cpystr(str)));
  3967. IMAPG(imap_errorstack)->errflg = errflg;
  3968. IMAPG(imap_errorstack)->next = NIL;
  3969. } else {
  3970. cur = IMAPG(imap_errorstack);
  3971. while (cur->next != NIL) {
  3972. cur = cur->next;
  3973. }
  3974. cur->next = mail_newerrorlist();
  3975. cur = cur->next;
  3976. cur->LSIZE = strlen((char*)(cur->LTEXT = (unsigned char*)cpystr(str)));
  3977. cur->errflg = errflg;
  3978. cur->next = NIL;
  3979. }
  3980. }
  3981. }
  3982. PHP_IMAP_EXPORT void mm_dlog(char *str)
  3983. {
  3984. /* CJH: this is for debugging; it might be useful to allow setting
  3985. the stream to debug mode and capturing this somewhere - syslog?
  3986. php debugger? */
  3987. }
  3988. PHP_IMAP_EXPORT void mm_login(NETMBX *mb, char *user, char *pwd, long trial)
  3989. {
  3990. if (*mb->user) {
  3991. strlcpy (user, mb->user, MAILTMPLEN);
  3992. } else {
  3993. strlcpy (user, IMAPG(imap_user), MAILTMPLEN);
  3994. }
  3995. strlcpy (pwd, IMAPG(imap_password), MAILTMPLEN);
  3996. }
  3997. PHP_IMAP_EXPORT void mm_critical(MAILSTREAM *stream)
  3998. {
  3999. }
  4000. PHP_IMAP_EXPORT void mm_nocritical(MAILSTREAM *stream)
  4001. {
  4002. }
  4003. PHP_IMAP_EXPORT long mm_diskerror(MAILSTREAM *stream, long errcode, long serious)
  4004. {
  4005. return 1;
  4006. }
  4007. PHP_IMAP_EXPORT void mm_fatal(char *str)
  4008. {
  4009. }
  4010. /* }}} */