func_callerid.c 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 1999-2010, Digium, Inc.
  5. *
  6. * See http://www.asterisk.org for more information about
  7. * the Asterisk project. Please do not directly contact
  8. * any of the maintainers of this project for assistance;
  9. * the project provides a web site, mailing lists and IRC
  10. * channels for your use.
  11. *
  12. * This program is free software, distributed under the terms of
  13. * the GNU General Public License Version 2. See the LICENSE file
  14. * at the top of the source tree.
  15. */
  16. /*! \file
  17. *
  18. * \brief Party ID related dialplan functions (Caller-ID, Connected-line, Redirecting)
  19. *
  20. * \ingroup functions
  21. *
  22. * See Also:
  23. * \arg \ref AstCREDITS
  24. */
  25. /*** MODULEINFO
  26. <support_level>core</support_level>
  27. ***/
  28. #include "asterisk.h"
  29. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  30. #include "asterisk/module.h"
  31. #include "asterisk/channel.h"
  32. #include "asterisk/pbx.h"
  33. #include "asterisk/utils.h"
  34. #include "asterisk/app.h"
  35. #include "asterisk/callerid.h"
  36. /*
  37. * Do not document the CALLERID(pres) datatype.
  38. * The name and number now have their own presentation value. The pres
  39. * option will simply live on as a historical relic with as best
  40. * as can be managed backward compatible meaning.
  41. *
  42. * Do not document the CALLERID(ton) datatype.
  43. * It is an alias for num-plan.
  44. *
  45. * Do not document the CALLERID(ANI-subaddr-...) datatype.
  46. * This is not used.
  47. *
  48. * Do not document the CONNECTEDLINE(source) datatype.
  49. * It has turned out to not be needed. The source value is really
  50. * only useful as a possible tracing aid.
  51. *
  52. * Do not document the CONNECTEDLINE(pres) datatype.
  53. * The name and number now have their own presentation value. The pres
  54. * option will simply live on as a historical relic with as best
  55. * as can be managed backward compatible meaning.
  56. *
  57. * Do not document the CONNECTEDLINE(ton) datatype.
  58. * It is an alias for num-plan.
  59. *
  60. * Do not document the REDIRECTING(pres) datatype.
  61. * It has turned out that the from-pres and to-pres values must be kept
  62. * separate. They represent two different parties and there is a case when
  63. * they are active at the same time. The plain pres option will simply
  64. * live on as a historical relic.
  65. *
  66. * Do not document the REDIRECTING(orig-pres), REDIRECTING(from-pres),
  67. * or REDIRECTING(to-pres) datatypes.
  68. * The name and number now have their own presentation value. The orig-pres,
  69. * from-pres, and to-pres options will simply live on as a historical relic
  70. * with as best as can be managed backward compatible meaning.
  71. *
  72. * Do not document the REDIRECTING(orig-ton), REDIRECTING(from-ton),
  73. * or REDIRECTING(to-ton) datatypes.
  74. * They are aliases for orig-num-plan, from-num-plan, and to-num-plan
  75. * respectively.
  76. */
  77. /*** DOCUMENTATION
  78. <function name="CALLERID" language="en_US">
  79. <synopsis>
  80. Gets or sets Caller*ID data on the channel.
  81. </synopsis>
  82. <syntax>
  83. <parameter name="datatype" required="true">
  84. <para>The allowable datatypes are:</para>
  85. <enumlist>
  86. <enum name = "all" />
  87. <enum name = "name" />
  88. <enum name = "name-valid" />
  89. <enum name = "name-charset" />
  90. <enum name = "name-pres" />
  91. <enum name = "num" />
  92. <enum name = "num-valid" />
  93. <enum name = "num-plan" />
  94. <enum name = "num-pres" />
  95. <enum name = "subaddr" />
  96. <enum name = "subaddr-valid" />
  97. <enum name = "subaddr-type" />
  98. <enum name = "subaddr-odd" />
  99. <enum name = "tag" />
  100. <enum name = "priv-all" />
  101. <enum name = "priv-name" />
  102. <enum name = "priv-name-valid" />
  103. <enum name = "priv-name-charset" />
  104. <enum name = "priv-name-pres" />
  105. <enum name = "priv-num" />
  106. <enum name = "priv-num-valid" />
  107. <enum name = "priv-num-plan" />
  108. <enum name = "priv-num-pres" />
  109. <enum name = "priv-subaddr" />
  110. <enum name = "priv-subaddr-valid" />
  111. <enum name = "priv-subaddr-type" />
  112. <enum name = "priv-subaddr-odd" />
  113. <enum name = "priv-tag" />
  114. <enum name = "ANI-all" />
  115. <enum name = "ANI-name" />
  116. <enum name = "ANI-name-valid" />
  117. <enum name = "ANI-name-charset" />
  118. <enum name = "ANI-name-pres" />
  119. <enum name = "ANI-num" />
  120. <enum name = "ANI-num-valid" />
  121. <enum name = "ANI-num-plan" />
  122. <enum name = "ANI-num-pres" />
  123. <enum name = "ANI-tag" />
  124. <enum name = "RDNIS" />
  125. <enum name = "DNID" />
  126. <enum name = "dnid-num-plan" />
  127. <enum name = "dnid-subaddr" />
  128. <enum name = "dnid-subaddr-valid" />
  129. <enum name = "dnid-subaddr-type" />
  130. <enum name = "dnid-subaddr-odd" />
  131. </enumlist>
  132. </parameter>
  133. <parameter name="CID">
  134. <para>Optional Caller*ID to parse instead of using the Caller*ID from the
  135. channel. This parameter is only optional when reading the Caller*ID.</para>
  136. </parameter>
  137. </syntax>
  138. <description>
  139. <para>Gets or sets Caller*ID data on the channel. Uses channel callerid by
  140. default or optional callerid, if specified.</para>
  141. <para>The allowable values for the <replaceable>name-charset</replaceable>
  142. field are the following:</para>
  143. <enumlist>
  144. <enum name = "unknown"><para>Unknown</para></enum>
  145. <enum name = "iso8859-1"><para>ISO8859-1</para></enum>
  146. <enum name = "withdrawn"><para>Withdrawn</para></enum>
  147. <enum name = "iso8859-2"><para>ISO8859-2</para></enum>
  148. <enum name = "iso8859-3"><para>ISO8859-3</para></enum>
  149. <enum name = "iso8859-4"><para>ISO8859-4</para></enum>
  150. <enum name = "iso8859-5"><para>ISO8859-5</para></enum>
  151. <enum name = "iso8859-7"><para>ISO8859-7</para></enum>
  152. <enum name = "bmp"><para>ISO10646 Bmp String</para></enum>
  153. <enum name = "utf8"><para>ISO10646 UTF-8 String</para></enum>
  154. </enumlist>
  155. </description>
  156. </function>
  157. <function name="CALLERPRES" language="en_US">
  158. <synopsis>
  159. Gets or sets Caller*ID presentation on the channel.
  160. </synopsis>
  161. <syntax />
  162. <description>
  163. <para>Gets or sets Caller*ID presentation on the channel.
  164. This function is deprecated in favor of CALLERID(num-pres)
  165. and CALLERID(name-pres).
  166. The following values are valid:</para>
  167. <enumlist>
  168. <enum name="allowed_not_screened">
  169. <para>Presentation Allowed, Not Screened.</para>
  170. </enum>
  171. <enum name="allowed_passed_screen">
  172. <para>Presentation Allowed, Passed Screen.</para>
  173. </enum>
  174. <enum name="allowed_failed_screen">
  175. <para>Presentation Allowed, Failed Screen.</para>
  176. </enum>
  177. <enum name="allowed">
  178. <para>Presentation Allowed, Network Number.</para>
  179. </enum>
  180. <enum name="prohib_not_screened">
  181. <para>Presentation Prohibited, Not Screened.</para>
  182. </enum>
  183. <enum name="prohib_passed_screen">
  184. <para>Presentation Prohibited, Passed Screen.</para>
  185. </enum>
  186. <enum name="prohib_failed_screen">
  187. <para>Presentation Prohibited, Failed Screen.</para>
  188. </enum>
  189. <enum name="prohib">
  190. <para>Presentation Prohibited, Network Number.</para>
  191. </enum>
  192. <enum name="unavailable">
  193. <para>Number Unavailable.</para>
  194. </enum>
  195. </enumlist>
  196. </description>
  197. </function>
  198. <function name="CONNECTEDLINE" language="en_US">
  199. <synopsis>
  200. Gets or sets Connected Line data on the channel.
  201. </synopsis>
  202. <syntax>
  203. <parameter name="datatype" required="true">
  204. <para>The allowable datatypes are:</para>
  205. <enumlist>
  206. <enum name = "all" />
  207. <enum name = "name" />
  208. <enum name = "name-valid" />
  209. <enum name = "name-charset" />
  210. <enum name = "name-pres" />
  211. <enum name = "num" />
  212. <enum name = "num-valid" />
  213. <enum name = "num-plan" />
  214. <enum name = "num-pres" />
  215. <enum name = "subaddr" />
  216. <enum name = "subaddr-valid" />
  217. <enum name = "subaddr-type" />
  218. <enum name = "subaddr-odd" />
  219. <enum name = "tag" />
  220. <enum name = "priv-all" />
  221. <enum name = "priv-name" />
  222. <enum name = "priv-name-valid" />
  223. <enum name = "priv-name-charset" />
  224. <enum name = "priv-name-pres" />
  225. <enum name = "priv-num" />
  226. <enum name = "priv-num-valid" />
  227. <enum name = "priv-num-plan" />
  228. <enum name = "priv-num-pres" />
  229. <enum name = "priv-subaddr" />
  230. <enum name = "priv-subaddr-valid" />
  231. <enum name = "priv-subaddr-type" />
  232. <enum name = "priv-subaddr-odd" />
  233. <enum name = "priv-tag" />
  234. </enumlist>
  235. </parameter>
  236. <parameter name="i">
  237. <para>If set, this will prevent the channel from sending out protocol
  238. messages because of the value being set</para>
  239. </parameter>
  240. </syntax>
  241. <description>
  242. <para>Gets or sets Connected Line data on the channel.</para>
  243. <para>The allowable values for the <replaceable>name-charset</replaceable>
  244. field are the following:</para>
  245. <enumlist>
  246. <enum name = "unknown"><para>Unknown</para></enum>
  247. <enum name = "iso8859-1"><para>ISO8859-1</para></enum>
  248. <enum name = "withdrawn"><para>Withdrawn</para></enum>
  249. <enum name = "iso8859-2"><para>ISO8859-2</para></enum>
  250. <enum name = "iso8859-3"><para>ISO8859-3</para></enum>
  251. <enum name = "iso8859-4"><para>ISO8859-4</para></enum>
  252. <enum name = "iso8859-5"><para>ISO8859-5</para></enum>
  253. <enum name = "iso8859-7"><para>ISO8859-7</para></enum>
  254. <enum name = "bmp"><para>ISO10646 Bmp String</para></enum>
  255. <enum name = "utf8"><para>ISO10646 UTF-8 String</para></enum>
  256. </enumlist>
  257. </description>
  258. </function>
  259. <function name="REDIRECTING" language="en_US">
  260. <synopsis>
  261. Gets or sets Redirecting data on the channel.
  262. </synopsis>
  263. <syntax>
  264. <parameter name="datatype" required="true">
  265. <para>The allowable datatypes are:</para>
  266. <enumlist>
  267. <enum name = "orig-all" />
  268. <enum name = "orig-name" />
  269. <enum name = "orig-name-valid" />
  270. <enum name = "orig-name-charset" />
  271. <enum name = "orig-name-pres" />
  272. <enum name = "orig-num" />
  273. <enum name = "orig-num-valid" />
  274. <enum name = "orig-num-plan" />
  275. <enum name = "orig-num-pres" />
  276. <enum name = "orig-subaddr" />
  277. <enum name = "orig-subaddr-valid" />
  278. <enum name = "orig-subaddr-type" />
  279. <enum name = "orig-subaddr-odd" />
  280. <enum name = "orig-tag" />
  281. <enum name = "orig-reason" />
  282. <enum name = "from-all" />
  283. <enum name = "from-name" />
  284. <enum name = "from-name-valid" />
  285. <enum name = "from-name-charset" />
  286. <enum name = "from-name-pres" />
  287. <enum name = "from-num" />
  288. <enum name = "from-num-valid" />
  289. <enum name = "from-num-plan" />
  290. <enum name = "from-num-pres" />
  291. <enum name = "from-subaddr" />
  292. <enum name = "from-subaddr-valid" />
  293. <enum name = "from-subaddr-type" />
  294. <enum name = "from-subaddr-odd" />
  295. <enum name = "from-tag" />
  296. <enum name = "to-all" />
  297. <enum name = "to-name" />
  298. <enum name = "to-name-valid" />
  299. <enum name = "to-name-charset" />
  300. <enum name = "to-name-pres" />
  301. <enum name = "to-num" />
  302. <enum name = "to-num-valid" />
  303. <enum name = "to-num-plan" />
  304. <enum name = "to-num-pres" />
  305. <enum name = "to-subaddr" />
  306. <enum name = "to-subaddr-valid" />
  307. <enum name = "to-subaddr-type" />
  308. <enum name = "to-subaddr-odd" />
  309. <enum name = "to-tag" />
  310. <enum name = "priv-orig-all" />
  311. <enum name = "priv-orig-name" />
  312. <enum name = "priv-orig-name-valid" />
  313. <enum name = "priv-orig-name-charset" />
  314. <enum name = "priv-orig-name-pres" />
  315. <enum name = "priv-orig-num" />
  316. <enum name = "priv-orig-num-valid" />
  317. <enum name = "priv-orig-num-plan" />
  318. <enum name = "priv-orig-num-pres" />
  319. <enum name = "priv-orig-subaddr" />
  320. <enum name = "priv-orig-subaddr-valid" />
  321. <enum name = "priv-orig-subaddr-type" />
  322. <enum name = "priv-orig-subaddr-odd" />
  323. <enum name = "priv-orig-tag" />
  324. <enum name = "priv-from-all" />
  325. <enum name = "priv-from-name" />
  326. <enum name = "priv-from-name-valid" />
  327. <enum name = "priv-from-name-charset" />
  328. <enum name = "priv-from-name-pres" />
  329. <enum name = "priv-from-num" />
  330. <enum name = "priv-from-num-valid" />
  331. <enum name = "priv-from-num-plan" />
  332. <enum name = "priv-from-num-pres" />
  333. <enum name = "priv-from-subaddr" />
  334. <enum name = "priv-from-subaddr-valid" />
  335. <enum name = "priv-from-subaddr-type" />
  336. <enum name = "priv-from-subaddr-odd" />
  337. <enum name = "priv-from-tag" />
  338. <enum name = "priv-to-all" />
  339. <enum name = "priv-to-name" />
  340. <enum name = "priv-to-name-valid" />
  341. <enum name = "priv-to-name-charset" />
  342. <enum name = "priv-to-name-pres" />
  343. <enum name = "priv-to-num" />
  344. <enum name = "priv-to-num-valid" />
  345. <enum name = "priv-to-num-plan" />
  346. <enum name = "priv-to-num-pres" />
  347. <enum name = "priv-to-subaddr" />
  348. <enum name = "priv-to-subaddr-valid" />
  349. <enum name = "priv-to-subaddr-type" />
  350. <enum name = "priv-to-subaddr-odd" />
  351. <enum name = "priv-to-tag" />
  352. <enum name = "reason" />
  353. <enum name = "count" />
  354. </enumlist>
  355. </parameter>
  356. <parameter name="i">
  357. <para>If set, this will prevent the channel from sending out protocol
  358. messages because of the value being set</para>
  359. </parameter>
  360. </syntax>
  361. <description>
  362. <para>Gets or sets Redirecting data on the channel.</para>
  363. <para>The allowable values for the <replaceable>reason</replaceable>
  364. and <replaceable>orig-reason</replaceable> fields are the following:</para>
  365. <enumlist>
  366. <enum name = "unknown"><para>Unknown</para></enum>
  367. <enum name = "cfb"><para>Call Forwarding Busy</para></enum>
  368. <enum name = "cfnr"><para>Call Forwarding No Reply</para></enum>
  369. <enum name = "unavailable"><para>Callee is Unavailable</para></enum>
  370. <enum name = "time_of_day"><para>Time of Day</para></enum>
  371. <enum name = "dnd"><para>Do Not Disturb</para></enum>
  372. <enum name = "deflection"><para>Call Deflection</para></enum>
  373. <enum name = "follow_me"><para>Follow Me</para></enum>
  374. <enum name = "out_of_order"><para>Called DTE Out-Of-Order</para></enum>
  375. <enum name = "away"><para>Callee is Away</para></enum>
  376. <enum name = "cf_dte"><para>Call Forwarding By The Called DTE</para></enum>
  377. <enum name = "cfu"><para>Call Forwarding Unconditional</para></enum>
  378. </enumlist>
  379. <para>The allowable values for the <replaceable>xxx-name-charset</replaceable>
  380. field are the following:</para>
  381. <enumlist>
  382. <enum name = "unknown"><para>Unknown</para></enum>
  383. <enum name = "iso8859-1"><para>ISO8859-1</para></enum>
  384. <enum name = "withdrawn"><para>Withdrawn</para></enum>
  385. <enum name = "iso8859-2"><para>ISO8859-2</para></enum>
  386. <enum name = "iso8859-3"><para>ISO8859-3</para></enum>
  387. <enum name = "iso8859-4"><para>ISO8859-4</para></enum>
  388. <enum name = "iso8859-5"><para>ISO8859-5</para></enum>
  389. <enum name = "iso8859-7"><para>ISO8859-7</para></enum>
  390. <enum name = "bmp"><para>ISO10646 Bmp String</para></enum>
  391. <enum name = "utf8"><para>ISO10646 UTF-8 String</para></enum>
  392. </enumlist>
  393. </description>
  394. </function>
  395. ***/
  396. enum ID_FIELD_STATUS {
  397. ID_FIELD_VALID,
  398. ID_FIELD_INVALID,
  399. ID_FIELD_UNKNOWN
  400. };
  401. AST_DEFINE_APP_ARGS_TYPE(ast_party_func_args,
  402. AST_APP_ARG(member); /*!< Member name */
  403. AST_APP_ARG(opts); /*!< Options token */
  404. AST_APP_ARG(other); /*!< Any remining unused arguments */
  405. );
  406. AST_DEFINE_APP_ARGS_TYPE(ast_party_members,
  407. AST_APP_ARG(subnames[10]); /*!< Option member subnames */
  408. );
  409. enum CONNECTED_LINE_OPT_FLAGS {
  410. CONNECTED_LINE_OPT_INHIBIT = (1 << 0),
  411. };
  412. enum CONNECTED_LINE_OPT_ARGS {
  413. CONNECTED_LINE_OPT_DUMMY, /*!< Delete this if CONNECTED_LINE ever gets an option with parameters. */
  414. /*! \note This entry _MUST_ be the last one in the enum */
  415. CONNECTED_LINE_OPT_ARG_ARRAY_SIZE
  416. };
  417. AST_APP_OPTIONS(connectedline_opts, BEGIN_OPTIONS
  418. AST_APP_OPTION('i', CONNECTED_LINE_OPT_INHIBIT),
  419. END_OPTIONS);
  420. enum REDIRECTING_OPT_FLAGS {
  421. REDIRECTING_OPT_INHIBIT = (1 << 0),
  422. };
  423. enum REDIRECTING_OPT_ARGS {
  424. REDIRECTING_OPT_DUMMY, /*!< Delete this if REDIRECTING ever gets an option with parameters. */
  425. /*! \note This entry _MUST_ be the last one in the enum */
  426. REDIRECTING_OPT_ARG_ARRAY_SIZE
  427. };
  428. AST_APP_OPTIONS(redirecting_opts, BEGIN_OPTIONS
  429. AST_APP_OPTION('i', REDIRECTING_OPT_INHIBIT),
  430. END_OPTIONS);
  431. /*!
  432. * \internal
  433. * \brief Read values from the party name struct.
  434. * \since 1.8
  435. *
  436. * \param buf Buffer to fill with read value.
  437. * \param len Length of the buffer.
  438. * \param argc Number of party member subnames.
  439. * \param argv Party member subnames given.
  440. * \param name Party name to get values from.
  441. *
  442. * \retval ID_FIELD_VALID on success.
  443. * \retval ID_FIELD_UNKNOWN on unknown field name.
  444. */
  445. static enum ID_FIELD_STATUS party_name_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_name *name)
  446. {
  447. enum ID_FIELD_STATUS status;
  448. status = ID_FIELD_VALID;
  449. if (argc == 0) {
  450. /* We want the name string */
  451. if (name->valid && name->str) {
  452. ast_copy_string(buf, name->str, len);
  453. }
  454. } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
  455. snprintf(buf, len, "%d", name->valid);
  456. } else if (argc == 1 && !strcasecmp("charset", argv[0])) {
  457. ast_copy_string(buf, ast_party_name_charset_str(name->char_set), len);
  458. } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
  459. /* Accept pres[entation] */
  460. ast_copy_string(buf, ast_named_caller_presentation(name->presentation), len);
  461. } else {
  462. status = ID_FIELD_UNKNOWN;
  463. }
  464. return status;
  465. }
  466. /*!
  467. * \internal
  468. * \brief Read values from the party number struct.
  469. * \since 1.8
  470. *
  471. * \param buf Buffer to fill with read value.
  472. * \param len Length of the buffer.
  473. * \param argc Number of party member subnames.
  474. * \param argv Party member subnames given.
  475. * \param number Party number to get values from.
  476. *
  477. * \retval ID_FIELD_VALID on success.
  478. * \retval ID_FIELD_UNKNOWN on unknown field name.
  479. */
  480. static enum ID_FIELD_STATUS party_number_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_number *number)
  481. {
  482. enum ID_FIELD_STATUS status;
  483. status = ID_FIELD_VALID;
  484. if (argc == 0) {
  485. /* We want the number string */
  486. if (number->valid && number->str) {
  487. ast_copy_string(buf, number->str, len);
  488. }
  489. } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
  490. snprintf(buf, len, "%d", number->valid);
  491. } else if (argc == 1 && !strcasecmp("plan", argv[0])) {
  492. snprintf(buf, len, "%d", number->plan);
  493. } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
  494. /* Accept pres[entation] */
  495. ast_copy_string(buf, ast_named_caller_presentation(number->presentation), len);
  496. } else {
  497. status = ID_FIELD_UNKNOWN;
  498. }
  499. return status;
  500. }
  501. /*!
  502. * \internal
  503. * \brief Read values from the party subaddress struct.
  504. * \since 1.8
  505. *
  506. * \param buf Buffer to fill with read value.
  507. * \param len Length of the buffer.
  508. * \param argc Number of party member subnames.
  509. * \param argv Party member subnames given.
  510. * \param subaddress Party subaddress to get values from.
  511. *
  512. * \retval ID_FIELD_VALID on success.
  513. * \retval ID_FIELD_UNKNOWN on unknown field name.
  514. */
  515. static enum ID_FIELD_STATUS party_subaddress_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_subaddress *subaddress)
  516. {
  517. enum ID_FIELD_STATUS status;
  518. status = ID_FIELD_VALID;
  519. if (argc == 0) {
  520. /* We want the subaddress string */
  521. if (subaddress->str) {
  522. ast_copy_string(buf, subaddress->str, len);
  523. }
  524. } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
  525. snprintf(buf, len, "%d", subaddress->valid);
  526. } else if (argc == 1 && !strcasecmp("type", argv[0])) {
  527. snprintf(buf, len, "%d", subaddress->type);
  528. } else if (argc == 1 && !strcasecmp("odd", argv[0])) {
  529. snprintf(buf, len, "%d", subaddress->odd_even_indicator);
  530. } else {
  531. status = ID_FIELD_UNKNOWN;
  532. }
  533. return status;
  534. }
  535. /*!
  536. * \internal
  537. * \brief Read values from the party id struct.
  538. * \since 1.8
  539. *
  540. * \param buf Buffer to fill with read value.
  541. * \param len Length of the buffer.
  542. * \param argc Number of party member subnames.
  543. * \param argv Party member subnames given.
  544. * \param id Party id to get values from.
  545. *
  546. * \retval ID_FIELD_VALID on success.
  547. * \retval ID_FIELD_UNKNOWN on unknown field name.
  548. */
  549. static enum ID_FIELD_STATUS party_id_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_id *id)
  550. {
  551. enum ID_FIELD_STATUS status;
  552. if (argc == 0) {
  553. /* Must have at least one subname. */
  554. return ID_FIELD_UNKNOWN;
  555. }
  556. status = ID_FIELD_VALID;
  557. if (argc == 1 && !strcasecmp("all", argv[0])) {
  558. snprintf(buf, len, "\"%s\" <%s>",
  559. S_COR(id->name.valid, id->name.str, ""),
  560. S_COR(id->number.valid, id->number.str, ""));
  561. } else if (!strcasecmp("name", argv[0])) {
  562. status = party_name_read(buf, len, argc - 1, argv + 1, &id->name);
  563. } else if (!strncasecmp("num", argv[0], 3)) {
  564. /* Accept num[ber] */
  565. status = party_number_read(buf, len, argc - 1, argv + 1, &id->number);
  566. } else if (!strncasecmp("subaddr", argv[0], 7)) {
  567. /* Accept subaddr[ess] */
  568. status = party_subaddress_read(buf, len, argc - 1, argv + 1, &id->subaddress);
  569. } else if (argc == 1 && !strcasecmp("tag", argv[0])) {
  570. if (id->tag) {
  571. ast_copy_string(buf, id->tag, len);
  572. }
  573. } else if (argc == 1 && !strcasecmp("ton", argv[0])) {
  574. /* ton is an alias for num-plan */
  575. snprintf(buf, len, "%d", id->number.plan);
  576. } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
  577. /*
  578. * Accept pres[entation]
  579. * This is the combined name/number presentation.
  580. */
  581. ast_copy_string(buf,
  582. ast_named_caller_presentation(ast_party_id_presentation(id)), len);
  583. } else {
  584. status = ID_FIELD_UNKNOWN;
  585. }
  586. return status;
  587. }
  588. /*!
  589. * \internal
  590. * \brief Write new values to the party name struct
  591. * \since 1.8
  592. *
  593. * \param name Party name struct to write values
  594. * \param argc Number of party member subnames.
  595. * \param argv Party member subnames given.
  596. * \param value Value to assign to the party name.
  597. *
  598. * \retval ID_FIELD_VALID on success.
  599. * \retval ID_FIELD_INVALID on error with field value.
  600. * \retval ID_FIELD_UNKNOWN on unknown field name.
  601. */
  602. static enum ID_FIELD_STATUS party_name_write(struct ast_party_name *name, int argc, char *argv[], const char *value)
  603. {
  604. char *val;
  605. enum ID_FIELD_STATUS status;
  606. status = ID_FIELD_VALID;
  607. if (argc == 0) {
  608. /* We are setting the name string */
  609. name->valid = 1;
  610. name->str = ast_strdup(value);
  611. ast_trim_blanks(name->str);
  612. } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
  613. name->valid = atoi(value) ? 1 : 0;
  614. } else if (argc == 1 && !strcasecmp("charset", argv[0])) {
  615. int char_set;
  616. val = ast_strdupa(value);
  617. ast_trim_blanks(val);
  618. if (('0' <= val[0]) && (val[0] <= '9')) {
  619. char_set = atoi(val);
  620. } else {
  621. char_set = ast_party_name_charset_parse(val);
  622. }
  623. if (char_set < 0) {
  624. ast_log(LOG_ERROR,
  625. "Unknown name char-set '%s', value unchanged\n", val);
  626. status = ID_FIELD_INVALID;
  627. } else {
  628. name->char_set = char_set;
  629. }
  630. } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
  631. int pres;
  632. /* Accept pres[entation] */
  633. val = ast_strdupa(value);
  634. ast_trim_blanks(val);
  635. if (('0' <= val[0]) && (val[0] <= '9')) {
  636. pres = atoi(val);
  637. } else {
  638. pres = ast_parse_caller_presentation(val);
  639. }
  640. if (pres < 0) {
  641. ast_log(LOG_ERROR,
  642. "Unknown name presentation '%s', value unchanged\n", val);
  643. status = ID_FIELD_INVALID;
  644. } else {
  645. name->presentation = pres;
  646. }
  647. } else {
  648. status = ID_FIELD_UNKNOWN;
  649. }
  650. return status;
  651. }
  652. /*!
  653. * \internal
  654. * \brief Write new values to the party number struct
  655. * \since 1.8
  656. *
  657. * \param number Party number struct to write values
  658. * \param argc Number of party member subnames.
  659. * \param argv Party member subnames given.
  660. * \param value Value to assign to the party number.
  661. *
  662. * \retval ID_FIELD_VALID on success.
  663. * \retval ID_FIELD_INVALID on error with field value.
  664. * \retval ID_FIELD_UNKNOWN on unknown field name.
  665. */
  666. static enum ID_FIELD_STATUS party_number_write(struct ast_party_number *number, int argc, char *argv[], const char *value)
  667. {
  668. char *val;
  669. enum ID_FIELD_STATUS status;
  670. status = ID_FIELD_VALID;
  671. if (argc == 0) {
  672. /* We are setting the number string */
  673. number->valid = 1;
  674. number->str = ast_strdup(value);
  675. ast_trim_blanks(number->str);
  676. } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
  677. number->valid = atoi(value) ? 1 : 0;
  678. } else if (argc == 1 && !strcasecmp("plan", argv[0])) {
  679. val = ast_strdupa(value);
  680. ast_trim_blanks(val);
  681. if (('0' <= val[0]) && (val[0] <= '9')) {
  682. number->plan = atoi(val);
  683. } else {
  684. ast_log(LOG_ERROR,
  685. "Unknown type-of-number/numbering-plan '%s', value unchanged\n", val);
  686. status = ID_FIELD_INVALID;
  687. }
  688. } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
  689. int pres;
  690. /* Accept pres[entation] */
  691. val = ast_strdupa(value);
  692. ast_trim_blanks(val);
  693. if (('0' <= val[0]) && (val[0] <= '9')) {
  694. pres = atoi(val);
  695. } else {
  696. pres = ast_parse_caller_presentation(val);
  697. }
  698. if (pres < 0) {
  699. ast_log(LOG_ERROR,
  700. "Unknown number presentation '%s', value unchanged\n", val);
  701. status = ID_FIELD_INVALID;
  702. } else {
  703. number->presentation = pres;
  704. }
  705. } else {
  706. status = ID_FIELD_UNKNOWN;
  707. }
  708. return status;
  709. }
  710. /*!
  711. * \internal
  712. * \brief Write new values to the party subaddress struct
  713. * \since 1.8
  714. *
  715. * \param subaddress Party subaddress struct to write values
  716. * \param argc Number of party member subnames.
  717. * \param argv Party member subnames given.
  718. * \param value Value to assign to the party subaddress.
  719. *
  720. * \retval ID_FIELD_VALID on success.
  721. * \retval ID_FIELD_INVALID on error with field value.
  722. * \retval ID_FIELD_UNKNOWN on unknown field name.
  723. */
  724. static enum ID_FIELD_STATUS party_subaddress_write(struct ast_party_subaddress *subaddress, int argc, char *argv[], const char *value)
  725. {
  726. enum ID_FIELD_STATUS status;
  727. status = ID_FIELD_VALID;
  728. if (argc == 0) {
  729. /* We are setting the subaddress string */
  730. subaddress->str = ast_strdup(value);
  731. ast_trim_blanks(subaddress->str);
  732. } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
  733. subaddress->valid = atoi(value) ? 1 : 0;
  734. } else if (argc == 1 && !strcasecmp("type", argv[0])) {
  735. subaddress->type = atoi(value) ? 2 : 0;
  736. } else if (argc == 1 && !strcasecmp("odd", argv[0])) {
  737. subaddress->odd_even_indicator = atoi(value) ? 1 : 0;
  738. } else {
  739. status = ID_FIELD_UNKNOWN;
  740. }
  741. return status;
  742. }
  743. /*!
  744. * \internal
  745. * \brief Write new values to the party id struct
  746. * \since 1.8
  747. *
  748. * \param id Party ID struct to write values
  749. * \param argc Number of party member subnames.
  750. * \param argv Party member subnames given.
  751. * \param value Value to assign to the party id.
  752. *
  753. * \retval ID_FIELD_VALID on success.
  754. * \retval ID_FIELD_INVALID on error with field value.
  755. * \retval ID_FIELD_UNKNOWN on unknown field name.
  756. */
  757. static enum ID_FIELD_STATUS party_id_write(struct ast_party_id *id, int argc, char *argv[], const char *value)
  758. {
  759. char *val;
  760. enum ID_FIELD_STATUS status;
  761. if (argc == 0) {
  762. /* Must have at least one subname. */
  763. return ID_FIELD_UNKNOWN;
  764. }
  765. status = ID_FIELD_VALID;
  766. if (argc == 1 && !strcasecmp("all", argv[0])) {
  767. char name[256];
  768. char num[256];
  769. ast_callerid_split(value, name, sizeof(name), num, sizeof(num));
  770. id->name.valid = 1;
  771. id->name.str = ast_strdup(name);
  772. if (!id->name.str) {
  773. return ID_FIELD_INVALID;
  774. }
  775. id->number.valid = 1;
  776. id->number.str = ast_strdup(num);
  777. if (!id->number.str) {
  778. return ID_FIELD_INVALID;
  779. }
  780. } else if (!strcasecmp("name", argv[0])) {
  781. status = party_name_write(&id->name, argc - 1, argv + 1, value);
  782. } else if (!strncasecmp("num", argv[0], 3)) {
  783. /* Accept num[ber] */
  784. status = party_number_write(&id->number, argc - 1, argv + 1, value);
  785. } else if (!strncasecmp("subaddr", argv[0], 7)) {
  786. /* Accept subaddr[ess] */
  787. status = party_subaddress_write(&id->subaddress, argc - 1, argv + 1, value);
  788. } else if (argc == 1 && !strcasecmp("tag", argv[0])) {
  789. id->tag = ast_strdup(value);
  790. ast_trim_blanks(id->tag);
  791. } else if (argc == 1 && !strcasecmp("ton", argv[0])) {
  792. /* ton is an alias for num-plan */
  793. argv[0] = "plan";
  794. status = party_number_write(&id->number, argc, argv, value);
  795. } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
  796. int pres;
  797. /*
  798. * Accept pres[entation]
  799. * This is the combined name/number presentation.
  800. */
  801. val = ast_strdupa(value);
  802. ast_trim_blanks(val);
  803. if (('0' <= val[0]) && (val[0] <= '9')) {
  804. pres = atoi(val);
  805. } else {
  806. pres = ast_parse_caller_presentation(val);
  807. }
  808. if (pres < 0) {
  809. ast_log(LOG_ERROR,
  810. "Unknown combined presentation '%s', value unchanged\n", val);
  811. status = ID_FIELD_INVALID;
  812. } else {
  813. id->name.presentation = pres;
  814. id->number.presentation = pres;
  815. }
  816. } else {
  817. status = ID_FIELD_UNKNOWN;
  818. }
  819. return status;
  820. }
  821. /*! TRUE if we have already notified about CALLERPRES being deprecated. */
  822. static int callerpres_deprecate_notify;
  823. /*!
  824. * \internal
  825. * \brief Read values from the caller-id presentation information struct.
  826. *
  827. * \param chan Asterisk channel to read
  828. * \param cmd Not used
  829. * \param data Caller-id presentation function datatype string
  830. * \param buf Buffer to fill with read value.
  831. * \param len Length of the buffer
  832. *
  833. * \retval 0 on success.
  834. * \retval -1 on error.
  835. */
  836. static int callerpres_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
  837. {
  838. if (!chan) {
  839. ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
  840. return -1;
  841. }
  842. if (!callerpres_deprecate_notify) {
  843. callerpres_deprecate_notify = 1;
  844. ast_log(LOG_WARNING, "CALLERPRES is deprecated."
  845. " Use CALLERID(name-pres) or CALLERID(num-pres) instead.\n");
  846. }
  847. ast_copy_string(buf,
  848. ast_named_caller_presentation(ast_party_id_presentation(&ast_channel_caller(chan)->id)), len);
  849. return 0;
  850. }
  851. /*!
  852. * \internal
  853. * \brief Write new values to the caller-id presentation information struct.
  854. *
  855. * \param chan Asterisk channel to update
  856. * \param cmd Not used
  857. * \param data Caller-id presentation function datatype string
  858. * \param value Value to assign to the caller-id presentation information struct.
  859. *
  860. * \retval 0 on success.
  861. * \retval -1 on error.
  862. */
  863. static int callerpres_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
  864. {
  865. int pres;
  866. if (!chan) {
  867. ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
  868. return -1;
  869. }
  870. if (!callerpres_deprecate_notify) {
  871. callerpres_deprecate_notify = 1;
  872. ast_log(LOG_WARNING, "CALLERPRES is deprecated."
  873. " Use CALLERID(name-pres) or CALLERID(num-pres) instead.\n");
  874. }
  875. pres = ast_parse_caller_presentation(value);
  876. if (pres < 0) {
  877. ast_log(LOG_WARNING, "'%s' is not a valid presentation (see 'show function CALLERPRES')\n", value);
  878. } else {
  879. ast_channel_caller(chan)->id.name.presentation = pres;
  880. ast_channel_caller(chan)->id.number.presentation = pres;
  881. }
  882. return 0;
  883. }
  884. /*!
  885. * \internal
  886. * \brief Read values from the caller-id information struct.
  887. *
  888. * \param chan Asterisk channel to read
  889. * \param cmd Not used
  890. * \param data Caller-id function datatype string
  891. * \param buf Buffer to fill with read value.
  892. * \param len Length of the buffer
  893. *
  894. * \retval 0 on success.
  895. * \retval -1 on error.
  896. */
  897. static int callerid_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
  898. {
  899. char *parms;
  900. struct ast_party_members member;
  901. AST_DECLARE_APP_ARGS(args,
  902. AST_APP_ARG(member); /*!< Member name */
  903. AST_APP_ARG(cid); /*!< Optional caller id to parse instead of from the channel. */
  904. );
  905. /* Ensure that the buffer is empty */
  906. *buf = 0;
  907. if (!chan) {
  908. return -1;
  909. }
  910. parms = ast_strdupa(data);
  911. AST_STANDARD_APP_ARGS(args, parms);
  912. if (args.argc == 0) {
  913. /* Must have at least one argument. */
  914. return -1;
  915. }
  916. AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
  917. if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
  918. /* Too few or too many subnames */
  919. return -1;
  920. }
  921. if (args.argc == 2) {
  922. char name[80];
  923. char num[80];
  924. ast_callerid_split(args.cid, name, sizeof(name), num, sizeof(num));
  925. if (member.argc == 1 && !strcasecmp("all", member.argv[0])) {
  926. snprintf(buf, len, "\"%s\" <%s>", name, num);
  927. } else if (member.argc == 1 && !strcasecmp("name", member.argv[0])) {
  928. ast_copy_string(buf, name, len);
  929. } else if (member.argc == 1 && !strncasecmp("num", member.argv[0], 3)) {
  930. /* Accept num[ber] */
  931. ast_copy_string(buf, num, len);
  932. } else {
  933. ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
  934. }
  935. } else {
  936. enum ID_FIELD_STATUS status;
  937. ast_channel_lock(chan);
  938. if (member.argc == 1 && !strcasecmp("rdnis", member.argv[0])) {
  939. if (ast_channel_redirecting(chan)->from.number.valid
  940. && ast_channel_redirecting(chan)->from.number.str) {
  941. ast_copy_string(buf, ast_channel_redirecting(chan)->from.number.str, len);
  942. }
  943. } else if (!strcasecmp("dnid", member.argv[0])) {
  944. if (member.argc == 1) {
  945. /* Setup as if user had given dnid-num instead. */
  946. member.argc = 2;
  947. member.argv[1] = "num";
  948. }
  949. if (!strncasecmp("num", member.argv[1], 3)) {
  950. /*
  951. * Accept num[ber]
  952. * dnid-num...
  953. */
  954. if (member.argc == 2) {
  955. /* dnid-num */
  956. if (ast_channel_dialed(chan)->number.str) {
  957. ast_copy_string(buf, ast_channel_dialed(chan)->number.str, len);
  958. }
  959. } else if (member.argc == 3 && !strcasecmp("plan", member.argv[2])) {
  960. /* dnid-num-plan */
  961. snprintf(buf, len, "%d", ast_channel_dialed(chan)->number.plan);
  962. } else {
  963. ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
  964. }
  965. } else if (!strncasecmp("subaddr", member.argv[1], 7)) {
  966. /*
  967. * Accept subaddr[ess]
  968. * dnid-subaddr...
  969. */
  970. status = party_subaddress_read(buf, len, member.argc - 2, member.argv + 2,
  971. &ast_channel_dialed(chan)->subaddress);
  972. switch (status) {
  973. case ID_FIELD_VALID:
  974. case ID_FIELD_INVALID:
  975. break;
  976. default:
  977. ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
  978. break;
  979. }
  980. } else {
  981. ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
  982. }
  983. } else if (member.argc == 1 && !strcasecmp("ani2", member.argv[0])) {
  984. snprintf(buf, len, "%d", ast_channel_caller(chan)->ani2);
  985. } else if (!strcasecmp("ani", member.argv[0])) {
  986. if (member.argc == 1) {
  987. /* Setup as if user had given ani-num instead. */
  988. member.argc = 2;
  989. member.argv[1] = "num";
  990. }
  991. status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
  992. &ast_channel_caller(chan)->ani);
  993. switch (status) {
  994. case ID_FIELD_VALID:
  995. case ID_FIELD_INVALID:
  996. break;
  997. default:
  998. ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
  999. break;
  1000. }
  1001. } else if (!strcasecmp("priv", member.argv[0])) {
  1002. status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
  1003. &ast_channel_caller(chan)->priv);
  1004. switch (status) {
  1005. case ID_FIELD_VALID:
  1006. case ID_FIELD_INVALID:
  1007. break;
  1008. default:
  1009. ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
  1010. break;
  1011. }
  1012. } else {
  1013. status = party_id_read(buf, len, member.argc, member.argv, &ast_channel_caller(chan)->id);
  1014. switch (status) {
  1015. case ID_FIELD_VALID:
  1016. case ID_FIELD_INVALID:
  1017. break;
  1018. default:
  1019. ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
  1020. break;
  1021. }
  1022. }
  1023. ast_channel_unlock(chan);
  1024. }
  1025. return 0;
  1026. }
  1027. /*!
  1028. * \internal
  1029. * \brief Write new values to the caller-id information struct.
  1030. *
  1031. * \param chan Asterisk channel to update
  1032. * \param cmd Not used
  1033. * \param data Caller-id function datatype string
  1034. * \param value Value to assign to the caller-id information struct.
  1035. *
  1036. * \retval 0 on success.
  1037. * \retval -1 on error.
  1038. */
  1039. static int callerid_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
  1040. {
  1041. struct ast_party_caller caller;
  1042. struct ast_party_dialed dialed;
  1043. enum ID_FIELD_STATUS status;
  1044. char *val;
  1045. char *parms;
  1046. struct ast_party_func_args args;
  1047. struct ast_party_members member;
  1048. if (!value || !chan) {
  1049. return -1;
  1050. }
  1051. parms = ast_strdupa(data);
  1052. AST_STANDARD_APP_ARGS(args, parms);
  1053. if (args.argc == 0) {
  1054. /* Must have at least one argument. */
  1055. return -1;
  1056. }
  1057. AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
  1058. if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
  1059. /* Too few or too many subnames */
  1060. return -1;
  1061. }
  1062. value = ast_skip_blanks(value);
  1063. ast_channel_lock(chan);
  1064. if (member.argc == 1 && !strcasecmp("rdnis", member.argv[0])) {
  1065. ast_channel_redirecting(chan)->from.number.valid = 1;
  1066. ast_free(ast_channel_redirecting(chan)->from.number.str);
  1067. ast_channel_redirecting(chan)->from.number.str = ast_strdup(value);
  1068. } else if (!strcasecmp("dnid", member.argv[0])) {
  1069. ast_party_dialed_set_init(&dialed, ast_channel_dialed(chan));
  1070. if (member.argc == 1) {
  1071. /* Setup as if user had given dnid-num instead. */
  1072. member.argc = 2;
  1073. member.argv[1] = "num";
  1074. }
  1075. if (!strncasecmp("num", member.argv[1], 3)) {
  1076. /*
  1077. * Accept num[ber]
  1078. * dnid-num...
  1079. */
  1080. if (member.argc == 2) {
  1081. /* dnid-num */
  1082. dialed.number.str = ast_strdup(value);
  1083. ast_trim_blanks(dialed.number.str);
  1084. ast_party_dialed_set(ast_channel_dialed(chan), &dialed);
  1085. } else if (member.argc == 3 && !strcasecmp("plan", member.argv[2])) {
  1086. /* dnid-num-plan */
  1087. val = ast_strdupa(value);
  1088. ast_trim_blanks(val);
  1089. if (('0' <= val[0]) && (val[0] <= '9')) {
  1090. ast_channel_dialed(chan)->number.plan = atoi(val);
  1091. } else {
  1092. ast_log(LOG_ERROR,
  1093. "Unknown type-of-number/numbering-plan '%s', value unchanged\n", val);
  1094. }
  1095. } else {
  1096. ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
  1097. }
  1098. } else if (!strncasecmp("subaddr", member.argv[1], 7)) {
  1099. /*
  1100. * Accept subaddr[ess]
  1101. * dnid-subaddr...
  1102. */
  1103. status = party_subaddress_write(&dialed.subaddress, member.argc - 2,
  1104. member.argv + 2, value);
  1105. switch (status) {
  1106. case ID_FIELD_VALID:
  1107. ast_party_dialed_set(ast_channel_dialed(chan), &dialed);
  1108. break;
  1109. case ID_FIELD_INVALID:
  1110. break;
  1111. default:
  1112. ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
  1113. break;
  1114. }
  1115. } else {
  1116. ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
  1117. }
  1118. ast_party_dialed_free(&dialed);
  1119. } else if (member.argc == 1 && !strcasecmp("ani2", member.argv[0])) {
  1120. val = ast_strdupa(value);
  1121. ast_trim_blanks(val);
  1122. if (('0' <= val[0]) && (val[0] <= '9')) {
  1123. ast_channel_caller(chan)->ani2 = atoi(val);
  1124. } else {
  1125. ast_log(LOG_ERROR, "Unknown callerid ani2 '%s', value unchanged\n", val);
  1126. }
  1127. } else if (!strcasecmp("ani", member.argv[0])) {
  1128. ast_party_caller_set_init(&caller, ast_channel_caller(chan));
  1129. if (member.argc == 1) {
  1130. /* Setup as if user had given ani-num instead. */
  1131. member.argc = 2;
  1132. member.argv[1] = "num";
  1133. }
  1134. status = party_id_write(&caller.ani, member.argc - 1, member.argv + 1, value);
  1135. switch (status) {
  1136. case ID_FIELD_VALID:
  1137. ast_party_caller_set(ast_channel_caller(chan), &caller, NULL);
  1138. break;
  1139. case ID_FIELD_INVALID:
  1140. break;
  1141. default:
  1142. ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
  1143. break;
  1144. }
  1145. ast_party_caller_free(&caller);
  1146. } else if (!strcasecmp("priv", member.argv[0])) {
  1147. ast_party_caller_set_init(&caller, ast_channel_caller(chan));
  1148. status = party_id_write(&caller.priv, member.argc - 1, member.argv + 1, value);
  1149. switch (status) {
  1150. case ID_FIELD_VALID:
  1151. ast_party_caller_set(ast_channel_caller(chan), &caller, NULL);
  1152. break;
  1153. case ID_FIELD_INVALID:
  1154. break;
  1155. default:
  1156. ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
  1157. break;
  1158. }
  1159. ast_party_caller_free(&caller);
  1160. } else {
  1161. ast_party_caller_set_init(&caller, ast_channel_caller(chan));
  1162. status = party_id_write(&caller.id, member.argc, member.argv, value);
  1163. switch (status) {
  1164. case ID_FIELD_VALID:
  1165. ast_channel_set_caller_event(chan, &caller, NULL);
  1166. break;
  1167. case ID_FIELD_INVALID:
  1168. break;
  1169. default:
  1170. ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
  1171. break;
  1172. }
  1173. ast_party_caller_free(&caller);
  1174. }
  1175. ast_channel_unlock(chan);
  1176. return 0;
  1177. }
  1178. /*!
  1179. * \internal
  1180. * \brief Read values from the connected line information struct.
  1181. *
  1182. * \param chan Asterisk channel to read
  1183. * \param cmd Not used
  1184. * \param data Connected line function datatype string
  1185. * \param buf Buffer to fill with read value.
  1186. * \param len Length of the buffer
  1187. *
  1188. * \retval 0 on success.
  1189. * \retval -1 on error.
  1190. */
  1191. static int connectedline_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
  1192. {
  1193. struct ast_party_members member;
  1194. char *read_what;
  1195. enum ID_FIELD_STATUS status;
  1196. /* Ensure that the buffer is empty */
  1197. *buf = 0;
  1198. if (!chan) {
  1199. return -1;
  1200. }
  1201. read_what = ast_strdupa(data);
  1202. AST_NONSTANDARD_APP_ARGS(member, read_what, '-');
  1203. if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
  1204. /* Too few or too many subnames */
  1205. return -1;
  1206. }
  1207. ast_channel_lock(chan);
  1208. if (member.argc == 1 && !strcasecmp("source", member.argv[0])) {
  1209. ast_copy_string(buf, ast_connected_line_source_name(ast_channel_connected(chan)->source), len);
  1210. } else if (!strcasecmp("priv", member.argv[0])) {
  1211. status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
  1212. &ast_channel_connected(chan)->priv);
  1213. switch (status) {
  1214. case ID_FIELD_VALID:
  1215. case ID_FIELD_INVALID:
  1216. break;
  1217. default:
  1218. ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
  1219. break;
  1220. }
  1221. } else {
  1222. status = party_id_read(buf, len, member.argc, member.argv, &ast_channel_connected(chan)->id);
  1223. switch (status) {
  1224. case ID_FIELD_VALID:
  1225. case ID_FIELD_INVALID:
  1226. break;
  1227. default:
  1228. ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
  1229. break;
  1230. }
  1231. }
  1232. ast_channel_unlock(chan);
  1233. return 0;
  1234. }
  1235. /*!
  1236. * \internal
  1237. * \brief Write new values to the connected line information struct.
  1238. *
  1239. * \param chan Asterisk channel to update
  1240. * \param cmd Not used
  1241. * \param data Connected line function datatype string
  1242. * \param value Value to assign to the connected line information struct.
  1243. *
  1244. * \retval 0 on success.
  1245. * \retval -1 on error.
  1246. */
  1247. static int connectedline_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
  1248. {
  1249. struct ast_party_connected_line connected;
  1250. char *val;
  1251. char *parms;
  1252. void (*set_it)(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update);
  1253. struct ast_party_func_args args;
  1254. struct ast_party_members member;
  1255. struct ast_flags opts;
  1256. char *opt_args[CONNECTED_LINE_OPT_ARG_ARRAY_SIZE];
  1257. enum ID_FIELD_STATUS status;
  1258. if (!value || !chan) {
  1259. return -1;
  1260. }
  1261. parms = ast_strdupa(data);
  1262. AST_STANDARD_APP_ARGS(args, parms);
  1263. if (args.argc == 0) {
  1264. /* Must have at least one argument. */
  1265. return -1;
  1266. }
  1267. AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
  1268. if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
  1269. /* Too few or too many subnames */
  1270. return -1;
  1271. }
  1272. if (ast_app_parse_options(connectedline_opts, &opts, opt_args, args.opts)) {
  1273. /* General invalid option syntax. */
  1274. return -1;
  1275. }
  1276. /* Determine if the update indication inhibit option is present */
  1277. if (ast_test_flag(&opts, CONNECTED_LINE_OPT_INHIBIT)) {
  1278. set_it = ast_channel_set_connected_line;
  1279. } else {
  1280. set_it = ast_channel_update_connected_line;
  1281. }
  1282. ast_channel_lock(chan);
  1283. ast_party_connected_line_set_init(&connected, ast_channel_connected(chan));
  1284. ast_channel_unlock(chan);
  1285. value = ast_skip_blanks(value);
  1286. if (member.argc == 1 && !strcasecmp("source", member.argv[0])) {
  1287. int source;
  1288. val = ast_strdupa(value);
  1289. ast_trim_blanks(val);
  1290. if (('0' <= val[0]) && (val[0] <= '9')) {
  1291. source = atoi(val);
  1292. } else {
  1293. source = ast_connected_line_source_parse(val);
  1294. }
  1295. if (source < 0) {
  1296. ast_log(LOG_ERROR, "Unknown connectedline source '%s', value unchanged\n", val);
  1297. } else {
  1298. connected.source = source;
  1299. set_it(chan, &connected, NULL);
  1300. }
  1301. } else if (!strcasecmp("priv", member.argv[0])) {
  1302. status = party_id_write(&connected.priv, member.argc - 1, member.argv + 1, value);
  1303. switch (status) {
  1304. case ID_FIELD_VALID:
  1305. set_it(chan, &connected, NULL);
  1306. break;
  1307. case ID_FIELD_INVALID:
  1308. break;
  1309. default:
  1310. ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
  1311. break;
  1312. }
  1313. ast_party_connected_line_free(&connected);
  1314. } else {
  1315. status = party_id_write(&connected.id, member.argc, member.argv, value);
  1316. switch (status) {
  1317. case ID_FIELD_VALID:
  1318. set_it(chan, &connected, NULL);
  1319. break;
  1320. case ID_FIELD_INVALID:
  1321. break;
  1322. default:
  1323. ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
  1324. break;
  1325. }
  1326. ast_party_connected_line_free(&connected);
  1327. }
  1328. return 0;
  1329. }
  1330. /*!
  1331. * \internal
  1332. * \brief Read values from the redirecting information struct.
  1333. *
  1334. * \param chan Asterisk channel to read
  1335. * \param cmd Not used
  1336. * \param data Redirecting function datatype string
  1337. * \param buf Buffer to fill with read value.
  1338. * \param len Length of the buffer
  1339. *
  1340. * \retval 0 on success.
  1341. * \retval -1 on error.
  1342. */
  1343. static int redirecting_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
  1344. {
  1345. struct ast_party_members member;
  1346. char *read_what;
  1347. const struct ast_party_redirecting *ast_redirecting;
  1348. enum ID_FIELD_STATUS status;
  1349. /* Ensure that the buffer is empty */
  1350. *buf = 0;
  1351. if (!chan) {
  1352. return -1;
  1353. }
  1354. read_what = ast_strdupa(data);
  1355. AST_NONSTANDARD_APP_ARGS(member, read_what, '-');
  1356. if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
  1357. /* Too few or too many subnames */
  1358. return -1;
  1359. }
  1360. ast_channel_lock(chan);
  1361. ast_redirecting = ast_channel_redirecting(chan);
  1362. if (!strcasecmp("orig", member.argv[0])) {
  1363. if (member.argc == 2 && !strcasecmp("reason", member.argv[1])) {
  1364. ast_copy_string(buf,
  1365. ast_redirecting_reason_name(&ast_redirecting->orig_reason), len);
  1366. } else {
  1367. status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
  1368. &ast_redirecting->orig);
  1369. switch (status) {
  1370. case ID_FIELD_VALID:
  1371. case ID_FIELD_INVALID:
  1372. break;
  1373. default:
  1374. ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
  1375. break;
  1376. }
  1377. }
  1378. } else if (!strcasecmp("from", member.argv[0])) {
  1379. status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
  1380. &ast_redirecting->from);
  1381. switch (status) {
  1382. case ID_FIELD_VALID:
  1383. case ID_FIELD_INVALID:
  1384. break;
  1385. default:
  1386. ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
  1387. break;
  1388. }
  1389. } else if (!strcasecmp("to", member.argv[0])) {
  1390. status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
  1391. &ast_redirecting->to);
  1392. switch (status) {
  1393. case ID_FIELD_VALID:
  1394. case ID_FIELD_INVALID:
  1395. break;
  1396. default:
  1397. ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
  1398. break;
  1399. }
  1400. } else if (member.argc == 1 && !strncasecmp("pres", member.argv[0], 4)) {
  1401. /*
  1402. * Accept pres[entation]
  1403. * This is the combined from name/number presentation.
  1404. */
  1405. ast_copy_string(buf,
  1406. ast_named_caller_presentation(
  1407. ast_party_id_presentation(&ast_redirecting->from)), len);
  1408. } else if (member.argc == 1 && !strcasecmp("reason", member.argv[0])) {
  1409. ast_copy_string(buf, ast_redirecting_reason_name(&ast_redirecting->reason), len);
  1410. } else if (member.argc == 1 && !strcasecmp("count", member.argv[0])) {
  1411. snprintf(buf, len, "%d", ast_redirecting->count);
  1412. } else if (1 < member.argc && !strcasecmp("priv", member.argv[0])) {
  1413. if (!strcasecmp("orig", member.argv[1])) {
  1414. status = party_id_read(buf, len, member.argc - 2, member.argv + 2,
  1415. &ast_redirecting->priv_orig);
  1416. switch (status) {
  1417. case ID_FIELD_VALID:
  1418. case ID_FIELD_INVALID:
  1419. break;
  1420. default:
  1421. ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
  1422. break;
  1423. }
  1424. } else if (!strcasecmp("from", member.argv[1])) {
  1425. status = party_id_read(buf, len, member.argc - 2, member.argv + 2,
  1426. &ast_redirecting->priv_from);
  1427. switch (status) {
  1428. case ID_FIELD_VALID:
  1429. case ID_FIELD_INVALID:
  1430. break;
  1431. default:
  1432. ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
  1433. break;
  1434. }
  1435. } else if (!strcasecmp("to", member.argv[1])) {
  1436. status = party_id_read(buf, len, member.argc - 2, member.argv + 2,
  1437. &ast_redirecting->priv_to);
  1438. switch (status) {
  1439. case ID_FIELD_VALID:
  1440. case ID_FIELD_INVALID:
  1441. break;
  1442. default:
  1443. ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
  1444. break;
  1445. }
  1446. } else {
  1447. ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
  1448. }
  1449. } else {
  1450. ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
  1451. }
  1452. ast_channel_unlock(chan);
  1453. return 0;
  1454. }
  1455. /*!
  1456. * \internal
  1457. * \brief Write new values to the redirecting information struct.
  1458. *
  1459. * \param chan Asterisk channel to update
  1460. * \param cmd Not used
  1461. * \param data Redirecting function datatype string
  1462. * \param value Value to assign to the redirecting information struct.
  1463. *
  1464. * \retval 0 on success.
  1465. * \retval -1 on error.
  1466. */
  1467. static int redirecting_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
  1468. {
  1469. struct ast_party_redirecting redirecting;
  1470. enum ID_FIELD_STATUS status;
  1471. char *val;
  1472. char *parms;
  1473. void (*set_it)(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update);
  1474. struct ast_party_func_args args;
  1475. struct ast_party_members member;
  1476. struct ast_flags opts;
  1477. char *opt_args[REDIRECTING_OPT_ARG_ARRAY_SIZE];
  1478. if (!value || !chan) {
  1479. return -1;
  1480. }
  1481. parms = ast_strdupa(data);
  1482. AST_STANDARD_APP_ARGS(args, parms);
  1483. if (args.argc == 0) {
  1484. /* Must have at least one argument. */
  1485. return -1;
  1486. }
  1487. AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
  1488. if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
  1489. /* Too few or too many subnames */
  1490. return -1;
  1491. }
  1492. if (ast_app_parse_options(redirecting_opts, &opts, opt_args, args.opts)) {
  1493. /* General invalid option syntax. */
  1494. return -1;
  1495. }
  1496. /* Determine if the update indication inhibit option is present */
  1497. if (ast_test_flag(&opts, REDIRECTING_OPT_INHIBIT)) {
  1498. set_it = ast_channel_set_redirecting;
  1499. } else {
  1500. set_it = ast_channel_update_redirecting;
  1501. }
  1502. ast_channel_lock(chan);
  1503. ast_party_redirecting_set_init(&redirecting, ast_channel_redirecting(chan));
  1504. ast_channel_unlock(chan);
  1505. value = ast_skip_blanks(value);
  1506. if (!strcasecmp("orig", member.argv[0])) {
  1507. if (member.argc == 2 && !strcasecmp("reason", member.argv[1])) {
  1508. int reason;
  1509. val = ast_strdupa(value);
  1510. ast_trim_blanks(val);
  1511. if (('0' <= val[0]) && (val[0] <= '9')) {
  1512. reason = atoi(val);
  1513. } else {
  1514. reason = ast_redirecting_reason_parse(val);
  1515. }
  1516. if (reason < 0) {
  1517. /* The argument passed into the function does not correspond to a pre-defined
  1518. * reason, so we can just set the reason string to what was given and set the
  1519. * code to be unknown
  1520. */
  1521. redirecting.orig_reason.code = AST_REDIRECTING_REASON_UNKNOWN;
  1522. redirecting.orig_reason.str = val;
  1523. set_it(chan, &redirecting, NULL);
  1524. } else {
  1525. redirecting.orig_reason.code = reason;
  1526. redirecting.orig_reason.str = "";
  1527. set_it(chan, &redirecting, NULL);
  1528. }
  1529. } else {
  1530. status = party_id_write(&redirecting.orig, member.argc - 1, member.argv + 1,
  1531. value);
  1532. switch (status) {
  1533. case ID_FIELD_VALID:
  1534. set_it(chan, &redirecting, NULL);
  1535. break;
  1536. case ID_FIELD_INVALID:
  1537. break;
  1538. default:
  1539. ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
  1540. break;
  1541. }
  1542. ast_party_redirecting_free(&redirecting);
  1543. }
  1544. } else if (!strcasecmp("from", member.argv[0])) {
  1545. status = party_id_write(&redirecting.from, member.argc - 1, member.argv + 1,
  1546. value);
  1547. switch (status) {
  1548. case ID_FIELD_VALID:
  1549. set_it(chan, &redirecting, NULL);
  1550. break;
  1551. case ID_FIELD_INVALID:
  1552. break;
  1553. default:
  1554. ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
  1555. break;
  1556. }
  1557. ast_party_redirecting_free(&redirecting);
  1558. } else if (!strcasecmp("to", member.argv[0])) {
  1559. status = party_id_write(&redirecting.to, member.argc - 1, member.argv + 1, value);
  1560. switch (status) {
  1561. case ID_FIELD_VALID:
  1562. set_it(chan, &redirecting, NULL);
  1563. break;
  1564. case ID_FIELD_INVALID:
  1565. break;
  1566. default:
  1567. ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
  1568. break;
  1569. }
  1570. ast_party_redirecting_free(&redirecting);
  1571. } else if (member.argc == 1 && !strncasecmp("pres", member.argv[0], 4)) {
  1572. int pres;
  1573. val = ast_strdupa(value);
  1574. ast_trim_blanks(val);
  1575. if (('0' <= val[0]) && (val[0] <= '9')) {
  1576. pres = atoi(val);
  1577. } else {
  1578. pres = ast_parse_caller_presentation(val);
  1579. }
  1580. if (pres < 0) {
  1581. ast_log(LOG_ERROR,
  1582. "Unknown redirecting combined presentation '%s', value unchanged\n", val);
  1583. } else {
  1584. redirecting.from.name.presentation = pres;
  1585. redirecting.from.number.presentation = pres;
  1586. redirecting.to.name.presentation = pres;
  1587. redirecting.to.number.presentation = pres;
  1588. set_it(chan, &redirecting, NULL);
  1589. }
  1590. } else if (member.argc == 1 && !strcasecmp("reason", member.argv[0])) {
  1591. int reason;
  1592. val = ast_strdupa(value);
  1593. ast_trim_blanks(val);
  1594. if (('0' <= val[0]) && (val[0] <= '9')) {
  1595. reason = atoi(val);
  1596. } else {
  1597. reason = ast_redirecting_reason_parse(val);
  1598. }
  1599. if (reason < 0) {
  1600. /* The argument passed into the function does not correspond to a pre-defined
  1601. * reason, so we can just set the reason string to what was given and set the
  1602. * code to be unknown
  1603. */
  1604. redirecting.reason.code = AST_REDIRECTING_REASON_UNKNOWN;
  1605. redirecting.reason.str = val;
  1606. set_it(chan, &redirecting, NULL);
  1607. } else {
  1608. redirecting.reason.code = reason;
  1609. redirecting.reason.str = "";
  1610. set_it(chan, &redirecting, NULL);
  1611. }
  1612. } else if (member.argc == 1 && !strcasecmp("count", member.argv[0])) {
  1613. val = ast_strdupa(value);
  1614. ast_trim_blanks(val);
  1615. if (('0' <= val[0]) && (val[0] <= '9')) {
  1616. redirecting.count = atoi(val);
  1617. set_it(chan, &redirecting, NULL);
  1618. } else {
  1619. ast_log(LOG_ERROR, "Unknown redirecting count '%s', value unchanged\n", val);
  1620. }
  1621. } else if (1 < member.argc && !strcasecmp("priv", member.argv[0])) {
  1622. if (!strcasecmp("orig", member.argv[1])) {
  1623. status = party_id_write(&redirecting.priv_orig, member.argc - 2, member.argv + 2,
  1624. value);
  1625. switch (status) {
  1626. case ID_FIELD_VALID:
  1627. set_it(chan, &redirecting, NULL);
  1628. break;
  1629. case ID_FIELD_INVALID:
  1630. break;
  1631. default:
  1632. ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
  1633. break;
  1634. }
  1635. ast_party_redirecting_free(&redirecting);
  1636. } else if (!strcasecmp("from", member.argv[1])) {
  1637. status = party_id_write(&redirecting.priv_from, member.argc - 2, member.argv + 2,
  1638. value);
  1639. switch (status) {
  1640. case ID_FIELD_VALID:
  1641. set_it(chan, &redirecting, NULL);
  1642. break;
  1643. case ID_FIELD_INVALID:
  1644. break;
  1645. default:
  1646. ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
  1647. break;
  1648. }
  1649. ast_party_redirecting_free(&redirecting);
  1650. } else if (!strcasecmp("to", member.argv[1])) {
  1651. status = party_id_write(&redirecting.priv_to, member.argc - 2, member.argv + 2, value);
  1652. switch (status) {
  1653. case ID_FIELD_VALID:
  1654. set_it(chan, &redirecting, NULL);
  1655. break;
  1656. case ID_FIELD_INVALID:
  1657. break;
  1658. default:
  1659. ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
  1660. break;
  1661. }
  1662. ast_party_redirecting_free(&redirecting);
  1663. } else {
  1664. ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
  1665. }
  1666. } else {
  1667. ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
  1668. }
  1669. return 0;
  1670. }
  1671. static struct ast_custom_function callerid_function = {
  1672. .name = "CALLERID",
  1673. .read = callerid_read,
  1674. .read_max = 256,
  1675. .write = callerid_write,
  1676. };
  1677. static struct ast_custom_function callerpres_function = {
  1678. .name = "CALLERPRES",
  1679. .read = callerpres_read,
  1680. .read_max = 50,
  1681. .write = callerpres_write,
  1682. };
  1683. static struct ast_custom_function connectedline_function = {
  1684. .name = "CONNECTEDLINE",
  1685. .read = connectedline_read,
  1686. .write = connectedline_write,
  1687. };
  1688. static struct ast_custom_function redirecting_function = {
  1689. .name = "REDIRECTING",
  1690. .read = redirecting_read,
  1691. .write = redirecting_write,
  1692. };
  1693. /*!
  1694. * \internal
  1695. * \brief Unload the function module
  1696. *
  1697. * \retval 0 on success.
  1698. * \retval -1 on error.
  1699. */
  1700. static int unload_module(void)
  1701. {
  1702. int res;
  1703. res = ast_custom_function_unregister(&callerpres_function);
  1704. res |= ast_custom_function_unregister(&callerid_function);
  1705. res |= ast_custom_function_unregister(&connectedline_function);
  1706. res |= ast_custom_function_unregister(&redirecting_function);
  1707. return res;
  1708. }
  1709. /*!
  1710. * \internal
  1711. * \brief Load and initialize the function module.
  1712. *
  1713. * \retval AST_MODULE_LOAD_SUCCESS on success.
  1714. * \retval AST_MODULE_LOAD_DECLINE on error.
  1715. */
  1716. static int load_module(void)
  1717. {
  1718. int res;
  1719. res = ast_custom_function_register(&callerpres_function);
  1720. res |= ast_custom_function_register(&callerid_function);
  1721. res |= ast_custom_function_register(&connectedline_function);
  1722. res |= ast_custom_function_register(&redirecting_function);
  1723. return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
  1724. }
  1725. /* Do not wrap the following line. */
  1726. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Party ID related dialplan functions (Caller-ID, Connected-line, Redirecting)");