Update mail/spamass-milter to 0.4.0.
Brief summary of changes (taken from upstream release announcement): - -C option to change the default reject code - -S option to specify a path to sendmail (for the -x option) - -R option to specify the rejection message - -a option to skip messages that were authenticated - IPv6 address support - zombie process fix for the - option introduced in 0.3.2 Some of these changes (notably the -R and -a flags and the IPv6 support) were previously included in the port via patch files, which are now unneeded and have been removed.
This commit is contained in:
parent
1beb35f1e7
commit
56ba9de21f
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=371495
6 changed files with 4 additions and 444 deletions
|
@ -2,8 +2,7 @@
|
|||
# $FreeBSD$
|
||||
|
||||
PORTNAME= spamass-milter
|
||||
PORTVERSION= 0.3.2
|
||||
PORTREVISION= 1
|
||||
PORTVERSION= 0.4.0
|
||||
CATEGORIES= mail
|
||||
MASTER_SITES= ${MASTER_SITE_SAVANNAH}
|
||||
MASTER_SITE_SUBDIR= spamass-milt
|
||||
|
@ -17,35 +16,11 @@ RUN_DEPENDS:= ${BUILD_DEPENDS}
|
|||
LICENSE= GPLv2
|
||||
|
||||
|
||||
OPTIONS_DEFINE= ADDAUTH_PATCH REJECTTEXT_PATCH LDAP SENDMAIL_PORT IPV6 DOCS
|
||||
ADDAUTH_PATCH_DESC= Bypass checks for SMTP AUTH connections
|
||||
REJECTTEXT_PATCH_DESC= Customize SMTP reject message
|
||||
OPTIONS_DEFINE= LDAP SENDMAIL_PORT DOCS
|
||||
SENDMAIL_PORT_DESC= Build against sendmail port
|
||||
|
||||
.include <bsd.port.pre.mk>
|
||||
|
||||
ORIG_ARGS= fd:mMp:P:r:u:D:i:b:B:e:x
|
||||
NEW_ARGS:= ${ORIG_ARGS}
|
||||
|
||||
.if ${PORT_OPTIONS:MADDAUTH_PATCH}
|
||||
EXTRA_PATCHES+= ${FILESDIR}/extra-patch-addauth
|
||||
NEW_ARGS:= ${NEW_ARGS}a
|
||||
.endif
|
||||
|
||||
.if ${PORT_OPTIONS:MREJECTTEXT_PATCH}
|
||||
EXTRA_PATCHES+= ${FILESDIR}/extra-patch-rejecttext1
|
||||
NEW_ARGS:= ${NEW_ARGS}R:
|
||||
.endif
|
||||
|
||||
.if ${PORT_OPTIONS:MIPV6}
|
||||
EXTRA_PATCHES+= ${FILESDIR}/extra-patch-ipv6
|
||||
.endif
|
||||
|
||||
# extra-patch-options is modified in pre-patch
|
||||
.if ${ORIG_ARGS} != ${NEW_ARGS}
|
||||
EXTRA_PATCHES+= ${WRKDIR}/extra-patch-options
|
||||
.endif
|
||||
|
||||
.if exists(${LOCALBASE}/lib/libldap.so)
|
||||
WITH_LDAP=yes
|
||||
.undef WITHOUT_LDAP
|
||||
|
@ -66,11 +41,6 @@ GNU_CONFIGURE= yes
|
|||
|
||||
SUB_FILES= pkg-message
|
||||
|
||||
pre-patch:
|
||||
.if ${ORIG_ARGS} != ${NEW_ARGS}
|
||||
@${SED} -e 's|%NEW_ARGS%|${NEW_ARGS}|' ${FILESDIR}/extra-patch-options > ${WRKDIR}/extra-patch-options
|
||||
.endif
|
||||
|
||||
post-patch:
|
||||
@${SED} -e's,%%PREFIX%%,${PREFIX},g' \
|
||||
${FILESDIR}/activation.txt > ${WRKDIR}/activation.txt
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
SHA256 (spamass-milter-0.3.2.tar.gz) = c14b9021092f8c5408df1db25e5645db4cba5bac5ba487175230696a99d269cc
|
||||
SIZE (spamass-milter-0.3.2.tar.gz) = 154579
|
||||
SHA256 (spamass-milter-0.4.0.tar.gz) = 782f1bb3b08a0447cd51ad4b64e7506926739fa9cce537f3cc62aa9b24d46b07
|
||||
SIZE (spamass-milter-0.4.0.tar.gz) = 158646
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
diff -u orig/spamass-milter.1.in spamass-milter.1.in
|
||||
--- orig/spamass-milter.1.in Thu Mar 18 10:37:08 2004
|
||||
+++ spamass-milter.1.in Wed Oct 18 18:06:23 2006
|
||||
@@ -199,6 +199,9 @@
|
||||
Requires the
|
||||
.Fl u
|
||||
flag.
|
||||
+.It Fl a
|
||||
+Causes spamass-milter to pass through unchecked any messages from connections
|
||||
+established using SMTP authentication. This is useful for sites with remote users.
|
||||
.It Fl - Ar spamc flags ...
|
||||
Pass all remaining options to spamc.
|
||||
This allows you to connect to a remote spamd with
|
||||
diff -u orig/spamass-milter.cpp spamass-milter.cpp
|
||||
--- orig/spamass-milter.cpp Thu Mar 23 13:41:36 2006
|
||||
+++ spamass-milter.cpp Wed Oct 18 21:13:25 2006
|
||||
@@ -170,6 +170,7 @@
|
||||
bool flag_full_email = false; /* pass full email address to spamc */
|
||||
bool flag_expand = false; /* alias/virtusertable expansion */
|
||||
bool warnedmacro = false; /* have we logged that we couldn't fetch a macro? */
|
||||
+bool auth = false; /* don't scan authenticated users */
|
||||
|
||||
#if defined(__FreeBSD__) /* popen bug - see PR bin/50770 */
|
||||
static pthread_mutex_t popen_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
@@ -196,6 +197,9 @@
|
||||
/* Process command line options */
|
||||
while ((c = getopt(argc, argv, args)) != -1) {
|
||||
switch (c) {
|
||||
+ case 'a':
|
||||
+ auth = true;
|
||||
+ break;
|
||||
case 'f':
|
||||
dofork = true;
|
||||
break;
|
||||
@@ -281,7 +285,7 @@
|
||||
cout << "SpamAssassin Sendmail Milter Plugin" << endl;
|
||||
cout << "Usage: spamass-milter -p socket [-b|-B bucket] [-d xx[,yy...]] [-D host]" << endl;
|
||||
cout << " [-e defaultdomain] [-f] [-i networks] [-m] [-M]" << endl;
|
||||
- cout << " [-P pidfile] [-r nn] [-u defaultuser] [-x]" << endl;
|
||||
+ cout << " [-P pidfile] [-r nn] [-u defaultuser] [-x] [-a]" << endl;
|
||||
cout << " [-- spamc args ]" << endl;
|
||||
cout << " -p socket: path to create socket" << endl;
|
||||
cout << " -b bucket: redirect spam to this mail address. The orignal" << endl;
|
||||
@@ -302,6 +306,7 @@
|
||||
cout << " -u defaultuser: pass the recipient's username to spamc.\n"
|
||||
" Uses 'defaultuser' if there are multiple recipients." << endl;
|
||||
cout << " -x: pass email address through alias and virtusertable expansion." << endl;
|
||||
+ cout << " -a: don't scan messages over an authenticated connection." << endl;
|
||||
cout << " -- spamc args: pass the remaining flags to spamc." << endl;
|
||||
|
||||
exit(EX_USAGE);
|
||||
@@ -782,6 +787,15 @@
|
||||
return SMFIS_TEMPFAIL;
|
||||
}
|
||||
/* debug(D_ALWAYS, "ZZZ got private context %p", sctx); */
|
||||
+
|
||||
+ if (auth) {
|
||||
+ const char *auth_type = smfi_getsymval(ctx, "{auth_type}");
|
||||
+
|
||||
+ if (auth_type) {
|
||||
+ debug(D_MISC, "auth_type=%s", auth_type);
|
||||
+ return SMFIS_ACCEPT;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
debug(D_FUNC, "mlfi_envfrom: enter");
|
||||
try {
|
||||
|
|
@ -1,270 +0,0 @@
|
|||
diff -ur orig/spamass-milter.cpp spamass-milter.cpp
|
||||
--- orig/spamass-milter.cpp 2010-01-31 11:35:47.000000000 +0000
|
||||
+++ spamass-milter.cpp 2008-01-09 01:20:38.000000000 +0000
|
||||
@@ -88,6 +88,7 @@
|
||||
#include "subst_poll.h"
|
||||
#endif
|
||||
#include <errno.h>
|
||||
+#include <netdb.h>
|
||||
|
||||
// C++ includes
|
||||
#include <cstdio>
|
||||
@@ -721,12 +722,19 @@
|
||||
sctx = (struct context *)malloc(sizeof(*sctx));
|
||||
if (!hostaddr)
|
||||
{
|
||||
+ static struct sockaddr_in localhost;
|
||||
+
|
||||
/* not a socket; probably a local user calling sendmail directly */
|
||||
/* set to 127.0.0.1 */
|
||||
- sctx->connect_ip.s_addr = htonl(INADDR_LOOPBACK);
|
||||
+ strcpy(sctx->connect_ip, "127.0.0.1");
|
||||
+ localhost.sin_family = AF_INET;
|
||||
+ localhost.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
+ hostaddr = (struct sockaddr*) &localhost;
|
||||
} else
|
||||
{
|
||||
- sctx->connect_ip = ((struct sockaddr_in *) hostaddr)->sin_addr;
|
||||
+ getnameinfo(hostaddr, sizeof(struct sockaddr_in6),
|
||||
+ sctx->connect_ip, 63, NULL, 0, NI_NUMERICHOST);
|
||||
+ debug(D_FUNC, "Remote address: %s", sctx->connect_ip);
|
||||
}
|
||||
sctx->assassin = NULL;
|
||||
sctx->helo = NULL;
|
||||
@@ -740,10 +748,12 @@
|
||||
}
|
||||
/* debug(D_ALWAYS, "ZZZ set private context to %p", sctx); */
|
||||
|
||||
- if (ip_in_networklist(sctx->connect_ip, &ignorenets))
|
||||
+ //debug(D_FUNC, "sctx->connect_ip: `%d'", sctx->connect_ip.sin_family);
|
||||
+
|
||||
+ if (ip_in_networklist(hostaddr, &ignorenets))
|
||||
{
|
||||
debug(D_NET, "%s is in our ignore list - accepting message",
|
||||
- inet_ntoa(sctx->connect_ip));
|
||||
+ sctx->connect_ip);
|
||||
debug(D_FUNC, "mlfi_connect: exit ignore");
|
||||
return SMFIS_ACCEPT;
|
||||
}
|
||||
@@ -815,7 +825,7 @@
|
||||
return SMFIS_TEMPFAIL;
|
||||
};
|
||||
|
||||
- assassin->set_connectip(string(inet_ntoa(sctx->connect_ip)));
|
||||
+ assassin->set_connectip(string(sctx->connect_ip));
|
||||
|
||||
// Store a pointer to the assassin object in our context struct
|
||||
sctx->assassin = assassin;
|
||||
@@ -2089,69 +2099,119 @@
|
||||
{
|
||||
char *tnet = strsep(&token, "/");
|
||||
char *tmask = token;
|
||||
- struct in_addr net, mask;
|
||||
+ struct in_addr net;
|
||||
+ struct in6_addr net6;
|
||||
|
||||
if (list->num_nets % 10 == 0)
|
||||
- list->nets = (struct net*)realloc(list->nets, sizeof(*list->nets) * (list->num_nets + 10));
|
||||
+ list->nets = (union net*)realloc(list->nets, sizeof(*list->nets) * (list->num_nets + 10));
|
||||
|
||||
- if (!inet_aton(tnet, &net))
|
||||
+ if (inet_pton(AF_INET, tnet, &net))
|
||||
{
|
||||
- fprintf(stderr, "Could not parse \"%s\" as a network\n", tnet);
|
||||
- exit(1);
|
||||
- }
|
||||
+ struct in_addr mask;
|
||||
+
|
||||
+ if (tmask)
|
||||
+ {
|
||||
+ if (strchr(tmask, '.') == NULL)
|
||||
+ {
|
||||
+ /* CIDR */
|
||||
+ unsigned int bits;
|
||||
+ int ret;
|
||||
+ ret = sscanf(tmask, "%u", &bits);
|
||||
+ if (ret != 1 || bits > 32)
|
||||
+ {
|
||||
+ fprintf(stderr,"%s: bad CIDR value", tmask);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ mask.s_addr = htonl(~((1L << (32 - bits)) - 1) & 0xffffffff);
|
||||
+ } else if (!inet_pton(AF_INET6, tmask, &mask))
|
||||
+ {
|
||||
+ fprintf(stderr, "Could not parse \"%s\" as a netmask\n", tmask);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ } else
|
||||
+ mask.s_addr = 0xffffffff;
|
||||
+
|
||||
+ {
|
||||
+ char *snet = strdup(inet_ntoa(net));
|
||||
+ debug(D_MISC, "Adding %s/%s to network list", snet, inet_ntoa(mask));
|
||||
+ free(snet);
|
||||
+ }
|
||||
|
||||
- if (tmask)
|
||||
+ net.s_addr = net.s_addr & mask.s_addr;
|
||||
+ list->nets[list->num_nets].net4.af = AF_INET;
|
||||
+ list->nets[list->num_nets].net4.network = net;
|
||||
+ list->nets[list->num_nets].net4.netmask = mask;
|
||||
+ list->num_nets++;
|
||||
+ } else if (inet_pton(AF_INET6, tnet, &net6))
|
||||
{
|
||||
- if (strchr(tmask, '.') == NULL)
|
||||
+ int mask;
|
||||
+
|
||||
+ if (tmask)
|
||||
{
|
||||
- /* CIDR */
|
||||
- unsigned int bits;
|
||||
- int ret;
|
||||
- ret = sscanf(tmask, "%u", &bits);
|
||||
- if (ret != 1 || bits > 32)
|
||||
+ if (sscanf(tmask, "%d", &mask) != 1 || mask > 128)
|
||||
{
|
||||
fprintf(stderr,"%s: bad CIDR value", tmask);
|
||||
exit(1);
|
||||
}
|
||||
- mask.s_addr = htonl(~((1L << (32 - bits)) - 1) & 0xffffffff);
|
||||
- } else if (!inet_aton(tmask, &mask))
|
||||
- {
|
||||
- fprintf(stderr, "Could not parse \"%s\" as a netmask\n", tmask);
|
||||
- exit(1);
|
||||
- }
|
||||
+ } else
|
||||
+ mask = 128;
|
||||
+
|
||||
+ list->nets[list->num_nets].net6.af = AF_INET6;
|
||||
+ list->nets[list->num_nets].net6.network = net6;
|
||||
+ list->nets[list->num_nets].net6.netmask = mask;
|
||||
+ list->num_nets++;
|
||||
} else
|
||||
- mask.s_addr = 0xffffffff;
|
||||
-
|
||||
{
|
||||
- char *snet = strdup(inet_ntoa(net));
|
||||
- debug(D_MISC, "Adding %s/%s to network list", snet, inet_ntoa(mask));
|
||||
- free(snet);
|
||||
+ fprintf(stderr, "Could not parse \"%s\" as a network\n", tnet);
|
||||
+ exit(1);
|
||||
}
|
||||
|
||||
- net.s_addr = net.s_addr & mask.s_addr;
|
||||
- list->nets[list->num_nets].network = net;
|
||||
- list->nets[list->num_nets].netmask = mask;
|
||||
- list->num_nets++;
|
||||
}
|
||||
free(string);
|
||||
}
|
||||
|
||||
-int ip_in_networklist(struct in_addr ip, struct networklist *list)
|
||||
+int ip_in_networklist(struct sockaddr *addr, struct networklist *list)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (list->num_nets == 0)
|
||||
return 0;
|
||||
-
|
||||
- debug(D_NET, "Checking %s against:", inet_ntoa(ip));
|
||||
+
|
||||
+ //debug(D_NET, "Checking %s against:", inet_ntoa(ip));
|
||||
for (i = 0; i < list->num_nets; i++)
|
||||
{
|
||||
- debug(D_NET, "%s", inet_ntoa(list->nets[i].network));
|
||||
- debug(D_NET, "/%s", inet_ntoa(list->nets[i].netmask));
|
||||
- if ((ip.s_addr & list->nets[i].netmask.s_addr) == list->nets[i].network.s_addr)
|
||||
- {
|
||||
- debug(D_NET, "Hit!");
|
||||
- return 1;
|
||||
+ if (list->nets[i].net.af == AF_INET && addr->sa_family == AF_INET)
|
||||
+ {
|
||||
+ struct in_addr ip = ((struct sockaddr_in *)addr)->sin_addr;
|
||||
+
|
||||
+ debug(D_NET, "%s", inet_ntoa(list->nets[i].net4.network));
|
||||
+ debug(D_NET, "/%s", inet_ntoa(list->nets[i].net4.netmask));
|
||||
+ if ((ip.s_addr & list->nets[i].net4.netmask.s_addr) == list->nets[i].net4.network.s_addr)
|
||||
+ {
|
||||
+ debug(D_NET, "Hit!");
|
||||
+ return 1;
|
||||
+ }
|
||||
+ } else if (list->nets[i].net.af == AF_INET6 && addr->sa_family == AF_INET6)
|
||||
+ {
|
||||
+ u_int8_t *ip = ((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr;
|
||||
+ int mask, j;
|
||||
+
|
||||
+ mask = list->nets[i].net6.netmask;
|
||||
+ for (j = 0; j < 16 && mask > 0; j++, mask -= 8)
|
||||
+ {
|
||||
+ unsigned char bytemask;
|
||||
+
|
||||
+ bytemask = (mask < 8) ? ~((1L << (8 - mask)) - 1) : 0xff;
|
||||
+
|
||||
+ if ((ip[j] & bytemask) != (list->nets[i].net6.network.s6_addr[j] & bytemask))
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (mask <= 0)
|
||||
+ {
|
||||
+ debug(D_NET, "Hit!");
|
||||
+ return 1;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
diff -ur orig/spamass-milter.h spamass-milter.h
|
||||
--- orig/spamass-milter.h 2006-03-23 22:07:55.000000000 +0000
|
||||
+++ spamass-milter.h 2008-01-01 23:55:44.000000000 +0000
|
||||
@@ -56,16 +56,30 @@
|
||||
extern struct smfiDesc smfilter;
|
||||
|
||||
/* struct describing a single network */
|
||||
-struct net
|
||||
+union net
|
||||
{
|
||||
- struct in_addr network;
|
||||
- struct in_addr netmask;
|
||||
+ struct
|
||||
+ {
|
||||
+ uint8_t af;
|
||||
+ } net;
|
||||
+ struct
|
||||
+ {
|
||||
+ uint8_t af;
|
||||
+ struct in_addr network;
|
||||
+ struct in_addr netmask;
|
||||
+ } net4;
|
||||
+ struct
|
||||
+ {
|
||||
+ uint8_t af;
|
||||
+ struct in6_addr network;
|
||||
+ int netmask; /* Just the number of bits for IPv6 */
|
||||
+ } net6;
|
||||
};
|
||||
|
||||
/* an array of networks */
|
||||
struct networklist
|
||||
{
|
||||
- struct net *nets;
|
||||
+ union net *nets;
|
||||
int num_nets;
|
||||
};
|
||||
|
||||
@@ -165,7 +179,7 @@
|
||||
/* Private data structure to carry per-client data between calls */
|
||||
struct context
|
||||
{
|
||||
- struct in_addr connect_ip; // remote IP address
|
||||
+ char connect_ip[64]; // remote IP address
|
||||
char *helo;
|
||||
SpamAssassin *assassin; // pointer to the SA object if we're processing a message
|
||||
};
|
||||
@@ -182,7 +196,7 @@
|
||||
int cmp_nocase_partial(const string&, const string&);
|
||||
void closeall(int fd);
|
||||
void parse_networklist(char *string, struct networklist *list);
|
||||
-int ip_in_networklist(struct in_addr ip, struct networklist *list);
|
||||
+int ip_in_networklist(struct sockaddr *addr, struct networklist *list);
|
||||
void parse_debuglevel(char* string);
|
||||
char *strlwr(char *str);
|
||||
void warnmacro(char *macro, char *scope);
|
|
@ -1,11 +0,0 @@
|
|||
--- spamass-milter.cpp.ORIG 2006-06-17 11:06:30.000000000 +0200
|
||||
+++ spamass-milter.cpp 2006-06-17 11:10:11.000000000 +0200
|
||||
@@ -181,7 +182,7 @@
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
int c, err = 0;
|
||||
- const char *args = "fd:mMp:P:r:u:D:i:b:B:e:x";
|
||||
+ const char *args = "%NEW_ARGS%";
|
||||
char *sock = NULL;
|
||||
bool dofork = false;
|
||||
char *pidfilename = NULL;
|
|
@ -1,61 +0,0 @@
|
|||
--- spamass-milter.cpp.orig 2006-03-23 16:41:36.000000000 -0500
|
||||
+++ spamass-milter.cpp 2010-01-11 09:32:07.000000000 -0500
|
||||
@@ -161,6 +161,7 @@
|
||||
char *defaultuser; /* Username to send to spamc if there are multiple recipients */
|
||||
char *defaultdomain; /* Domain to append if incoming address has none */
|
||||
char *spamdhost;
|
||||
+char *rejecttext = NULL; /* If we reject a mail, then use this text */
|
||||
struct networklist ignorenets;
|
||||
int spamc_argc;
|
||||
char **spamc_argv;
|
||||
@@ -193,6 +194,11 @@
|
||||
|
||||
openlog("spamass-milter", LOG_PID, LOG_MAIL);
|
||||
|
||||
+
|
||||
+ syslog(LOG_ERR, "argc: %d", argc);
|
||||
+ for (int xy=0; xy<argc; xy++) {
|
||||
+ syslog(LOG_ERR, "argv[%d]: %s", xy, argv[xy]);
|
||||
+ }
|
||||
/* Process command line options */
|
||||
while ((c = getopt(argc, argv, args)) != -1) {
|
||||
switch (c) {
|
||||
@@ -232,6 +238,9 @@
|
||||
flag_reject = true;
|
||||
reject_score = atoi(optarg);
|
||||
break;
|
||||
+ case 'R':
|
||||
+ rejecttext = strdup (optarg);
|
||||
+ break;
|
||||
case 'u':
|
||||
flag_sniffuser = true;
|
||||
defaultuser = strdup(optarg);
|
||||
@@ -299,6 +308,7 @@
|
||||
cout << " -P pidfile: Put processid in pidfile" << endl;
|
||||
cout << " -r nn: reject messages with a score >= nn with an SMTP error.\n"
|
||||
" use -1 to reject any messages tagged by SA." << endl;
|
||||
+ cout << " -R RejectText: using this Reject Text." << endl;
|
||||
cout << " -u defaultuser: pass the recipient's username to spamc.\n"
|
||||
" Uses 'defaultuser' if there are multiple recipients." << endl;
|
||||
cout << " -x: pass email address through alias and virtusertable expansion." << endl;
|
||||
@@ -307,6 +317,11 @@
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
|
||||
+ /* Set standard reject text */
|
||||
+ if (rejecttext == NULL) {
|
||||
+ rejecttext = strdup ("Blocked by SpamAssassin");
|
||||
+ }
|
||||
+
|
||||
if (pidfilename)
|
||||
{
|
||||
unlink(pidfilename);
|
||||
@@ -452,7 +467,7 @@
|
||||
if (do_reject)
|
||||
{
|
||||
debug(D_MISC, "Rejecting");
|
||||
- smfi_setreply(ctx, "550", "5.7.1", "Blocked by SpamAssassin");
|
||||
+ smfi_setreply(ctx, "550", "5.7.1", rejecttext);
|
||||
|
||||
|
||||
if (flag_bucket)
|
Loading…
Reference in a new issue