/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999-2021 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
. */
/* A "file wicket" implementation */
#ifdef HAVE_CONFIG_H
# include
#endif
#include
#include
#include
#include
#include
#include
#include
#include
struct file_wicket
{
char *filename;
};
static void
_file_wicket_destroy (mu_wicket_t wicket)
{
struct file_wicket *fw = mu_wicket_get_data (wicket);
free (fw->filename);
free (fw);
}
struct file_ticket
{
char *filename;
char *user;
mu_url_t tickurl;
};
static void
file_ticket_destroy (mu_ticket_t ticket)
{
struct file_ticket *ft = mu_ticket_get_data (ticket);
if (ft)
{
free (ft->filename);
free (ft->user);
mu_url_destroy (&ft->tickurl);
free (ft);
}
}
int
file_ticket_get_cred (mu_ticket_t ticket, mu_url_t url, const char *challenge,
char **pplain, mu_secret_t *psec)
{
struct file_ticket *ft = mu_ticket_get_data (ticket);
int rc = 0;
if (!ft->tickurl)
{
rc = mu_wicket_file_match_url (ft->filename, url,
MU_URL_PARSE_ALL,
&ft->tickurl);
if (rc)
return rc;
}
if (pplain)
{
if (ft->user)
{
*pplain = strdup (ft->user);
if (!*pplain)
rc = ENOMEM;
}
else
rc = mu_url_aget_user (ft->tickurl, pplain);
}
else
rc = mu_url_get_secret (ft->tickurl, psec);
return rc;
}
static int
_file_wicket_get_ticket (mu_wicket_t wicket, void *data,
const char *user, mu_ticket_t *pticket)
{
int rc;
mu_ticket_t ticket;
struct file_wicket *fw = data;
struct file_ticket *ft = calloc (1, sizeof (*ft));
ft->filename = strdup (fw->filename);
if (!ft->filename)
{
free (ft);
return ENOMEM;
}
if (user)
{
ft->user = strdup (user);
if (!ft->user)
{
free (ft->filename);
free (ft);
return ENOMEM;
}
}
else
ft->user = NULL;
rc = mu_ticket_create (&ticket, NULL);
if (rc)
{
free (ft->filename);
free (ft->user);
free (ft);
return rc;
}
mu_ticket_set_destroy (ticket, file_ticket_destroy, NULL);
mu_ticket_set_data (ticket, ft, NULL);
mu_ticket_set_get_cred (ticket, file_ticket_get_cred, NULL);
*pticket = ticket;
return 0;
}
int
mu_wicket_stream_match_url (mu_stream_t stream, struct mu_locus_point *loc,
mu_url_t url, int parse_flags,
mu_url_t *pticket_url)
{
int rc;
mu_url_t u = NULL;
char *buf = NULL;
size_t bufsize = 0;
size_t len;
mu_url_t pret = NULL;
int weight = 0;
int line = loc->mu_line;
while ((rc = mu_stream_getline (stream, &buf, &bufsize, &len)) == 0
&& len > 0)
{
char *p;
int err;
int n;
loc->mu_line++;
p = mu_str_stripws (buf);
/* Skip empty lines and comments. */
if (*p == 0 || *p == '#')
continue;
if ((err = mu_url_create_hint (&u, p, parse_flags, NULL)) != 0)
{
/* Skip erroneous entry */
mu_error (_("%s:%u: cannot create URL: %s"),
loc->mu_file, loc->mu_line, mu_strerror (err));
continue;
}
if (!mu_url_has_flag (u, MU_URL_USER|MU_URL_SECRET))
{
mu_error (_("%s:%u: URL is missing required parts"),
loc->mu_file, loc->mu_line);
mu_url_destroy (&u);
continue;
}
if (!mu_url_matches_ticket (u, url, &n))
{
mu_url_destroy (&u);
continue;
}
if (!pret || n < weight)
{
pret = u;
weight = n;
line = loc->mu_line;
if (weight == 0)
break;
}
}
free (buf);
if (rc == 0)
{
if (pret)
{
*pticket_url = pret;
loc->mu_line = line;
}
else
rc = MU_ERR_NOENT;
}
return rc;
}
int
mu_wicket_file_match_url (const char *name, mu_url_t url,
int parse_flags,
mu_url_t *pticket_url)
{
mu_stream_t stream;
int rc;
struct mu_locus_point loc;
rc = mu_file_stream_create (&stream, name, MU_STREAM_READ);
if (rc)
return rc;
loc.mu_file = (char*) name;
loc.mu_line = 0;
loc.mu_col = 0;
rc = mu_wicket_stream_match_url (stream, &loc, url, parse_flags,
pticket_url);
mu_stream_close (stream);
mu_stream_destroy (&stream);
return rc;
}
int
mu_file_wicket_create (mu_wicket_t *pwicket, const char *filename)
{
mu_wicket_t wicket;
int rc;
struct file_wicket *fw = calloc (1, sizeof (*fw));
if (!fw)
return ENOMEM;
fw->filename = strdup (filename);
if (!fw->filename)
{
free (fw);
return ENOMEM;
}
rc = mu_wicket_create (&wicket);
if (rc)
{
free (fw->filename);
free (fw);
return rc;
}
mu_wicket_set_data (wicket, fw);
mu_wicket_set_destroy (wicket, _file_wicket_destroy);
mu_wicket_set_get_ticket (wicket, _file_wicket_get_ticket);
*pwicket = wicket;
return 0;
}