Merge "astobj2: Create function to copy weak proxied objects from container."
[asterisk/asterisk.git] / apps / app_privacy.c
old mode 100755 (executable)
new mode 100644 (file)
index babb6c6..86aec01
 /*
- * Asterisk -- A telephony toolkit for Linux.
+ * Asterisk -- An open source telephony toolkit.
  *
- * Block all calls without Caller*ID, require phone # to be entered
- * 
- * Copyright (C) 1999, Mark Spencer
+ * Copyright (C) 1999 - 2005, Digium, Inc.
  *
- * Mark Spencer <markster@linux-support.net>
+ * Mark Spencer <markster@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
  *
  * This program is free software, distributed under the terms of
- * the GNU General Public License
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
  */
 
-#include <asterisk/lock.h>
-#include <asterisk/file.h>
-#include <asterisk/logger.h>
-#include <asterisk/options.h>
-#include <asterisk/channel.h>
-#include <asterisk/pbx.h>
-#include <asterisk/module.h>
-#include <asterisk/translate.h>
-#include <asterisk/image.h>
-#include <asterisk/callerid.h>
-#include <string.h>
-#include <stdlib.h>
-#include <pthread.h>
-
-static char *tdesc = "Require phone number to be entered, if no CallerID sent";
-
-static char *app = "PrivacyManager";
-
-static char *synopsis = "Require phone number to be entered, if no CallerID sent";
+/*! \file
+ *
+ * \brief Block all calls without Caller*ID, require phone # to be entered
+ *
+ * \author Mark Spencer <markster@digium.com>
+ *
+ * \ingroup applications
+ */
 
-static char *descrip =
-  "  PrivacyManager: If no Caller*ID is sent, PrivacyManager answers the\n"
-  "channel and asks the caller to enter their 10 digit phone number.\n"
-  "The caller is given 3 attempts.  If after 3 attempts, they do no enter\n"
-  "their 10 digit phone number, and if there exists a priority n + 101,\n"
-  "where 'n' is the priority of the current instance, then  the\n"
-  "channel  will  be  setup  to continue at that priority level.\n"
-  "Otherwise, it returns 0.  Does nothing if Caller*ID was received on the\n"
-  "channel.\n";
+/*** MODULEINFO
+       <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+#include "asterisk/lock.h"
+#include "asterisk/file.h"
+#include "asterisk/utils.h"
+#include "asterisk/channel.h"
+#include "asterisk/pbx.h"
+#include "asterisk/module.h"
+#include "asterisk/translate.h"
+#include "asterisk/callerid.h"
+#include "asterisk/app.h"
+#include "asterisk/config.h"
+
+/*** DOCUMENTATION
+       <application name="PrivacyManager" language="en_US">
+               <synopsis>
+                       Require phone number to be entered, if no CallerID sent
+               </synopsis>
+               <syntax>
+                       <parameter name="maxretries">
+                               <para>Total tries caller is allowed to input a callerid. Defaults to <literal>3</literal>.</para>
+                       </parameter>
+                       <parameter name="minlength">
+                               <para>Minimum allowable digits in the input callerid number. Defaults to <literal>10</literal>.</para>
+                       </parameter>
+                       <parameter name="options">
+                               <para>Position reserved for options.</para>
+                       </parameter>
+                       <parameter name="context">
+                               <para>Context to check the given callerid against patterns.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>If no Caller*ID is sent, PrivacyManager answers the channel and asks
+                       the caller to enter their phone number. The caller is given
+                       <replaceable>maxretries</replaceable> attempts to do so. The application does
+                       <emphasis>nothing</emphasis> if Caller*ID was received on the channel.</para>
+                       <para>The application sets the following channel variable upon completion:</para>
+                       <variablelist>
+                               <variable name="PRIVACYMGRSTATUS">
+                                       <para>The status of the privacy manager's attempt to collect a phone number from the user.</para>
+                                       <value name="SUCCESS"/>
+                                       <value name="FAILED"/>
+                               </variable>
+                       </variablelist>
+               </description>
+               <see-also>
+                       <ref type="application">Zapateller</ref>
+               </see-also>
+       </application>
+ ***/
 
-STANDARD_LOCAL_USER;
 
-LOCAL_USER_DECL;
+static char *app = "PrivacyManager";
 
-static int
-privacy_exec (struct ast_channel *chan, void *data)
+static int privacy_exec(struct ast_channel *chan, const char *data)
 {
        int res=0;
        int retries;
-       char phone[10];
-       char new_cid[144];
-       struct localuser *u;
-
-       LOCAL_USER_ADD (u);
-       if (chan->callerid)
-       {
-               if (option_verbose > 2)
-                       ast_verbose (VERBOSE_PREFIX_3 "CallerID Present: Skipping\n");
-       }
-       else
-       {
+       int maxretries = 3;
+       int minlength = 10;
+       int x = 0;
+       char phone[30];
+       char *parse = NULL;
+       AST_DECLARE_APP_ARGS(args,
+               AST_APP_ARG(maxretries);
+               AST_APP_ARG(minlength);
+               AST_APP_ARG(options);
+               AST_APP_ARG(checkcontext);
+       );
+
+       if (ast_channel_caller(chan)->id.number.valid
+               && !ast_strlen_zero(ast_channel_caller(chan)->id.number.str)) {
+               ast_verb(3, "CallerID number present: Skipping\n");
+       } else {
                /*Answer the channel if it is not already*/
-               if (chan->_state != AST_STATE_UP) {
-                       res = ast_answer(chan);
-                       if (res) {
-                               LOCAL_USER_REMOVE(u);
+               if (ast_channel_state(chan) != AST_STATE_UP) {
+                       if ((res = ast_answer(chan))) {
                                return -1;
                        }
                }
-               /*Just a quick sleep*/
-               sleep(1);
-               
-               /*Play unidentified call*/
-               res = ast_streamfile(chan, "privacy-unident", chan->language);
-               if (!res)
+
+               parse = ast_strdupa(data);
+
+               AST_STANDARD_APP_ARGS(args, parse);
+
+               if (!ast_strlen_zero(args.maxretries)) {
+                       if (sscanf(args.maxretries, "%30d", &x) == 1 && x > 0) {
+                               maxretries = x;
+                       } else {
+                               ast_log(LOG_WARNING, "Invalid max retries argument: '%s'\n", args.maxretries);
+                       }
+               }
+               if (!ast_strlen_zero(args.minlength)) {
+                       if (sscanf(args.minlength, "%30d", &x) == 1 && x > 0) {
+                               minlength = x;
+                       } else {
+                               ast_log(LOG_WARNING, "Invalid min length argument: '%s'\n", args.minlength);
+                       }
+               }
+
+               /* Play unidentified call */
+               res = ast_safe_sleep(chan, 1000);
+               if (!res) {
+                       res = ast_streamfile(chan, "privacy-unident", ast_channel_language(chan));
+               }
+               if (!res) {
                        res = ast_waitstream(chan, "");
+               }
 
-               /*Ask for 10 digit number, give 3 attempts*/
-               for (retries = 0; retries < 3; retries++) {
-                       res = ast_app_getdata(chan, "privacy-prompt", phone, sizeof(phone), 0);
-                       if (res < 0)
-                               break;
+               /* Ask for 10 digit number, give 3 attempts */
+               for (retries = 0; retries < maxretries; retries++) {
+                       if (!res) {
+                               res = ast_streamfile(chan, "privacy-prompt", ast_channel_language(chan));
+                       }
+                       if (!res) {
+                               res = ast_waitstream(chan, "");
+                       }
 
-                       /*Make sure we get 10 digits*/
-                       if (strlen(phone) == 10) 
+                       if (!res) {
+                               res = ast_readstring(chan, phone, sizeof(phone) - 1, /* digit timeout ms */ 3200, /* first digit timeout */ 5000, "#");
+                       }
+
+                       if (res < 0) {
                                break;
-                       else {
-                               res = ast_streamfile(chan, "privacy-incorrect", chan->language);
-                               if (!res)
+                       }
+
+                       /* Make sure we get at least digits */
+                       if (strlen(phone) >= minlength ) {
+                               /* if we have a checkcontext argument, do pattern matching */
+                               if (!ast_strlen_zero(args.checkcontext)) {
+                                       if (!ast_exists_extension(NULL, args.checkcontext, phone, 1, NULL)) {
+                                               res = ast_streamfile(chan, "privacy-incorrect", ast_channel_language(chan));
+                                               if (!res) {
+                                                       res = ast_waitstream(chan, "");
+                                               }
+                                       } else {
+                                               break;
+                                       }
+                               } else {
+                                       break;
+                               }
+                       } else {
+                               res = ast_streamfile(chan, "privacy-incorrect", ast_channel_language(chan));
+                               if (!res) {
                                        res = ast_waitstream(chan, "");
+                               }
                        }
                }
-               
-               /*Got a number, play sounds and send them on their way*/
-               if ((retries < 3) && !res) {
-                       res = ast_streamfile(chan, "privacy-thankyou", chan->language);
-                       if (!res)
+
+               /* Got a number, play sounds and send them on their way */
+               if ((retries < maxretries) && res >= 0) {
+                       res = ast_streamfile(chan, "privacy-thankyou", ast_channel_language(chan));
+                       if (!res) {
                                res = ast_waitstream(chan, "");
-                       snprintf (new_cid, sizeof (new_cid), "\"%s\" <%s>", "Privacy Manager", phone);
-                       ast_set_callerid (chan, new_cid, 0);
-                       if (option_verbose > 2)
-                               ast_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID to %s\n",new_cid);
+                       }
+
+                       /*
+                        * This is a caller entered number that is going to be used locally.
+                        * Therefore, the given number presentation is allowed and should
+                        * be passed out to other channels.  This is the point of the
+                        * privacy application.
+                        */
+                       ast_channel_caller(chan)->id.name.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+                       ast_channel_caller(chan)->id.number.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+                       ast_channel_caller(chan)->id.number.plan = 0;/* Unknown */
+
+                       ast_set_callerid(chan, phone, "Privacy Manager", NULL);
+
+                       ast_verb(3, "Changed Caller*ID number to '%s'\n", phone);
+
+                       pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "SUCCESS");
                } else {
-                       /*Send the call to n+101 priority, where n is the current priority*/
-                       if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
-                               chan->priority+=100;
+                       pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "FAILED");
                }
        }
 
-  LOCAL_USER_REMOVE (u);
-  return 0;
-}
-
-int
-unload_module (void)
-{
-  STANDARD_HANGUP_LOCALUSERS;
-  return ast_unregister_application (app);
-}
-
-int
-load_module (void)
-{
-  return ast_register_application (app, privacy_exec, synopsis,
-                                  descrip);
+       return 0;
 }
 
-char *
-description (void)
+static int unload_module(void)
 {
-  return tdesc;
+       return ast_unregister_application(app);
 }
 
-int
-usecount (void)
+static int load_module(void)
 {
-  int res;
-  STANDARD_USECOUNT (res);
-  return res;
+       return ast_register_application_xml(app, privacy_exec);
 }
 
-char *
-key ()
-{
-  return ASTERISK_GPL_KEY;
-}
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Require phone number to be entered, if no CallerID sent");