func_callerid.c 46 KB

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