Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
-*- coding: utf-8 -*-
Changes with Apache 2.4.69

*) mod_env: Add the SetEnvFromFile directive to set internal environment
variables from a file of name=value lines, read at configuration time.
[Cornel Isbiceanu]

*) mod_cgid, mod_ssl, mod_md: Various hardening fixes. [Various authors]

*) mod_md: MDServerStatus is now disabled by default. [Joe Orton]
Expand Down
49 changes: 49 additions & 0 deletions docs/manual/mod/mod_env.xml
Original file line number Diff line number Diff line change
Expand Up @@ -118,5 +118,54 @@ SSI pages</description>
</usage>
</directivesynopsis>

<directivesynopsis>
<name>SetEnvFromFile</name>
<description>Sets environment variables from a file</description>
<syntax>SetEnvFromFile <var>file-path</var></syntax>
<contextlist><context>server config</context><context>virtual host</context>
<context>directory</context><context>.htaccess</context></contextlist>
<override>FileInfo</override>
<compatibility>Available in version 2.4.69 and later.</compatibility>

<usage>
<p>Sets internal environment variables read from a file, which are then
available to Apache HTTP Server modules, and passed on to CGI scripts and
SSI pages. This is equivalent to a series of <directive
module="mod_env">SetEnv</directive> directives, one per variable, but keeps
the values in a separate file.</p>

<p>The <var>file-path</var> is either an absolute path or a path relative
to the <directive module="core">ServerRoot</directive>. The file is read
once when the configuration is parsed; changes to it take effect only after
the server is restarted.</p>

<p>Each line of the file has the form <code>name=value</code>. Blank lines
and lines beginning with <code>#</code> are ignored, and leading and
trailing whitespace is stripped. If a line contains no <code>=</code>, the
variable is set to an empty string.</p>

<example><title>Example</title>
<highlight language="config">
SetEnvFromFile conf/app.env
</highlight>
</example>

<example><title>Example file (<code>conf/app.env</code>)</title>
<highlight language="config">
# Application settings
APP_MODE=production
SPECIAL_PATH=/foo/bin
</highlight>
</example>

<note><p>As with <directive module="mod_env">SetEnv</directive>, the
variables are set <em>after</em> most early request processing directives
are run, such as access control and URI-to-filename mapping.</p>
</note>
</usage>
<seealso><a href="../env.html">Environment Variables</a></seealso>
<seealso><directive module="mod_env">SetEnv</directive></seealso>
</directivesynopsis>

</modulesynopsis>

55 changes: 55 additions & 0 deletions modules/metadata/mod_env.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,59 @@ static const char *add_env_module_vars_unset(cmd_parms *cmd, void *sconf_,
return NULL;
}

static const char *add_env_module_vars_from_file(cmd_parms *cmd, void *sconf_,
const char *arg)
{
env_dir_config_rec *sconf = sconf_;
const char *fname;
ap_configfile_t *file;
apr_status_t rv;
char line[MAX_STRING_LEN];

fname = ap_server_root_relative(cmd->temp_pool, arg);
if (!fname) {
return apr_pstrcat(cmd->pool, cmd->cmd->name,
": Invalid file path ", arg, NULL);
}

rv = ap_pcfg_openfile(&file, cmd->temp_pool, fname);
if (rv != APR_SUCCESS) {
return apr_psprintf(cmd->pool, "%s: Could not open file %s: %pm",
cmd->cmd->name, fname, &rv);
}

/* Each line is "name=value"; blank lines and '#' comments are ignored.
* ap_cfg_getline() strips surrounding whitespace and handles line
* continuations. Names are read at config time and stored in the same
* table used by SetEnv, so they merge and reach r->subprocess_env the
* same way.
*/
while (!ap_cfg_getline(line, sizeof(line), file)) {
const char *rest = line;
const char *name, *value;

if (line[0] == '#' || line[0] == '\0') {
continue;
}

name = ap_getword(cmd->pool, &rest, '=');
if (!name[0]) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
APLOGNO(10622) "%s: Skipping malformed line "
"(no variable name) in %s", cmd->cmd->name, fname);
continue;
}

/* rest points just past the '='; no '=' means an empty value. */
value = apr_pstrdup(cmd->pool, rest);
apr_table_setn(sconf->vars, name, value);
}

ap_cfg_closefile(file);

return NULL;
}

static const command_rec env_module_cmds[] =
{
AP_INIT_ITERATE("PassEnv", add_env_module_vars_passed, NULL,
Expand All @@ -154,6 +207,8 @@ AP_INIT_TAKE12("SetEnv", add_env_module_vars_set, NULL,
OR_FILEINFO, "an environment variable name and optional value to pass to CGI."),
AP_INIT_ITERATE("UnsetEnv", add_env_module_vars_unset, NULL,
OR_FILEINFO, "a list of variables to remove from the CGI environment."),
AP_INIT_TAKE1("SetEnvFromFile", add_env_module_vars_from_file, NULL,
OR_FILEINFO, "the path to a file of name=value lines to pass to CGI."),
{NULL},
};

Expand Down
2 changes: 2 additions & 0 deletions test/pytest_suite/t/conf/extra.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,8 @@ Alias /manual @inherit_documentroot@/manual
SetEnv NOT_HERE "this will not be here"
UnsetEnv NOT_HERE

SetEnvFromFile @SERVERROOT@/htdocs/modules/env/vars.env

<Directory @SERVERROOT@/htdocs/modules/env>
Options +Includes
</Directory>
Expand Down
1 change: 1 addition & 0 deletions test/pytest_suite/t/htdocs/modules/env/fromfile.shtml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!--#echo var="ENV_FROM_FILE" -->
2 changes: 2 additions & 0 deletions test/pytest_suite/t/htdocs/modules/env/vars.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# mod_env SetEnvFromFile test fixture
ENV_FROM_FILE=set from file
2 changes: 2 additions & 0 deletions test/pytest_suite/tests/t/modules/test_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
"unset": "(none)",
"type": "(none)",
"nothere": "(none)",
# SetEnvFromFile reads htdocs/modules/env/vars.env (ENV_FROM_FILE=set from file).
"fromfile": "set from file",
}


Expand Down