00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <sys/types.h>
00026 #include <string.h>
00027 #include <unistd.h>
00028 #include <stdlib.h>
00029 #include <stdio.h>
00030 #include <ctype.h>
00031 #include <errno.h>
00032 #include <time.h>
00033 #include <sys/time.h>
00034
00035 #include "asterisk.h"
00036
00037 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 62737 $")
00038
00039 #include "asterisk/lock.h"
00040 #include "asterisk/cli.h"
00041 #include "asterisk/pbx.h"
00042 #include "asterisk/channel.h"
00043 #include "asterisk/options.h"
00044 #include "asterisk/logger.h"
00045 #include "asterisk/file.h"
00046 #include "asterisk/callerid.h"
00047 #include "asterisk/cdr.h"
00048 #include "asterisk/config.h"
00049 #include "asterisk/term.h"
00050 #include "asterisk/manager.h"
00051 #include "asterisk/ast_expr.h"
00052 #include "asterisk/linkedlists.h"
00053 #include "asterisk/say.h"
00054 #include "asterisk/utils.h"
00055 #include "asterisk/causes.h"
00056 #include "asterisk/musiconhold.h"
00057 #include "asterisk/app.h"
00058 #include "asterisk/devicestate.h"
00059 #include "asterisk/compat.h"
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 #ifdef LOW_MEMORY
00072 #define EXT_DATA_SIZE 256
00073 #else
00074 #define EXT_DATA_SIZE 8192
00075 #endif
00076
00077 #define SWITCH_DATA_LENGTH 256
00078
00079 #define VAR_BUF_SIZE 4096
00080
00081 #define VAR_NORMAL 1
00082 #define VAR_SOFTTRAN 2
00083 #define VAR_HARDTRAN 3
00084
00085 #define BACKGROUND_SKIP (1 << 0)
00086 #define BACKGROUND_NOANSWER (1 << 1)
00087 #define BACKGROUND_MATCHEXTEN (1 << 2)
00088 #define BACKGROUND_PLAYBACK (1 << 3)
00089
00090 AST_APP_OPTIONS(background_opts, {
00091 AST_APP_OPTION('s', BACKGROUND_SKIP),
00092 AST_APP_OPTION('n', BACKGROUND_NOANSWER),
00093 AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN),
00094 AST_APP_OPTION('p', BACKGROUND_PLAYBACK),
00095 });
00096
00097 #define WAITEXTEN_MOH (1 << 0)
00098
00099 AST_APP_OPTIONS(waitexten_opts, {
00100 AST_APP_OPTION_ARG('m', WAITEXTEN_MOH, 1),
00101 });
00102
00103 struct ast_context;
00104
00105
00106
00107
00108
00109
00110 struct ast_exten {
00111 char *exten;
00112 int matchcid;
00113 char *cidmatch;
00114 int priority;
00115 char *label;
00116 struct ast_context *parent;
00117 char *app;
00118 void *data;
00119 void (*datad)(void *);
00120 struct ast_exten *peer;
00121 const char *registrar;
00122 struct ast_exten *next;
00123 char stuff[0];
00124 };
00125
00126
00127 struct ast_include {
00128 char *name;
00129 char *rname;
00130 const char *registrar;
00131 int hastime;
00132 struct ast_timing timing;
00133 struct ast_include *next;
00134 char stuff[0];
00135 };
00136
00137
00138 struct ast_sw {
00139 char *name;
00140 const char *registrar;
00141 char *data;
00142 int eval;
00143 struct ast_sw *next;
00144 char *tmpdata;
00145 char stuff[0];
00146 };
00147
00148
00149 struct ast_ignorepat {
00150 const char *registrar;
00151 struct ast_ignorepat *next;
00152 char pattern[0];
00153 };
00154
00155
00156 struct ast_context {
00157 ast_mutex_t lock;
00158 struct ast_exten *root;
00159 struct ast_context *next;
00160 struct ast_include *includes;
00161 struct ast_ignorepat *ignorepats;
00162 const char *registrar;
00163 struct ast_sw *alts;
00164 char name[0];
00165 };
00166
00167
00168
00169 struct ast_app {
00170 int (*execute)(struct ast_channel *chan, void *data);
00171 const char *synopsis;
00172 const char *description;
00173 struct ast_app *next;
00174 char name[0];
00175 };
00176
00177
00178 struct ast_state_cb {
00179 int id;
00180 void *data;
00181 ast_state_cb_type callback;
00182 struct ast_state_cb *next;
00183 };
00184
00185
00186
00187
00188
00189 struct ast_hint {
00190 struct ast_exten *exten;
00191 int laststate;
00192 struct ast_state_cb *callbacks;
00193 struct ast_hint *next;
00194 };
00195
00196 int ast_pbx_outgoing_cdr_failed(void);
00197
00198 static int pbx_builtin_answer(struct ast_channel *, void *);
00199 static int pbx_builtin_goto(struct ast_channel *, void *);
00200 static int pbx_builtin_hangup(struct ast_channel *, void *);
00201 static int pbx_builtin_background(struct ast_channel *, void *);
00202 static int pbx_builtin_dtimeout(struct ast_channel *, void *);
00203 static int pbx_builtin_rtimeout(struct ast_channel *, void *);
00204 static int pbx_builtin_atimeout(struct ast_channel *, void *);
00205 static int pbx_builtin_wait(struct ast_channel *, void *);
00206 static int pbx_builtin_waitexten(struct ast_channel *, void *);
00207 static int pbx_builtin_setlanguage(struct ast_channel *, void *);
00208 static int pbx_builtin_resetcdr(struct ast_channel *, void *);
00209 static int pbx_builtin_setaccount(struct ast_channel *, void *);
00210 static int pbx_builtin_setamaflags(struct ast_channel *, void *);
00211 static int pbx_builtin_ringing(struct ast_channel *, void *);
00212 static int pbx_builtin_progress(struct ast_channel *, void *);
00213 static int pbx_builtin_congestion(struct ast_channel *, void *);
00214 static int pbx_builtin_busy(struct ast_channel *, void *);
00215 static int pbx_builtin_setglobalvar(struct ast_channel *, void *);
00216 static int pbx_builtin_noop(struct ast_channel *, void *);
00217 static int pbx_builtin_gotoif(struct ast_channel *, void *);
00218 static int pbx_builtin_gotoiftime(struct ast_channel *, void *);
00219 static int pbx_builtin_execiftime(struct ast_channel *, void *);
00220 static int pbx_builtin_saynumber(struct ast_channel *, void *);
00221 static int pbx_builtin_saydigits(struct ast_channel *, void *);
00222 static int pbx_builtin_saycharacters(struct ast_channel *, void *);
00223 static int pbx_builtin_sayphonetic(struct ast_channel *, void *);
00224 static int pbx_builtin_setvar_old(struct ast_channel *, void *);
00225 int pbx_builtin_setvar(struct ast_channel *, void *);
00226 static int pbx_builtin_importvar(struct ast_channel *, void *);
00227
00228 AST_MUTEX_DEFINE_STATIC(globalslock);
00229 static struct varshead globals;
00230
00231 static int autofallthrough = 0;
00232
00233 AST_MUTEX_DEFINE_STATIC(maxcalllock);
00234 static int countcalls = 0;
00235
00236 AST_MUTEX_DEFINE_STATIC(acflock);
00237 static struct ast_custom_function *acf_root = NULL;
00238
00239
00240 static struct pbx_builtin {
00241 char name[AST_MAX_APP];
00242 int (*execute)(struct ast_channel *chan, void *data);
00243 char *synopsis;
00244 char *description;
00245 } builtins[] =
00246 {
00247
00248
00249
00250 { "AbsoluteTimeout", pbx_builtin_atimeout,
00251 "Set absolute maximum time of call",
00252 " AbsoluteTimeout(seconds): This application will set the absolute maximum\n"
00253 "amount of time permitted for a call. A setting of 0 disables the timeout.\n"
00254 " AbsoluteTimeout has been deprecated in favor of Set(TIMEOUT(absolute)=timeout)\n"
00255 },
00256
00257 { "Answer", pbx_builtin_answer,
00258 "Answer a channel if ringing",
00259 " Answer([delay]): If the call has not been answered, this application will\n"
00260 "answer it. Otherwise, it has no effect on the call. If a delay is specified,\n"
00261 "Asterisk will wait this number of milliseconds before returning to\n"
00262 "the dialplan after answering the call.\n"
00263 },
00264
00265 { "BackGround", pbx_builtin_background,
00266 "Play a file while awaiting extension",
00267 " Background(filename1[&filename2...][|options[|langoverride][|context]]):\n"
00268 "This application will play the given list of files while waiting for an\n"
00269 "extension to be dialed by the calling channel. To continue waiting for digits\n"
00270 "after this application has finished playing files, the WaitExten application\n"
00271 "should be used. The 'langoverride' option explicity specifies which language\n"
00272 "to attempt to use for the requested sound files. If a 'context' is specified,\n"
00273 "this is the dialplan context that this application will use when exiting to a\n"
00274 "dialed extension."
00275 " If one of the requested sound files does not exist, call processing will be\n"
00276 "terminated.\n"
00277 " Options:\n"
00278 " s - causes the playback of the message to be skipped\n"
00279 " if the channel is not in the 'up' state (i.e. it\n"
00280 " hasn't been answered yet.) If this happens, the\n"
00281 " application will return immediately.\n"
00282 " n - don't answer the channel before playing the files\n"
00283 " m - only break if a digit hit matches a one digit\n"
00284 " extension in the destination context\n"
00285 },
00286
00287 { "Busy", pbx_builtin_busy,
00288 "Indicate the Busy condition",
00289 " Busy([timeout]): This application will indicate the busy condition to\n"
00290 "the calling channel. If the optional timeout is specified, the calling channel\n"
00291 "will be hung up after the specified number of seconds. Otherwise, this\n"
00292 "application will wait until the calling channel hangs up.\n"
00293 },
00294
00295 { "Congestion", pbx_builtin_congestion,
00296 "Indicate the Congestion condition",
00297 " Congestion([timeout]): This application will indicate the congenstion\n"
00298 "condition to the calling channel. If the optional timeout is specified, the\n"
00299 "calling channel will be hung up after the specified number of seconds.\n"
00300 "Otherwise, this application will wait until the calling channel hangs up.\n"
00301 },
00302
00303 { "DigitTimeout", pbx_builtin_dtimeout,
00304 "Set maximum timeout between digits",
00305 " DigitTimeout(seconds): Set the maximum amount of time permitted between\n"
00306 "digits when the user is typing in an extension. When this timeout expires,\n"
00307 "after the user has started to type in an extension, the extension will be\n"
00308 "considered complete, and will be interpreted. Note that if an extension\n"
00309 "typed in is valid, it will not have to timeout to be tested, so typically\n"
00310 "at the expiry of this timeout, the extension will be considered invalid\n"
00311 "(and thus control would be passed to the 'i' extension, or if it doesn't\n"
00312 "exist the call would be terminated). The default timeout is 5 seconds.\n"
00313 " DigitTimeout has been deprecated in favor of Set(TIMEOUT(digit)=timeout)\n"
00314 },
00315
00316 { "Goto", pbx_builtin_goto,
00317 "Jump to a particular priority, extension, or context",
00318 " Goto([[context|]extension|]priority): This application will set the current\n"
00319 "context, extension, and priority in the channel structure. After it completes, the\n"
00320 "pbx engine will continue dialplan execution at the specified location.\n"
00321 "If no specific extension, or extension and context, are specified, then this\n"
00322 "application will just set the specified priority of the current extension.\n"
00323 " At least a priority is required as an argument, or the goto will return a -1,\n"
00324 "and the channel and call will be terminated.\n"
00325 " If the location that is put into the channel information is bogus, and asterisk cannot\n"
00326 "find that location in the dialplan,\n"
00327 "then the execution engine will try to find and execute the code in the 'i' (invalid)\n"
00328 "extension in the current context. If that does not exist, it will try to execute the\n"
00329 "'h' extension. If either or neither the 'h' or 'i' extensions have been defined, the\n"
00330 "channel is hung up, and the execution of instructions on the channel is terminated.\n"
00331 "What this means is that, for example, you specify a context that does not exist, then\n"
00332 "it will not be possible to find the 'h' or 'i' extensions, and the call will terminate!\n"
00333 },
00334
00335 { "GotoIf", pbx_builtin_gotoif,
00336 "Conditional goto",
00337 " GotoIf(condition?[labeliftrue]:[labeliffalse]): This application will set the current\n"
00338 "context, extension, and priority in the channel structure based on the evaluation of\n"
00339 "the given condition. After this application completes, the\n"
00340 "pbx engine will continue dialplan execution at the specified location in the dialplan.\n"
00341 "The channel will continue at\n"
00342 "'labeliftrue' if the condition is true, or 'labeliffalse' if the condition is\n"
00343 "false. The labels are specified with the same syntax as used within the Goto\n"
00344 "application. If the label chosen by the condition is omitted, no jump is\n"
00345 "performed, and the execution passes to the next instruction.\n"
00346 "If the target location is bogus, and does not exist, the execution engine will try \n"
00347 "to find and execute the code in the 'i' (invalid)\n"
00348 "extension in the current context. If that does not exist, it will try to execute the\n"
00349 "'h' extension. If either or neither the 'h' or 'i' extensions have been defined, the\n"
00350 "channel is hung up, and the execution of instructions on the channel is terminated.\n"
00351 "Remember that this command can set the current context, and if the context specified\n"
00352 "does not exist, then it will not be able to find any 'h' or 'i' extensions there,\n"
00353 "and the channel and call will both be terminated!\n"
00354 },
00355
00356 { "GotoIfTime", pbx_builtin_gotoiftime,
00357 "Conditional Goto based on the current time",
00358 " GotoIfTime(<times>|<weekdays>|<mdays>|<months>?[[context|]exten|]priority):\n"
00359 "This application will set the context, extension, and priority in the channel structure\n"
00360 "if the current time matches the given time specification. Otherwise, nothing is done.\n"
00361 "Further information on the time specification can be found in examples\n"
00362 "illustrating how to do time-based context includes in the dialplan.\n"
00363 "If the target jump location is bogus, Asterisk will respond as outlined in Goto.\n"
00364 },
00365
00366 { "ExecIfTime", pbx_builtin_execiftime,
00367 "Conditional application execution based on the current time",
00368 " ExecIfTime(<times>|<weekdays>|<mdays>|<months>?appname[|appargs]):\n"
00369 "This application will execute the specified dialplan application, with optional\n"
00370 "arguments, if the current time matches the given time specification. Further\n"
00371 "information on the time speicification can be found in examples illustrating\n"
00372 "how to do time-based context includes in the dialplan.\n"
00373 },
00374
00375 { "Hangup", pbx_builtin_hangup,
00376 "Hang up the calling channel",
00377 " Hangup(): This application will hang up the calling channel.\n"
00378 },
00379
00380 { "NoOp", pbx_builtin_noop,
00381 "Do Nothing",
00382 " NoOp(): This applicatiion does nothing. However, it is useful for debugging\n"
00383 "purposes. Any text that is provided as arguments to this application can be\n"
00384 "viewed at the Asterisk CLI. This method can be used to see the evaluations of\n"
00385 "variables or functions without having any effect."
00386 },
00387
00388 { "Progress", pbx_builtin_progress,
00389 "Indicate progress",
00390 " Progress(): This application will request that in-band progress information\n"
00391 "be provided to the calling channel.\n"
00392 },
00393
00394 { "ResetCDR", pbx_builtin_resetcdr,
00395 "Resets the Call Data Record",
00396 " ResetCDR([options]): This application causes the Call Data Record to be\n"
00397 "reset.\n"
00398 " Options:\n"
00399 " w -- Store the current CDR record before resetting it.\n"
00400 " a -- Store any stacked records.\n"
00401 " v -- Save CDR variables.\n"
00402 },
00403
00404 { "ResponseTimeout", pbx_builtin_rtimeout,
00405 "Set maximum timeout awaiting response",
00406 " ResponseTimeout(seconds): This will set the maximum amount of time permitted\n"
00407 "to wait for an extension to dialed (see the WaitExten application), before the\n"
00408 "timeout occurs. If this timeout is reached, dialplan execution will continue at\n"
00409 "the 't' extension, if it exists.\n"
00410 " ResponseTimeout has been deprecated in favor of Set(TIMEOUT(response)=timeout)\n"
00411 },
00412
00413 { "Ringing", pbx_builtin_ringing,
00414 "Indicate ringing tone",
00415 " Ringing(): This application will request that the channel indicate a ringing\n"
00416 "tone to the user.\n"
00417 },
00418
00419 { "SayNumber", pbx_builtin_saynumber,
00420 "Say Number",
00421 " SayNumber(digits[,gender]): This application will play the sounds that\n"
00422 "correspond to the given number. Optionally, a gender may be specified.\n"
00423 "This will use the language that is currently set for the channel. See the\n"
00424 "LANGUAGE function for more information on setting the language for the channel.\n"
00425 },
00426
00427 { "SayDigits", pbx_builtin_saydigits,
00428 "Say Digits",
00429 " SayDigits(digits): This application will play the sounds that correspond\n"
00430 "to the digits of the given number. This will use the language that is currently\n"
00431 "set for the channel. See the LANGUAGE function for more information on setting\n"
00432 "the language for the channel.\n"
00433 },
00434
00435 { "SayAlpha", pbx_builtin_saycharacters,
00436 "Say Alpha",
00437 " SayAlpha(string): This application will play the sounds that correspond to\n"
00438 "the letters of the given string.\n"
00439 },
00440
00441 { "SayPhonetic", pbx_builtin_sayphonetic,
00442 "Say Phonetic",
00443 " SayPhonetic(string): This application will play the sounds from the phonetic\n"
00444 "alphabet that correspond to the letters in the given string.\n"
00445 },
00446
00447 { "SetAccount", pbx_builtin_setaccount,
00448 "Set the CDR Account Code",
00449 " SetAccount([account]): This application will set the channel account code for\n"
00450 "billing purposes.\n"
00451 " SetAccount has been deprecated in favor of the Set(CDR(accountcode)=account).\n"
00452 },
00453
00454 { "SetAMAFlags", pbx_builtin_setamaflags,
00455 "Set the AMA Flags",
00456 " SetAMAFlags([flag]): This channel will set the channel's AMA Flags for billing\n"
00457 "purposes.\n"
00458 },
00459
00460 { "SetGlobalVar", pbx_builtin_setglobalvar,
00461 "Set a global variable to a given value",
00462 " SetGlobalVar(variable=value): This application sets a given global variable to\n"
00463 "the specified value.\n"
00464 },
00465
00466 { "SetLanguage", pbx_builtin_setlanguage,
00467 "Set the channel's preferred language",
00468 " SetLanguage(language): This will set the channel language to the given value.\n"
00469 "This information is used for the syntax in generation of numbers, and to choose\n"
00470 "a sound file in the given language, when it is available.\n"
00471 " For example, if language is set to 'fr' and the file 'demo-congrats' is \n"
00472 "requested to be played, if the file 'fr/demo-congrats' exists, then\n"
00473 "it will play that file. If not, it will play the normal 'demo-congrats'.\n"
00474 "For some language codes, SetLanguage also changes the syntax of some\n"
00475 "Asterisk functions, like SayNumber.\n"
00476 " SetLanguage has been deprecated in favor of Set(LANGUAGE()=language)\n"
00477 },
00478
00479 { "Set", pbx_builtin_setvar,
00480 "Set channel variable(s) or function value(s)",
00481 " Set(name1=value1|name2=value2|..[|options])\n"
00482 "This function can be used to set the value of channel variables or dialplan\n"
00483 "functions. It will accept up to 24 name/value pairs. When setting variables,\n"
00484 "if the variable name is prefixed with _, the variable will be inherited into\n"
00485 "channels created from the current channel. If the variable name is prefixed\n"
00486 "with __, the variable will be inherited into channels created from the current\n"
00487 "channel and all children channels.\n"
00488 " Options:\n"
00489 " g - Set variable globally instead of on the channel\n"
00490 " (applies only to variables, not functions)\n"
00491 },
00492
00493 { "SetVar", pbx_builtin_setvar_old,
00494 "Set channel variable(s)",
00495 " SetVar(name1=value1|name2=value2|..[|options]): This application has been\n"
00496 "deprecated in favor of using the Set application.\n"
00497 },
00498
00499 { "ImportVar", pbx_builtin_importvar,
00500 "Import a variable from a channel into a new variable",
00501 " ImportVar(newvar=channelname|variable): This application imports a variable\n"
00502 "from the specified channel (as opposed to the current one) and stores it as\n"
00503 "a variable in the current channel (the channel that is calling this\n"
00504 "application). Variables created by this application have the same inheritance\n"
00505 "properties as those created with the Set application. See the documentation for\n"
00506 "Set for more information.\n"
00507 },
00508
00509 { "Wait", pbx_builtin_wait,
00510 "Waits for some time",
00511 " Wait(seconds): This application waits for a specified number of seconds.\n"
00512 "Then, dialplan execution will continue at the next priority.\n"
00513 " Note that the seconds can be passed with fractions of a second. For example,\n"
00514 "'1.5' will ask the application to wait for 1.5 seconds.\n"
00515 },
00516
00517 { "WaitExten", pbx_builtin_waitexten,
00518 "Waits for an extension to be entered",
00519 " WaitExten([seconds][|options]): This application waits for the user to enter\n"
00520 "a new extension for a specified number of seconds.\n"
00521 " Note that the seconds can be passed with fractions of a second. For example,\n"
00522 "'1.5' will ask the application to wait for 1.5 seconds.\n"
00523 " Options:\n"
00524 " m[(x)] - Provide music on hold to the caller while waiting for an extension.\n"
00525 " Optionally, specify the class for music on hold within parenthesis.\n"
00526 },
00527
00528 };
00529
00530 static struct ast_context *contexts = NULL;
00531 AST_MUTEX_DEFINE_STATIC(conlock);
00532 static struct ast_app *apps = NULL;
00533 AST_MUTEX_DEFINE_STATIC(applock);
00534
00535 struct ast_switch *switches = NULL;
00536 AST_MUTEX_DEFINE_STATIC(switchlock);
00537
00538
00539
00540
00541
00542
00543
00544 AST_MUTEX_DEFINE_STATIC(hintlock);
00545 static int stateid = 1;
00546 struct ast_hint *hints = NULL;
00547 struct ast_state_cb *statecbs = NULL;
00548
00549
00550
00551
00552 int pbx_exec(struct ast_channel *c,
00553 struct ast_app *app,
00554 void *data,
00555 int newstack)
00556 {
00557 int res;
00558
00559 char *saved_c_appl;
00560 char *saved_c_data;
00561
00562 int (*execute)(struct ast_channel *chan, void *data) = app->execute;
00563
00564 if (newstack) {
00565 if (c->cdr && !ast_check_hangup(c))
00566 ast_cdr_setapp(c->cdr, app->name, data);
00567
00568
00569 saved_c_appl= c->appl;
00570 saved_c_data= c->data;
00571
00572 c->appl = app->name;
00573 c->data = data;
00574 res = execute(c, data);
00575
00576 c->appl= saved_c_appl;
00577 c->data= saved_c_data;
00578 return res;
00579 } else
00580 ast_log(LOG_WARNING, "You really didn't want to call this function with newstack set to 0\n");
00581 return -1;
00582 }
00583
00584
00585
00586 #define AST_PBX_MAX_STACK 128
00587
00588 #define HELPER_EXISTS 0
00589 #define HELPER_SPAWN 1
00590 #define HELPER_EXEC 2
00591 #define HELPER_CANMATCH 3
00592 #define HELPER_MATCHMORE 4
00593 #define HELPER_FINDLABEL 5
00594
00595
00596
00597 struct ast_app *pbx_findapp(const char *app)
00598 {
00599 struct ast_app *tmp;
00600
00601 if (ast_mutex_lock(&applock)) {
00602 ast_log(LOG_WARNING, "Unable to obtain application lock\n");
00603 return NULL;
00604 }
00605 tmp = apps;
00606 while(tmp) {
00607 if (!strcasecmp(tmp->name, app))
00608 break;
00609 tmp = tmp->next;
00610 }
00611 ast_mutex_unlock(&applock);
00612 return tmp;
00613 }
00614
00615 static struct ast_switch *pbx_findswitch(const char *sw)
00616 {
00617 struct ast_switch *asw;
00618
00619 if (ast_mutex_lock(&switchlock)) {
00620 ast_log(LOG_WARNING, "Unable to obtain application lock\n");
00621 return NULL;
00622 }
00623 asw = switches;
00624 while(asw) {
00625 if (!strcasecmp(asw->name, sw))
00626 break;
00627 asw = asw->next;
00628 }
00629 ast_mutex_unlock(&switchlock);
00630 return asw;
00631 }
00632
00633 static inline int include_valid(struct ast_include *i)
00634 {
00635 if (!i->hastime)
00636 return 1;
00637
00638 return ast_check_timing(&(i->timing));
00639 }
00640
00641 static void pbx_destroy(struct ast_pbx *p)
00642 {
00643 free(p);
00644 }
00645
00646 #define EXTENSION_MATCH_CORE(data,pattern,match) {\
00647 \
00648 if (pattern[0] != '_') \
00649 return 0;\
00650 \
00651 match=1;\
00652 pattern++;\
00653 while(match && *data && *pattern && (*pattern != '/')) {\
00654 while (*data == '-' && (*(data+1) != '\0')) data++;\
00655 switch(toupper(*pattern)) {\
00656 case '[': \
00657 {\
00658 int i,border=0;\
00659 char *where;\
00660 match=0;\
00661 pattern++;\
00662 where=strchr(pattern,']');\
00663 if (where)\
00664 border=(int)(where-pattern);\
00665 if (!where || border > strlen(pattern)) {\
00666 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");\
00667 return match;\
00668 }\
00669 for (i=0; i<border; i++) {\
00670 int res=0;\
00671 if (i+2<border)\
00672 if (pattern[i+1]=='-') {\
00673 if (*data >= pattern[i] && *data <= pattern[i+2]) {\
00674 res=1;\
00675 } else {\
00676 i+=2;\
00677 continue;\
00678 }\
00679 }\
00680 if (res==1 || *data==pattern[i]) {\
00681 match = 1;\
00682 break;\
00683 }\
00684 }\
00685 pattern+=border;\
00686 break;\
00687 }\
00688 case 'N':\
00689 if ((*data < '2') || (*data > '9'))\
00690 match=0;\
00691 break;\
00692 case 'X':\
00693 if ((*data < '0') || (*data > '9'))\
00694 match = 0;\
00695 break;\
00696 case 'Z':\
00697 if ((*data < '1') || (*data > '9'))\
00698 match = 0;\
00699 break;\
00700 case '.':\
00701 \
00702 return 1;\
00703 case '!':\
00704 \
00705 return 2;\
00706 case ' ':\
00707 case '-':\
00708 \
00709 data--;\
00710 break;\
00711 default:\
00712 if (*data != *pattern)\
00713 match =0;\
00714 }\
00715 data++;\
00716 pattern++;\
00717 }\
00718 \
00719 if (match && !*data && (*pattern == '!'))\
00720 return 2;\
00721 }
00722
00723 int ast_extension_match(const char *pattern, const char *data)
00724 {
00725 int match;
00726
00727 if (!strcmp(pattern, data))
00728 return 1;
00729 EXTENSION_MATCH_CORE(data,pattern,match);
00730
00731 if (*data || (*pattern && (*pattern != '/')))
00732 match = 0;
00733 return match;
00734 }
00735
00736 int ast_extension_close(const char *pattern, const char *data, int needmore)
00737 {
00738 int match;
00739
00740
00741 if ((strlen(pattern) < strlen(data)) && (pattern[0] != '_'))
00742 return 0;
00743
00744 if ((ast_strlen_zero((char *)data) || !strncasecmp(pattern, data, strlen(data))) &&
00745 (!needmore || (strlen(pattern) > strlen(data)))) {
00746 return 1;
00747 }
00748 EXTENSION_MATCH_CORE(data,pattern,match);
00749
00750
00751 if (!needmore || *pattern || match == 2) {
00752 return match;
00753 } else
00754 return 0;
00755 }
00756
00757 struct ast_context *ast_context_find(const char *name)
00758 {
00759 struct ast_context *tmp;
00760 ast_mutex_lock(&conlock);
00761 if (name) {
00762 tmp = contexts;
00763 while(tmp) {
00764 if (!strcasecmp(name, tmp->name))
00765 break;
00766 tmp = tmp->next;
00767 }
00768 } else
00769 tmp = contexts;
00770 ast_mutex_unlock(&conlock);
00771 return tmp;
00772 }
00773
00774 #define STATUS_NO_CONTEXT 1
00775 #define STATUS_NO_EXTENSION 2
00776 #define STATUS_NO_PRIORITY 3
00777 #define STATUS_NO_LABEL 4
00778 #define STATUS_SUCCESS 5
00779
00780 static int matchcid(const char *cidpattern, const char *callerid)
00781 {
00782 int failresult;
00783
00784
00785
00786
00787 if (!ast_strlen_zero(cidpattern))
00788 failresult = 0;
00789 else
00790 failresult = 1;
00791
00792 if (!callerid)
00793 return failresult;
00794
00795 return ast_extension_match(cidpattern, callerid);
00796 }
00797
00798 static struct ast_exten *pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, const char *context, const char *exten, int priority, const char *label, const char *callerid, int action, char *incstack[], int *stacklen, int *status, struct ast_switch **swo, char **data, const char **foundcontext)
00799 {
00800 int x, res;
00801 struct ast_context *tmp;
00802 struct ast_exten *e, *eroot;
00803 struct ast_include *i;
00804 struct ast_sw *sw;
00805 struct ast_switch *asw;
00806
00807
00808 if (!*stacklen) {
00809 *status = STATUS_NO_CONTEXT;
00810 *swo = NULL;
00811 *data = NULL;
00812 }
00813
00814 if (*stacklen >= AST_PBX_MAX_STACK) {
00815 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
00816 return NULL;
00817 }
00818
00819 for (x=0; x<*stacklen; x++) {
00820 if (!strcasecmp(incstack[x], context))
00821 return NULL;
00822 }
00823 if (bypass)
00824 tmp = bypass;
00825 else
00826 tmp = contexts;
00827 while(tmp) {
00828
00829 if (bypass || !strcmp(tmp->name, context)) {
00830 struct ast_exten *earlymatch = NULL;
00831
00832 if (*status < STATUS_NO_EXTENSION)
00833 *status = STATUS_NO_EXTENSION;
00834 for (eroot = tmp->root; eroot; eroot=eroot->next) {
00835 int match = 0;
00836
00837 if ((((action != HELPER_MATCHMORE) && ast_extension_match(eroot->exten, exten)) ||
00838 ((action == HELPER_CANMATCH) && (ast_extension_close(eroot->exten, exten, 0))) ||
00839 ((action == HELPER_MATCHMORE) && (match = ast_extension_close(eroot->exten, exten, 1)))) &&
00840 (!eroot->matchcid || matchcid(eroot->cidmatch, callerid))) {
00841
00842 if (action == HELPER_MATCHMORE && match == 2 && !earlymatch) {
00843
00844
00845 earlymatch = eroot;
00846 } else {
00847 e = eroot;
00848 if (*status < STATUS_NO_PRIORITY)
00849 *status = STATUS_NO_PRIORITY;
00850 while(e) {
00851
00852 if (action == HELPER_FINDLABEL) {
00853 if (*status < STATUS_NO_LABEL)
00854 *status = STATUS_NO_LABEL;
00855 if (label && e->label && !strcmp(label, e->label)) {
00856 *status = STATUS_SUCCESS;
00857 *foundcontext = context;
00858 return e;
00859 }
00860 } else if (e->priority == priority) {
00861 *status = STATUS_SUCCESS;
00862 *foundcontext = context;
00863 return e;
00864 }
00865 e = e->peer;
00866 }
00867 }
00868 }
00869 }
00870 if (earlymatch) {
00871
00872
00873
00874
00875 return NULL;
00876 }
00877
00878 sw = tmp->alts;
00879 while(sw) {
00880 if ((asw = pbx_findswitch(sw->name))) {
00881
00882 if (sw->eval)
00883 pbx_substitute_variables_helper(chan, sw->data, sw->tmpdata, SWITCH_DATA_LENGTH - 1);
00884 if (action == HELPER_CANMATCH)
00885 res = asw->canmatch ? asw->canmatch(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
00886 else if (action == HELPER_MATCHMORE)
00887 res = asw->matchmore ? asw->matchmore(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
00888 else
00889 res = asw->exists ? asw->exists(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
00890 if (res) {
00891
00892 *swo = asw;
00893 *data = sw->eval ? sw->tmpdata : sw->data;
00894 *foundcontext = context;
00895 return NULL;
00896 }
00897 } else {
00898 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
00899 }
00900 sw = sw->next;
00901 }
00902
00903 incstack[*stacklen] = tmp->name;
00904 (*stacklen)++;
00905
00906 i = tmp->includes;
00907 while(i) {
00908 if (include_valid(i)) {
00909 if ((e = pbx_find_extension(chan, bypass, i->rname, exten, priority, label, callerid, action, incstack, stacklen, status, swo, data, foundcontext)))
00910 return e;
00911 if (*swo)
00912 return NULL;
00913 }
00914 i = i->next;
00915 }
00916 break;
00917 }
00918 tmp = tmp->next;
00919 }
00920 return NULL;
00921 }
00922
00923
00924 #define DONT_HAVE_LENGTH 0x80000000
00925
00926 static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
00927 {
00928 char *varchar, *offsetchar = NULL;
00929 int parens=0;
00930
00931 *offset = 0;
00932 *length = DONT_HAVE_LENGTH;
00933 *isfunc = 0;
00934 for (varchar=var; *varchar; varchar++) {
00935 switch (*varchar) {
00936 case '(':
00937 (*isfunc)++;
00938 parens++;
00939 break;
00940 case ')':
00941 parens--;
00942 break;
00943 case ':':
00944 if (parens == 0) {
00945 offsetchar = varchar + 1;
00946 *varchar = '\0';
00947 goto pvn_endfor;
00948 }
00949 }
00950 }
00951 pvn_endfor:
00952 if (offsetchar) {
00953 sscanf(offsetchar, "%d:%d", offset, length);
00954 return 1;
00955 } else {
00956 return 0;
00957 }
00958 }
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968 static char *substring(const char *value, int offset, int length, char *workspace, size_t workspace_len)
00969 {
00970 char *ret = workspace;
00971 int lr;
00972
00973 ast_copy_string(workspace, value, workspace_len);
00974
00975 if (offset == 0 && length < 0)
00976 return ret;
00977
00978 lr = strlen(ret);
00979
00980 if (offset < 0) {
00981 offset = lr + offset;
00982 if (offset < 0)
00983 offset = 0;
00984 }
00985
00986
00987 if (offset >= lr)
00988 return ret + lr;
00989
00990 ret += offset;
00991 if (length >= 0 && length < lr - offset)
00992 ret[length] = '\0';
00993
00994 return ret;
00995 }
00996
00997
00998
00999 void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
01000 {
01001 char tmpvar[80];
01002 time_t thistime;
01003 struct tm brokentime;
01004 int offset, offset2, isfunc;