Author: issac
Date: Sun Oct 22 02:42:25 2006
New Revision: 466638
URL: http://svn.apache.org/viewvc?view=rev&rev=466638
Log:
Added initial support for dynamic prompts + prompt function allows val to
(usually) be const char * (as it used to be)
Modified:
httpd/apreq/branches/enhanced-cgi/library/module_cgi.c
Modified: httpd/apreq/branches/enhanced-cgi/library/module_cgi.c
URL:
http://svn.apache.org/viewvc/httpd/apreq/branches/enhanced-cgi/library/module_cgi.c?view=diff&rev=466638&r1=466637&r2=466638
==============================================================================
--- httpd/apreq/branches/enhanced-cgi/library/module_cgi.c (original)
+++ httpd/apreq/branches/enhanced-cgi/library/module_cgi.c Sun Oct 22 02:42:25
2006
@@ -15,6 +15,8 @@
*/
#include <assert.h>
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
#include "apreq_module.h"
#include "apreq_error.h"
#include "apr_strings.h"
@@ -48,8 +50,6 @@
* never catch it now, as args param will match...
*/
-
-
struct cgi_handle {
struct apreq_handle_t handle;
@@ -70,11 +70,16 @@
apr_bucket_brigade *in;
apr_bucket_brigade *tmpbb;
- int interactive_mode;
- apr_file_t *sout, *sin;
+ int interactive_mode;
+ const char *promptstr;
+ apr_file_t *sout, *sin;
};
#define CRLF "\015\012"
+const char *nullstr;
+#define DEFAULT_PROMPT "([$t] )$n(\\($l\\))([$d]): "
+#define MAX_PROMPT_NESTING_LEVELS 8
+#define MAX_BUFFER_SIZE 65536
typedef struct {
const char *t_name;
@@ -95,17 +100,132 @@
static char* chomp(char* str) {
apr_size_t p = strlen(str);
- while (--p > 0) {
+ while (--p >= 0) {
switch ((char)(str[p])) {
case '\015':
case '\012':str[p]='\000';
break;
default:return str;
}
- }
+ }
return str;
}
+/** TODO: Support wide-characters */
+static char *prompt(apreq_handle_t *handle, const char *name,
+ const char *type) {
+ struct cgi_handle *req = (struct cgi_handle *)handle;
+ const char *defval = nullstr;
+ const char *label = NULL;
+ const char *prompt;
+ char buf[MAX_PROMPT_NESTING_LEVELS][MAX_BUFFER_SIZE];
+ /* Array of current arg for given p-level */
+ char *start, curarg[MAX_PROMPT_NESTING_LEVELS] = "";
+ /* Parenthesis level (for argument/text grouping) */
+ int plevel;
+
+ prompt = req->promptstr - 1;
+ *buf[0] = plevel = 0;
+ start = buf[0];
+
+ while (*(++prompt) != 0) {
+ switch (*prompt) {
+ case '$': /* interpolate argument; curarg[plevel] => 1 */
+ prompt++;
+ switch (*prompt) {
+ case 't':
+ if (type != NULL) {
+ strcpy(start, type);
+ start += strlen(type);
+ curarg[plevel] = 1;
+ } else {
+ curarg[plevel] = curarg[plevel] | 0;
+ }
+ break;
+ case 'n':
+ /* Name can't be null :-) [If it can, we should
+ * immediately return NULL] */
+ strcpy(start, name);
+ start += strlen(name);
+ curarg[plevel] = 1;
+ break;
+ case 'l':
+ if (label != NULL) {
+ strcpy(start, label);
+ start += strlen(label);
+ curarg[plevel] = 1;
+ } else {
+ curarg[plevel] = curarg[plevel] | 0;
+ }
+ break;
+ case 'd':
+ /* TODO: Once null defaults are available,
+ * remove if and use nullstr if defval == NULL */
+ if (defval != NULL) {
+ strcpy(start, defval);
+ start += strlen(defval);
+ curarg[plevel] = 1;
+ } else {
+ curarg[plevel] = curarg[plevel] | 0;
+ }
+ break;
+ default:
+ /* Handle this? */
+ break;
+ }
+ break;
+
+ case '(':
+ if (plevel <= MAX_PROMPT_NESTING_LEVELS) {
+ plevel++;
+ curarg[plevel] = *buf[plevel] = 0;
+ start = buf[plevel];
+ }
+ /* else? */
+ break;
+
+ case ')':
+ if (plevel > 0) {
+ *start = 0; /* Null terminate current string */
+
+ /* Move pointer to end of string */
+ start = buf[--plevel] + strlen(buf[plevel]);
+
+ /* If old curarg was set, concat buffer with level down */
+ if (curarg[plevel + 1]) {
+ strcpy(start, buf[plevel + 1]);
+ start += strlen(buf[plevel + 1]);
+ }
+
+ break;
+ }
+ case '\\': /* Check next character for escape sequence
+ * (just ignore it for now) */
+ *prompt++;
+ /* Fallthrough */
+
+ default:
+ *start++ = *prompt;
+ }
+ }
+
+ *start = 0; /* Null terminate the string */
+
+ apr_file_printf(req->sout, "%s", buf[0]);
+ apr_file_gets(buf[0], MAX_BUFFER_SIZE, req->sin);
+ chomp(buf[0]);
+ if (stricmp(buf[0], "")) {
+/* if (strcmp(buf[0], nullstr)) */
+ return apr_pstrdup(handle->pool, buf[0]);
+/* return NULL; */
+ }
+
+ if (strcmp(defval, nullstr))
+ return apr_pstrdup(handle->pool, defval);
+
+ return NULL;
+}
+
static const char *cgi_header_in(apreq_handle_t *handle,
const char *name)
{
@@ -350,27 +470,26 @@
if (req->interactive_mode && req->jar_status != APR_SUCCESS) {
char buf[65536];
- char *name, *val;
+ const char *name, *val;
apreq_cookie_t *p;
int i = 1;
apr_file_printf(req->sout, "[CGI] Requested all cookies\n");
while (1) {
- apr_file_printf(req->sout, "[CGI] Please enter a name for cookie
%d (or END to end): ",
+ apr_file_printf(req->sout, "[CGI] Please enter a name for cookie
%d (or just hit ENTER to end): ",
i++);
apr_file_gets(buf, 65536, req->sin);
chomp(buf);
- if (!strcmp(buf, "END")) {
+ if (!strcmp(buf, "")) {
break;
}
name = apr_pstrdup(handle->pool, buf);
- apr_file_printf(req->sout, "[CGI] Please enter a value for cookie
%s: ",
- name);
- apr_file_gets(buf, 65536, req->sin);
- chomp(buf);
- p = apreq_cookie_make(handle->pool, name, strlen(name), buf,
strlen(buf));
+ val = prompt(handle, name, "cookie");
+ if (val == NULL)
+ val = "";
+ p = apreq_cookie_make(handle->pool, name, strlen(name), val,
strlen(val));
apreq_cookie_tainted_on(p);
apreq_value_table_add(&p->v, req->jar);
- val = (char *)p->v.data;
+ val = p->v.data;
}
req->jar_status = APR_SUCCESS;
} /** Fallthrough */
@@ -396,27 +515,26 @@
if (req->interactive_mode && req->args_status != APR_SUCCESS) {
char buf[65536];
- char *name, *val;
+ const char *name, *val;
apreq_param_t *p;
int i = 1;
apr_file_printf(req->sout, "[CGI] Requested all argument
parameters\n");
while (1) {
- apr_file_printf(req->sout, "[CGI] Please enter a name for
parameter %d (or END to end): ",
+ apr_file_printf(req->sout, "[CGI] Please enter a name for
parameter %d (or jusr hit ENTER to end): ",
i++);
apr_file_gets(buf, 65536, req->sin);
chomp(buf);
- if (!strcmp(buf, "END")) {
+ if (!strcmp(buf, "")) {
break;
}
name = apr_pstrdup(handle->pool, buf);
- apr_file_printf(req->sout, "[CGI] Please enter a value for
parameter %s: ",
- name);
- apr_file_gets(buf, 65536, req->sin);
- chomp(buf);
- p = apreq_param_make(handle->pool, name, strlen(name), buf,
strlen(buf));
+ val = prompt(handle, name, "parameter");
+ if (val == NULL)
+ val = "";
+ p = apreq_param_make(handle->pool, name, strlen(name), val,
strlen(val));
apreq_param_tainted_on(p);
apreq_value_table_add(&p->v, req->args);
- val = (char *)p->v.data;
+ val = p->v.data;
}
req->args_status = APR_SUCCESS;
} /** Fallthrough */
@@ -443,7 +561,7 @@
{
struct cgi_handle *req = (struct cgi_handle *)handle;
const apr_table_t *t;
- char *val = NULL;
+ const char *val = NULL;
if (req->jar_status == APR_EINIT && !req->interactive_mode)
cgi_jar(handle, &t);
@@ -455,16 +573,14 @@
if (!req->interactive_mode) {
return NULL;
} else {
- char buf[65536];
apreq_cookie_t *p;
- apr_file_printf(req->sout, "[CGI] Please enter a value for cookie
%s: ",
- name);
- apr_file_gets(buf, 65536, req->sin);
- chomp(buf);
- p = apreq_cookie_make(handle->pool, name, strlen(name), buf,
strlen(buf));
+ val = prompt(handle, name, "cookie");
+ if (val == NULL)
+ return NULL;
+ p = apreq_cookie_make(handle->pool, name, strlen(name), val,
strlen(val));
apreq_cookie_tainted_on(p);
apreq_value_table_add(&p->v, req->jar);
- val = (char *)p->v.data;
+ val = p->v.data;
}
}
@@ -477,28 +593,26 @@
{
struct cgi_handle *req = (struct cgi_handle *)handle;
const apr_table_t *t;
- char *val = NULL;
+ const char *val = NULL;
if (req->args_status == APR_EINIT && !req->interactive_mode)
cgi_args(handle, &t);
else
t = req->args;
- val = (char *)apr_table_get(t, name);
+ val = apr_table_get(t, name);
if (val == NULL) {
if (!req->interactive_mode) {
return NULL;
} else {
- char buf[65536];
apreq_param_t *p;
- apr_file_printf(req->sout, "[CGI] Please enter a value for
parameter %s: ",
- name);
- apr_file_gets(buf, 65536, req->sin);
- chomp(buf);
- p = apreq_param_make(handle->pool, name, strlen(name), buf,
strlen(buf));
+ val = prompt(handle, name, "parameter");
+ if (val == NULL)
+ return NULL;
+ p = apreq_param_make(handle->pool, name, strlen(name), val,
strlen(val));
apreq_param_tainted_on(p);
apreq_value_table_add(&p->v, req->args);
- val = (char *)p->v.data;
+ val = p->v.data;
}
}
@@ -514,28 +628,27 @@
struct cgi_handle *req = (struct cgi_handle *)handle;
if (req->interactive_mode && req->body_status != APR_SUCCESS) {
- char buf[65536];
- char *name, *val;
+ const char *name, *val;
apreq_param_t *p;
int i = 1;
apr_file_printf(req->sout, "[CGI] Requested all body parameters\n");
while (1) {
- apr_file_printf(req->sout, "[CGI] Please enter a name for
parameter %d (or END to end): ",
+ char buf[65536];
+ apr_file_printf(req->sout, "[CGI] Please enter a name for
parameter %d (or just hit ENTER to end): ",
i++);
apr_file_gets(buf, 65536, req->sin);
chomp(buf);
- if (!strcmp(buf, "END")) {
+ if (!strcmp(buf, "")) {
break;
}
name = apr_pstrdup(handle->pool, buf);
- apr_file_printf(req->sout, "[CGI] Please enter a value for
parameter %s: ",
- name);
- apr_file_gets(buf, 65536, req->sin);
- chomp(buf);
- p = apreq_param_make(handle->pool, name, strlen(name), buf,
strlen(buf));
+ val = prompt(handle, name, "parameter");
+ if (val == NULL)
+ val = "";
+ p = apreq_param_make(handle->pool, name, strlen(name), val,
strlen(val));
apreq_param_tainted_on(p);
apreq_value_table_add(&p->v, req->body);
- val = (char *)p->v.data;
+ val = p->v.data;
}
req->body_status = APR_SUCCESS;
} /** Fallthrough */
@@ -561,24 +674,22 @@
const char *name)
{
struct cgi_handle *req = (struct cgi_handle *)handle;
- char *val = NULL;
+ const char *val = NULL;
apreq_hook_t *h;
if (req->interactive_mode) {
- val = (char *)apr_table_get(req->body, name);
+ val = apr_table_get(req->body, name);
if (val == NULL) {
return NULL;
} else {
- char buf[65536];
apreq_param_t *p;
- apr_file_printf(req->sout, "[CGI] Please enter a value for
parameter %s: ",
- name);
- apr_file_gets(buf, 65536, req->sin);
- chomp(buf);
- p = apreq_param_make(handle->pool, name, strlen(name), buf,
strlen(buf));
+ val = prompt(handle, name, "parameter");
+ if (val == NULL)
+ return NULL;
+ p = apreq_param_make(handle->pool, name, strlen(name), val,
strlen(val));
apreq_param_tainted_on(p);
apreq_value_table_add(&p->v, req->body);
- val = (char *)p->v.data;
+ val = p->v.data;
return apreq_value_to_param(val);
}
}
@@ -588,7 +699,7 @@
case APR_SUCCESS:
- val = (char *)apr_table_get(req->body, name);
+ val = apr_table_get(req->body, name);
if (val != NULL)
return apreq_value_to_param(val);
return NULL;
@@ -604,7 +715,7 @@
case APR_INCOMPLETE:
- val = (char *)apr_table_get(req->body, name);
+ val = apr_table_get(req->body, name);
if (val != NULL)
return apreq_value_to_param(val);
@@ -637,7 +748,7 @@
if (req->body == NULL)
return NULL;
- val = (char *)apr_table_get(req->body, name);
+ val = apr_table_get(req->body, name);
if (val != NULL)
return apreq_value_to_param(val);
return NULL;
@@ -853,9 +964,13 @@
req->body_status = APR_EINIT;
if (is_interactive_mode(pool)) {
+ char buf[10];
req->interactive_mode = 1;
apr_file_open_stdout(&(req->sout), pool);
apr_file_open_stdin(&(req->sin), pool);
+ req->promptstr=apr_pstrdup(pool, DEFAULT_PROMPT);
+ sprintf(buf, "%s", NULL);
+ nullstr = apr_pstrdup(pool, buf);
}
apr_pool_userdata_setn(&req->handle, USER_DATA_KEY, NULL, pool);