/*
 * This is called after session_init() when a session needs to authenticate
 * to HPSS.
 */
globus_result_t
session_authenticate(session_handle_t * SessionHandle)
{
	globus_result_t result = GLOBUS_SUCCESS;

    GlobusGFSName(__func__);
    GlobusGFSHpssDebugEnter();

	/* Check if we have already authenticated. */
	if (SessionHandle->Authenticated == GLOBUS_TRUE)
		goto cleanup;

	/* Parse the config files. */
	result = config_init(&SessionHandle->ConfigHandle);
	if (result != GLOBUS_SUCCESS)
	{
		result = GlobusGFSErrorWrapFailed("config_init", result);
		goto cleanup;
	}

	/* Authenticate to HPSS. */
	result = session_auth_to_hpss(SessionHandle);
	if (result != GLOBUS_SUCCESS)
	{
		result = GlobusGFSErrorWrapFailed("Attempt to authenticate to HPSS", result);
		goto cleanup;
	}

	/* Indicate that we have authenticated. */
	SessionHandle->Authenticated = GLOBUS_TRUE;

cleanup:
	if (result != GLOBUS_SUCCESS)
	{
		GlobusGFSHpssDebugExitWithError();
		return result;
	}

	GlobusGFSHpssDebugExit();
	return GLOBUS_SUCCESS;
}
static int
osg_activate(void)
{
    GlobusGFSName(osg_activate);
    globus_result_t result = GLOBUS_SUCCESS;

    memset(&osg_dsi_iface, '\0', sizeof(globus_gfs_storage_iface_t));

    char * dsi_name = getenv("OSG_EXTENSIONS_OVERRIDE_DSI");
    dsi_name = dsi_name ? dsi_name : "file";

    // Code adapted from globus_i_gfs_data.c in Globus Toolkit.
    void *new_dsi = (globus_gfs_storage_iface_t *) globus_extension_lookup(
        &osg_dsi_handle, GLOBUS_GFS_DSI_REGISTRY, dsi_name);
    if (new_dsi == NULL)
    {
        char module_name[1024];
        snprintf(module_name, 1024, "globus_gridftp_server_%s", dsi_name);
        module_name[1023] = '\0';
        result = globus_extension_activate(module_name);
        if (result != GLOBUS_SUCCESS)
        {
            result = GlobusGFSErrorWrapFailed("DSI activation", result);
            return result;
        }
    }
    new_dsi = (globus_gfs_storage_iface_t *) globus_extension_lookup(
        &osg_dsi_handle, GLOBUS_GFS_DSI_REGISTRY, dsi_name);
    if(new_dsi == NULL)
    {
        GlobusGFSErrorGenericStr(result,
            ("DSI '%s' is not available in the module.", dsi_name));
        return result;
    }

    memcpy(&osg_dsi_iface, new_dsi, sizeof(globus_gfs_storage_iface_t));
    original_command_function = osg_dsi_iface.command_func;
    original_init_function = osg_dsi_iface.init_func;
    osg_dsi_iface.command_func = osg_command;
    osg_dsi_iface.init_func = osg_extensions_init;

    globus_extension_registry_add(
        GLOBUS_GFS_DSI_REGISTRY,
        "osg",
        GlobusExtensionMyModule(globus_gridftp_server_osg),
        &osg_dsi_iface);
    
    return result;
}
static void
osg_extensions_init(globus_gfs_operation_t op, globus_gfs_session_info_t * session)
{
    GlobusGFSName(osg_extensions_init);

    globus_result_t result = globus_gridftp_server_add_command(op, "SITE USAGE",
                                 GLOBUS_GFS_OSG_CMD_SITE_USAGE,
                                 3,
                                 5,
                                 "SITE USAGE <sp> [TOKEN <sp> $name] <sp> $location: Get usage information for a location.",
                                 GLOBUS_FALSE,
                                 GFS_ACL_ACTION_LOOKUP);

    if (result != GLOBUS_SUCCESS)
    {
        result = GlobusGFSErrorWrapFailed("Failed to add custom 'SITE USAGE' command", result);
        globus_gridftp_server_finished_session_start(op,
                                                 result,
                                                 NULL,
                                                 NULL,
                                                 NULL);
        return;
    }

#ifdef VOMS_FOUND

    struct vomsdata *vdata = VOMS_Init(NULL, NULL);
    if (vdata)
    {
        int error;
        if (!VOMS_RetrieveFromCred(session->del_cred, RECURSE_CHAIN, vdata, &error))
        {
            globus_gfs_log_message(GLOBUS_GFS_LOG_TRANSFER, "No VOMS info in credential.\n");
        }
        else
        {
            struct voms *vext;
            int idx;
            for (idx = 0; vdata->data[idx] != NULL; idx++)
            {
                char msg[1024];
                char *pos = msg;
                int char_remaining = 1022;
                vext = vdata->data[idx];
                int this_round;
                if ((char_remaining > 0) && vext->voname)
                {
                    this_round = snprintf(pos, char_remaining, "VO %s ", vext->voname);
                    pos += this_round;
                    char_remaining -= this_round;
                }
                char *fqan;
                int count = 0;
                int idx2 = 0;
                for (idx2 = 0; vext->fqan[idx2] != NULL; idx2++)
                {
                    fqan = vext->fqan[idx2];
                    if (char_remaining > 0)
                    {
                        count ++;
                        this_round = snprintf(pos, char_remaining, "%s,", fqan);
                        pos += this_round;
                        char_remaining -= this_round;
                    }
                }
                if (count && char_remaining >= 0) {pos--;}
                if (char_remaining >= 0)
                {
                    *pos = '\n';
                    *(pos+1) = '\0';
                }
                else
                {
                    msg[1023] = '\0';
                    msg[1022] = '\n';
                }
                globus_gfs_log_message(GLOBUS_GFS_LOG_TRANSFER, msg);
            }
        }
        VOMS_Destroy(vdata);
    }

#endif  // VOMS_FOUND

    original_init_function(op, session);
}