Index: CHANGES
===================================================================
--- CHANGES	(revision 247247)
+++ CHANGES	(working copy)
@@ -197,6 +197,15 @@
  * Added DYNAMIC_FEATURENAME which holds the last triggered dynamic feature.
  * Added DYNAMIC_PEERNAME which holds the unique channel name on the other side
    and is set when a dynamic feature is triggered.
+ * Added PARKINGLOT which can be used with parkeddynamic feature.conf option
+   to dynamically create a new parking lot matching the value this varible is
+   set to.
+ * Added PARKINGDYNAMIC which represents the template parkinglot defined in
+   features.conf that should be the base for dynamic parkinglots.
+ * Added PARKINGDYNCONTEXT which tells what context a newly created dynamic
+   parkinglot should have.
+ * Added PARKINGDYNPOS which holds what parking positions a dynamic parkinglot
+   should have.
 
 Queue changes
 -------------
@@ -396,6 +405,8 @@
  * jabber.conf supports a new option auth_policy that toggles auto user registration.
  * A new lockconfdir option has been added to asterisk.conf to protect the
    configuration directory (/etc/asterisk by default) during reloads.
+ * The parkeddynamic option has been added to features.conf to enable the creation
+   of dynamic parkinglots.
 
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 1.6.1 to Asterisk 1.6.2  -------------
Index: main/features.c
===================================================================
--- main/features.c	(revision 247247)
+++ main/features.c	(working copy)
@@ -212,6 +212,14 @@
 			<para>If you set the <variable>PARKINGEXTEN</variable> variable to an extension in your
 			parking context, Park() will park the call on that extension, unless
 			it already exists. In that case, execution will continue at next priority.</para>
+			<para>If you set the <variable>PARKINGLOT</variable> variable, Park() will park the call
+			in that parkinglot.</para>
+			<para>If you set the <variable>PARKINGDYNAMIC</variable> variable, this parkinglot from features.conf
+			will be used as template for the newly created dynamic lot.</para>
+			<para>If you set the <variable>PARKINGDYNCONTEXT</variable> variable the newly created dynamic
+			parking lot will use this context.</para>
+			<para>If you set the <variable>PARKINGDYNPOS</variable> variable the newly created dynamic parkinglot
+			will use those parking postitions.</para>
 		</description>
 		<see-also>
 			<ref type="application">ParkAndAnnounce</ref>
@@ -356,6 +364,7 @@
 
 static char courtesytone[256];                             /*!< Courtesy tone */
 static int parkedplay = 0;                                 /*!< Who to play the courtesy tone to */
+static int parkeddynamic = 0;                              /*!< Enable creation of parkinglots dynamically */
 static char xfersound[256];                                /*!< Call transfer sound */
 static char xferfailsound[256];                            /*!< Call transfer failure sound */
 static char pickupsound[256];                              /*!< Pickup sound */
@@ -426,8 +435,9 @@
 static void parkinglot_destroy(void *obj);
 int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds, int *fs, int *max);
 struct ast_parkinglot *find_parkinglot(const char *name);
+static struct ast_parkinglot *create_parkinglot(const char *name);
+static struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot);
 
-
 const char *ast_parking_ext(void)
 {
 	return parking_ext;
@@ -679,23 +689,67 @@
 	struct parkeduser *pu;
 };
 
-static struct parkeduser *park_space_reserve(struct ast_channel *chan,
- struct ast_channel *peer, struct ast_park_call_args *args)
+static struct parkeduser *park_space_reserve(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
 {
 	struct parkeduser *pu;
 	int i, parking_space = -1, parking_range;
 	const char *parkinglotname = NULL;
 	const char *parkingexten;
 	struct ast_parkinglot *parkinglot = NULL;
-	
+
 	if (peer)
 		parkinglotname = findparkinglotname(peer);
 
 	if (parkinglotname) {
-		if (option_debug)
-			ast_log(LOG_DEBUG, "Found chanvar Parkinglot: %s\n", parkinglotname);
-		parkinglot = find_parkinglot(parkinglotname);	
+		ast_debug(1, "Found chanvar Parkinglot: %s\n", parkinglotname);
+		parkinglot = find_parkinglot(parkinglotname);
+
 	}
+
+	/* Dynamically create parkinglot */
+	if (!parkinglot && parkeddynamic && !ast_strlen_zero(parkinglotname)) {
+		const char *dyn_context, *dyn_range;
+		const char *parkinglotname_copy = NULL;
+		struct ast_parkinglot *parkinglot_copy = NULL;
+		int dyn_start, dyn_end;
+
+		ast_channel_lock(chan);
+		parkinglotname_copy = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNAMIC"), ""));
+		dyn_context = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNCONTEXT"), ""));
+		dyn_range = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNPOS"), ""));
+		ast_channel_unlock(chan);
+
+		if (!ast_strlen_zero(parkinglotname_copy)) {
+			parkinglot_copy = find_parkinglot(parkinglotname_copy);
+		}
+		if (!parkinglot_copy) {
+			parkinglot_copy = parkinglot_addref(default_parkinglot);
+			ast_debug(1, "Using default parking lot for copy\n");
+		}
+		if (!(parkinglot = copy_parkinglot(parkinglotname, parkinglot_copy))) {
+			ast_log(LOG_ERROR, "Could not build dynamic parking lot!\n");
+		} else {
+			if (!ast_strlen_zero(dyn_context)) {
+				ast_copy_string(parkinglot->parking_con, dyn_context, sizeof(parkinglot->parking_con));
+			}
+			if (!ast_strlen_zero(dyn_range)) {
+				if (sscanf(dyn_range, "%30d-%30d", &dyn_start, &dyn_end) != 2) {
+					ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers\n");
+				} else {
+					parkinglot->parking_start = dyn_start;
+					parkinglot->parking_stop = dyn_end;
+				}
+			}
+			ao2_link(parkinglots, parkinglot);
+		}
+
+		if (parkinglot_copy) {
+			/* unref our tempory copy */
+			parkinglot_unref(parkinglot_copy);
+			parkinglot_copy = NULL;
+		}
+	}
+
 	if (!parkinglot) {
 		parkinglot = parkinglot_addref(default_parkinglot);
 	}
@@ -3508,6 +3562,27 @@
 	return parkinglot;
 }
 
+/*! \brief Copy parkinglot and store it with new name */
+struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot) {
+	struct ast_parkinglot *copylot;
+
+	if (ast_strlen_zero(name)) { /* No name specified */
+		return NULL;
+	}
+	if (find_parkinglot(name)) { /* Parkinglot with that name allready exists */
+		return NULL;
+	}
+
+	copylot = create_parkinglot(name);
+	ast_debug(1, "Building parking lot %s\n", name);
+
+	memcpy(copylot, parkinglot, sizeof(struct ast_parkinglot));
+	ast_copy_string(copylot->name, name, sizeof(copylot->name));
+	AST_LIST_HEAD_INIT(&copylot->parkings);
+
+	return copylot;
+}
+
 AST_APP_OPTIONS(park_call_options, BEGIN_OPTIONS
 	AST_APP_OPTION('r', AST_PARK_OPT_RINGING),
 	AST_APP_OPTION('R', AST_PARK_OPT_RANDOMIZE),
@@ -3792,7 +3867,7 @@
 }
 
 /*! \brief Allocate parking lot structure */
-static struct ast_parkinglot *create_parkinglot(char *name)
+static struct ast_parkinglot *create_parkinglot(const char *name)
 {
 	struct ast_parkinglot *newlot = (struct ast_parkinglot *) NULL;
 
@@ -3842,9 +3917,8 @@
 
 	ao2_lock(parkinglot);
 
-	if (option_debug)
-		ast_log(LOG_DEBUG, "Building parking lot %s\n", name);
-	
+	ast_debug(1, "Building parking lot %s\n", name);
+
 	/* Do some config stuff */
 	while(confvar) {
 		if (!strcasecmp(confvar->name, "context")) {
@@ -4027,6 +4101,7 @@
 	pickupfailsound[0] = '\0';
 	adsipark = 0;
 	comebacktoorigin = 1;
+	parkeddynamic = 0;
 
 	default_parkinglot->parkaddhints = 0;
 	default_parkinglot->parkedcalltransfers = 0;
@@ -4098,6 +4173,8 @@
 				default_parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYCALLER;
 			else if (!strcasecmp(var->value, "callee"))
 				default_parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYCALLEE;
+		} else if (!strcasecmp(var->name, "parkeddynamic")) {
+			parkeddynamic = ast_true(var->value);
 		} else if (!strcasecmp(var->name, "adsipark")) {
 			adsipark = ast_true(var->value);
 		} else if (!strcasecmp(var->name, "transferdigittimeout")) {
Index: configs/features.conf.sample
===================================================================
--- configs/features.conf.sample	(revision 247247)
+++ configs/features.conf.sample	(working copy)
@@ -27,6 +27,7 @@
                                 ; one of: callee, caller, both, no (default is no)
 ;parkedcallrecording = caller   ; Enables or disables DTMF based one-touch recording when picking up a parked call.
                                 ; one of: callee, caller, both, no (default is no)
+;parkeddynamic = yes            ; Enables dynamically created parkinglots. (default is no)
 ;adsipark = yes			; if you want ADSI parking announcements
 ;findslot => next		; Continue to the 'next' free parking space.
 				; Defaults to 'first' available
