/*
 * Dynamically load map routine.
 *
 * Replace the userdir rule in http_paths.conf with the following:
 *
 *    usermap /$* myuserdir,dynuser
 */
#include "access.h"			/* Access structure. */
#include "ident_map.h"
#include "tutil.h"
#include <stdio.h>

int http_user_information();
int ts_tcp_stack_used ( ) { return 1000; }
/***************************************************************************/
/* Convert /$username/.... specification to /device/home-dir/... according
 * to information in the user authorization file.  The sysuaf file may need to
 * be modified to granted read access.
 *
 * Return values:
 *	-1	Translation failed (username not found)
 *	4	Translation successful.
 */
int myuserdir ( info_ptr blk, char *translation, int maxlen,
	access_info acc, char **case_preserved, int cp_len )
{
    int i, user_len, login_len, delta, status, length;
    char login[128];
    /*
     * Parse username out of translation (part after pattern).
     */
    for ( i = blk->pat_len; (i < maxlen) && translation[i] &&
	  (translation[i] != '/'); i++ );
    user_len = i - blk->pat_len;
    /*
     * Search remainder of translation buffer for parent directory references
     * (/../) and disallow.
     */
    for ( ; translation[i]; i++ ) if ( translation[i] == '/' ) {
	if ( 0 == tu_strncmp ( &translation[i], "/../", 4 ) ) return IDENT_MAP_LOOP;
    }
    /*
     * Fetch information about user.  Block other activity and set privilege.
     */
    status = http_user_information ( &translation[blk->pat_len], user_len, 
		&acc->uic, login, sizeof(login) );
    if ( (status&1) == 0 ) return IDENT_MAP_LOOP;
    /*
     * Calculate length of login directory + userdir path and make gap
     * in translation string to accomodate it.
     */
    login_len = tu_strlen ( login );
    if ( blk->val_len == 0 ) {
	/* userdir is null, shorten login_len to exclude extra '/' */
	login_len--;
    }
    
    user_len += blk->pat_len;
    delta = login_len + blk->val_len - user_len;

    length = tu_strlen ( translation );
    if ( delta > 0 ) {
	/* New value longer than current */
	if ( length+delta > maxlen ) delta = 0;
	for ( i = length; i > 0; --i )
		translation[i+delta] = translation[i];
    } else {
	/* New value smaller than /~username. */
	for ( i = user_len; i <= length; i++ ) 
		translation[i+delta] = translation[i];
    }
    /*
     * Load users device, directory and subdirectory into gap.
     */
    tu_strncpy ( translation, login, login_len );
    tu_strncpy ( &translation[login_len], blk->value, blk->val_len );
    /*
     * Do additional fixup of user portion.
     */
    tu_strupcase ( &translation[login_len], &translation[login_len] );

    return IDENT_MAP_OK_USERMAP;
}
