add mtime support to ftpparse

This commit is contained in:
Mario Fetka 2010-09-18 12:55:05 +02:00
parent 267f5a2964
commit 7c3da640e1
13 changed files with 969 additions and 447 deletions

View File

@ -170,7 +170,7 @@ typedef int boolean;
/* Gettext */ /* Gettext */
#include "gettext.h" #include "gettext.h"
#define _(String) dgettext (PACKAGE, String) #define _(String) dgettext(PACKAGE, String)
/* Gettext */ /* Gettext */

View File

@ -104,6 +104,43 @@ int proz_download_setup_connections_no_ftpsearch(download_t * download,
download->pconnections = kmalloc(sizeof(connection_t *) * num_connections); download->pconnections = kmalloc(sizeof(connection_t *) * num_connections);
download->num_connections = num_connections; download->num_connections = num_connections;
// Compare file size and modification time
char * final_file = kmalloc(PATH_MAX);
struct stat final_stat_buf;
snprintf(final_file, PATH_MAX, "%s/%s", download->dl_dir, connection->u.file);
proz_debug("final file %s", final_file);
if (stat(final_file, &final_stat_buf) == -1)
{
if (errno == ENOENT)
proz_debug("final file does not exist, perfect!");
else
{
proz_debug("something else happened %d", errno);
return -1;
}
}
else // there is such file, compare size and mdate
{
proz_debug("final file exists, check size and mdate");
proz_debug("local file is %lld byte, last mod at %s",
final_stat_buf.st_size, ctime(&(final_stat_buf.st_mtime)));
proz_debug("remotefile is %lld byte, last mod at %s",
connection->main_file_size, ctime(&(connection->u.remote_time)));
// not download again if same mod time and same size
if (final_stat_buf.st_size == connection->main_file_size &&
final_stat_buf.st_mtime == connection->u.remote_time)
{
proz_debug("same file size and modification time, skip this file");
return -2; // -2 will be handler seperately in DL_Window::start_download
}
else
{
proz_debug("file size of mod time differs, go ahead with downloading");
}
}
kfree(final_file);
// end of new code
out_file = kmalloc(PATH_MAX); out_file = kmalloc(PATH_MAX);
snprintf(out_file, PATH_MAX, "%s/%s.prozilla", snprintf(out_file, PATH_MAX, "%s/%s.prozilla",
download->dl_dir, connection->u.file); download->dl_dir, connection->u.file);

View File

@ -1111,23 +1111,36 @@ uerr_t proz_ftp_get_url_info(connection_t * connection)
close_sock(&connection->ctrl_sock); close_sock(&connection->ctrl_sock);
// size_rt = size_returner(buffer, strlen(buffer)); // size_rt = size_returner(buffer, strlen(buffer));
err = ftp_parse(&fp, buffer, strlen(buffer)); // use old ftpparse
// err =ftp_parse(&fp, buffer, strlen(buffer));
int parse_ret;
parse_ret = ftpparse(&fp, buffer, strlen(buffer));
if (parse_ret == 1)
err = FTPPARSEOK;
else
err = FTPPARSEFAIL;
// end of use old ftpparse
if (err != FTPPARSEOK) if (err != FTPPARSEOK)
{ {
connection_show_message(connection, connection_show_message(connection,
_ _("Unable to parse the line the FTP server returned:please report URL to prozilla-dev@disconnected-by-peer.at "));
("Unable to parse the line the FTP server returned:please report URL to prozilla-dev@disconnected-by-peer.at "));
} }
if (err == FTPPARSEOK) if (err == FTPPARSEOK)
{ {
proz_debug("size returned from LIST %ld", fp.filesize); // use old ftpparse
//proz_debug("size returned from LIST %ld", fp.filesize);
proz_debug("size returned from LIST %ld", fp.size);
//SEC size_rt off_t? //SEC size_rt off_t?
if (size_ok == FALSE) //if (size_ok == FALSE)
{ //{
proz_debug("SIZE failed, setting file size based on LIST"); //proz_debug("SIZE failed, setting file size based on LIST");
connection->main_file_size = fp.filesize; //connection->main_file_size = fp.filesize;
} connection->main_file_size = fp.size;
//}
// set the mtime, only obtainable using ftpparse.c from prozilla-1.3.x
connection->u.remote_time = fp.mtime;
// end of Chen Pengs code
} }
return FTPOK; return FTPOK;
} }

View File

@ -1,161 +1,381 @@
/****************************************************************************** /* ftpparse.c, ftpparse.h: library for parsing FTP LIST responses
libprozilla - a download accelerator library D. J. Bernstein, djb@pobox.com
Copyright (C) 2001 Kalum Somaratna 19970712 (doc updated 19970810)
Commercial use is fine, if you let me know what programs you're using this in.
This program is free software; you can redistribute it and/or modify Currently covered:
it under the terms of the GNU General Public License as published by EPLF.
the Free Software Foundation; either version 2 of the License, or UNIX ls, with or without gid.
(at your option) any later version. Microsoft FTP Service.
Windows NT FTP Server.
VMS.
WFTPD (DOS).
NetPresenz (Mac).
NetWare.
This program is distributed in the hope that it will be useful, Definitely not covered:
but WITHOUT ANY WARRANTY; without even the implied warranty of Long VMS filenames, with information split across two lines.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the NCSA Telnet FTP server. Has LIST = NLST (and bad NLST for directories).
GNU General Public License for more details.
You should have received a copy of the GNU General Public License Written for maximum portability, but tested only under UNIX so far.
along with this program; if not, write to the Free Software */
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
******************************************************************************/
//Rewrite of the ftp parsing code as we needed to extract the date of #ifdef HAVE_CONFIG_H
//the file to save it when the downloading is complete. #include <config.h>
#endif /*
* HAVE_CONFIG_H
*/
#include <sys/types.h>
#include "common.h" #include <time.h>
#include "ftpparse.h" #include "ftpparse.h"
#include "prozilla.h"
static long totai(year, month, mday)
long year;
long month;
long mday;
{
/*
* adapted from datetime_untai()
*/
/*
* about 100x faster than typical mktime()
*/
long result;
if (month >= 2)
month -= 2;
else
{
month += 10;
--year;
}
result = (mday - 1) * 10 + 5 + 306 * month;
result /= 10;
if (result == 365)
{
year -= 3;
result = 1460;
}
else
result += 365 * (year % 4);
year /= 4;
result += 1461 * (year % 25);
year /= 25;
if (result == 36524)
{
year -= 3;
result = 146096;
}
else
{
result += 36524 * (year % 4);
}
year /= 4;
result += 146097 * (year - 5);
result += 11017;
return result * 86400;
}
static int flagneedbase = 1;
static time_t base; /*
* time() value on this OS at the beginning of 1970 TAI
*/
static long now; /*
* current time
*/
static int flagneedcurrentyear = 1;
static long currentyear; /*
* approximation to current year
*/
static void initbase()
{
struct tm *t;
/* MultiNet (some spaces removed from examples) */ if (!flagneedbase)
/* "00README.TXT;1 2 30-DEC-1996 17:44 [SYSTEM] (RWED,RWED,RE,RE)" */ return;
/* "CORE.DIR;1 1 8-SEP-1996 16:09 [SYSTEM] (RWE,RWE,RE,RE)" */
/* and non-MutliNet VMS: */
/* "CII-MANUAL.TEX;1 213/216 29-JAN-1996 03:33:12 [ANONYMOU,ANONYMOUS] (RWED,RWED,,)" */
/* MSDOS format */ base = 0;
/* 04-27-00 09:09PM <DIR> licensed */ t = gmtime(&base);
/* 07-18-00 10:16AM <DIR> pub */ base =
/* 04-14-00 03:47PM 589 readme.htm */ -(totai(t->tm_year + 1900, t->tm_mon, t->tm_mday) +
t->tm_hour * 3600 + t->tm_min * 60 + t->tm_sec);
/*
* time_t is assumed to be measured in TAI seconds.
*/
/*
* base may be slightly off if time_t is measured in UTC seconds.
*/
/*
* Typical software naively claims to use UTC but actually uses TAI.
*/
flagneedbase = 0;
}
static void initnow()
{
long day;
long year;
initbase();
now = time((time_t *)0) - base;
long getlong(char *buf, int len) if (flagneedcurrentyear)
{
/*
* adapted from datetime_tai()
*/
day = now / 86400;
if ((now % 86400) < 0)
--day;
day -= 11017;
year = 5 + day / 146097;
day = day % 146097;
if (day < 0)
{
day += 146097;
--year;
}
year *= 4;
if (day == 146096)
{
year += 3;
day = 36524;
}
else
{
year += day / 36524;
day %= 36524;
}
year *= 25;
year += day / 1461;
day %= 1461;
year *= 4;
if (day == 1460)
{
year += 3;
day = 365;
}
else
{
year += day / 365;
day %= 365;
}
day *= 10;
if ((day + 5) / 306 >= 10)
++year;
currentyear = year;
flagneedcurrentyear = 0;
}
}
/* UNIX ls does not show the year for dates in the last six months. */
/* So we have to guess the year. */
/* Apparently NetWare uses ``twelve months'' instead of ``six months''; ugh. */
/* Some versions of ls also fail to show the year for future dates. */
static long guesstai(month, mday)
long month;
long mday;
{
long year;
long t;
initnow();
for (year = currentyear - 1; year < currentyear + 100; ++year)
{
t = totai(year, month, mday);
if (now - t < 350 * 86400)
return t;
}
/* Added by Grendel */
return 0;
}
static int check(buf, monthname)
char *buf;
char *monthname;
{
if ((buf[0] != monthname[0]) && (buf[0] != monthname[0] - 32))
return 0;
if ((buf[1] != monthname[1]) && (buf[1] != monthname[1] - 32))
return 0;
if ((buf[2] != monthname[2]) && (buf[2] != monthname[2] - 32))
return 0;
return 1;
}
static char *months[12] = {
"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct",
"nov", "dec"
};
static int getmonth(buf, len)
char *buf;
int len;
{
int i;
if (len == 3)
for (i = 0; i < 12; ++i)
if (check(buf, months[i]))
return i;
return -1;
}
static long getlong(buf, len)
char *buf;
int len;
{ {
long u = 0; long u = 0;
while (len-- > 0) while (len-- > 0)
u = u * 10 + (*buf++ - '0'); u = u * 10 + (*buf++ - '0');
return u; return u;
} }
static long long getlonglong(buf, len)
/* Find next Field char *buf;
** --------------- int len;
** Finds the next RFC822 token in a string
** On entry,
** *pstr points to a string containing a word separated
** by white white space "," ";" or "=". The word
** can optionally be quoted using <"> or "<" ">"
** Comments surrrounded by '(' ')' are filtered out
**
** On exit,
** *pstr has been moved to the first delimiter past the
** field
** THE STRING HAS BEEN MUTILATED by a 0 terminator
**
** Returns a pointer to the first word or NULL on error
*/
char * get_nextfield(char ** pstr)
{ {
char * p = *pstr; long long u = 0;
while (len-- > 0)
char * start = NULL; u = u * 10 + (*buf++ - '0');
return u;
if (!pstr || !*pstr)
return NULL;
while (1)
{
/* Strip white space and other delimiters */
while (*p && (isspace((int)*p) || *p == ',' || *p == ';' || *p == '='))
p++;
if (!*p)
{
*pstr = p;
return NULL; /* No field */
}
if (*p == '"') /* quoted field */
{
start = ++p;
for (; *p && *p != '"'; p++)
if (*p == '\\' && *(p + 1))
p++;
/* Skip escaped chars */
break; /* kr95-10-9: needs to stop here */
}
else if (*p == '<') /* quoted field */
{
start = ++p;
for (; *p && *p != '>'; p++)
if (*p == '\\' && *(p + 1))
p++;
/* Skip escaped chars */
break; /* kr95-10-9: needs to stop here */
}
else if (*p == '(') /* Comment */
{
for (; *p && *p != ')'; p++)
if (*p == '\\' && *(p + 1))
p++;
/* Skip escaped chars */
p++;
}
else /* Spool field */
{
start = p;
while (*p && !isspace((int)*p) && *p != ',' && *p != ';' && *p != '=')
p++;
break; /* Got it */
}
}
if (*p)
*p++ = '\0';
*pstr = p;
return start;
} }
int ftpparse(fp, buf, len)
struct ftpparse *fp;
uerr_t ftp_parse(ftpparse *fp, char *buf, int len) char *buf;
int len;
{ {
char *cp;
char *token;
char *ptr;
char *date;
int i; int i;
int j;
int state;
off_t size = -1;
long year;
long month = -1;
long mday = -1;
long hour;
long minute;
fp->filename = 0; fp->name = 0;
fp->namelen = 0; fp->namelen = 0;
// fp->flagtrycwd = 0; fp->flagtrycwd = 0;
// fp->flagtryretr = 0; fp->flagtryretr = 0;
//fp->sizetype = FTPPARSE_SIZE_UNKNOWN; fp->sizetype = FTPPARSE_SIZE_UNKNOWN;
fp->filesize = 0; fp->size = 0;
// fp->mtimetype = FTPPARSE_MTIME_UNKNOWN; fp->mtimetype = FTPPARSE_MTIME_UNKNOWN;
fp->mtime = 0; fp->mtime = 0;
// fp->idtype = FTPPARSE_ID_UNKNOWN; fp->idtype = FTPPARSE_ID_UNKNOWN;
fp->id = 0; fp->id = 0;
// fp->idlen = 0; fp->idlen = 0;
proz_debug("FTP LIST to be parsed is %s", cp = strdup(buf)); if (len < 2) /*
free(cp); * an empty name in EPLF, with no info, could be 2 chars
*/
if (len < 2) /* an empty name in EPLF, with no info, could be 2 chars */ return 0;
return FTPPARSENOTEXIST;
switch (*buf) switch (*buf)
{ {
/*
* see http://pobox.com/~djb/proto/eplf.txt
*/
/*
* "+i8388621.29609,m824255902,/,\tdev"
*/
/*
* "+i8388621.44468,m839956783,r,s10376,\tRFCEPLF"
*/
case '+':
i = 1;
for (j = 1; j < len; ++j)
{
if (buf[j] == 9)
{
fp->name = buf + j + 1;
fp->namelen = len - j - 1;
return 1;
}
if (buf[j] == ',')
{
switch (buf[i])
{
case '/':
fp->flagtrycwd = 1;
break;
case 'r':
fp->flagtryretr = 1;
break;
case 's':
fp->sizetype = FTPPARSE_SIZE_BINARY;
fp->size = getlonglong(buf + i + 1, j - i - 1);
break;
case 'm':
fp->mtimetype = FTPPARSE_MTIME_LOCAL;
initbase();
fp->mtime = base + getlong(buf + i + 1, j - i - 1);
break;
case 'i':
fp->idtype = FTPPARSE_ID_FULL;
fp->id = buf + i + 1;
fp->idlen = j - i - 1;
}
i = j + 1;
}
}
return 0;
/*
* UNIX-style listing, without inum and without blocks
*/
/*
* "-rw-r--r-- 1 root other 531 Jan 29 03:26 README"
*/
/*
* "dr-xr-xr-x 2 root other 512 Apr 8 1994 etc"
*/
/*
* "dr-xr-xr-x 2 root 512 Apr 8 1994 etc"
*/
/*
* "lrwxrwxrwx 1 root other 7 Jan 25 00:17 bin -> usr/bin"
*/
/*
* Also produced by Microsoft's FTP servers for Windows:
*/
/*
* "---------- 1 owner group 1803128 Jul 10 10:18 ls-lR.Z"
*/
/*
* "d--------- 1 owner group 0 May 9 19:45 Softlib"
*/
/*
* Also WFTPD for MSDOS:
*/
/*
* "-rwxrwxrwx 1 noone nogroup 322 Aug 19 1996 message.ftp"
*/
/*
* Also NetWare:
*/
/*
* "d [R----F--] supervisor 512 Jan 16 18:53 login"
*/
/*
* "- [R----F--] rhesus 214059 Oct 20 15:27 cx.exe"
*/
/*
* Also NetPresenz for the Mac:
*/
/*
* "-------r-- 326 1391972 1392298 Nov 22 1995 MegaPhone.sit"
*/
/*
* "drwxrwxr-x folder 2 May 10 1996 network"
*/
case 'b': case 'b':
case 'c': case 'c':
case 'd': case 'd':
@ -163,88 +383,257 @@ uerr_t ftp_parse(ftpparse *fp, char *buf, int len)
case 'p': case 'p':
case 's': case 's':
case '-': case '-':
/* UNIX-style listing, without inum and without blocks */
/* "-rw-r--r-- 1 root other 531 Jan 29 03:26 README" */
/* "dr-xr-xr-x 2 root other 512 Apr 8 1994 etc" */
/* "dr-xr-xr-x 2 root 512 Apr 8 1994 etc" */
/* "lrwxrwxrwx 1 root other 7 Jan 25 00:17 bin -> usr/bin" */
/* Also produced by Microsoft's FTP servers for Windows: */
/* "---------- 1 owner group 1803128 Jul 10 10:18 ls-lR.Z" */
/* "d--------- 1 owner group 0 May 9 19:45 Softlib" */
/* Also WFTPD for MSDOS: */
/* "-rwxrwxrwx 1 noone nogroup 322 Aug 19 1996 message.ftp" */
/* Also NetWare: */
/* "d [R----F--] supervisor 512 Jan 16 18:53 login" */
/* "- [R----F--] rhesus 214059 Oct 20 15:27 cx.exe" */
/* Also NetPresenz for the Mac: */
/* "-------r-- 326 1391972 1392298 Nov 22 1995 MegaPhone.sit" */
/* "drwxrwxr-x folder 2 May 10 1996 network"
*/
if (*buf == 'd') if (*buf == 'd')
fp->filetype = DIRECTORY; fp->flagtrycwd = 1;
if (*buf == '-') if (*buf == '-')
fp->filetype = DIRECTORY; fp->flagtryretr = 1;
if (*buf == 'l') if (*buf == 'l')
fp->filetype = SYMBOLIC_LINK; fp->flagtrycwd = fp->flagtryretr = 1;
ptr = cp = strdup(buf);
for (i = 0; i < 4; i++) state = 1;
i = 0;
for (j = 1; j < len; ++j)
if ((buf[j] == ' ') && (buf[j - 1] != ' '))
{ {
//add checking switch (state)
token = get_nextfield(&cp); {
if (token == NULL) //failed to parse case 1: /*
return FTPPARSEFAIL; * skipping perm
}
/*
** This field can either be group or size. We find out by looking at the
** next field. If this is a non-digit then this field is the size.
*/ */
while (*cp && isspace((int)*cp)) state = 2;
cp++; break;
if (isdigit((int)*cp))
case 2: /*
* skipping nlink
*/
state = 3;
if ((j - i == 6) && (buf[i] == 'f')) /*
* for NetPresenz
*/
state = 4;
break;
case 3: /*
* skipping uid
*/
state = 4;
break;
case 4: /*
* getting tentative size
*/
size = getlonglong(buf + i, j - i);
state = 5;
break;
case 5: /*
* searching for month, otherwise getting tentative size
*/
month = getmonth(buf + i, j - i);
if (month >= 0)
state = 6;
else
size = getlonglong(buf + i, j - i);
break;
case 6: /*
* have size and month
*/
mday = getlong(buf + i, j - i);
state = 7;
break;
case 7: /*
* have size, month, mday
*/
if ((j - i == 4) && (buf[i + 1] == ':'))
{ {
token = get_nextfield(&cp); hour = getlong(buf + i, 1);
while (*cp && isspace((int)*cp)) minute = getlong(buf + i + 2, 2);
cp++; fp->mtimetype = FTPPARSE_MTIME_REMOTEMINUTE;
initbase();
fp->mtime =
base + guesstai(month,
mday) + hour * 3600 +
minute * 60;
} }
//if it is a filename else if ((j - i == 5) && (buf[i + 2] == ':'))
fp->filesize = strtol(token, NULL, 10); {
proz_debug("FTP file size is %ld", fp->filesize); hour = getlong(buf + i, 2);
minute = getlong(buf + i + 3, 2);
fp->mtimetype = FTPPARSE_MTIME_REMOTEMINUTE;
while (*cp && isspace((int)*cp)) initbase();
cp++; fp->mtime =
assert(cp + 12 < ptr + len); base + guesstai(month,
date = cp; mday) + hour * 3600 +
cp += 12; minute * 60;
*cp++ = '\0';
fp->date_str = strdup(date);
proz_debug("LIST date is %s", fp->date_str);
return FTPPARSEOK;
default:
return FTPPARSEFAIL;
} }
} else if (j - i >= 4)
{
year = getlong(buf + i, j - i);
fp->mtimetype = FTPPARSE_MTIME_REMOTEDAY;
initbase();
fp->mtime = base + totai(year, month, mday);
}
else
return 0;
fp->name = buf + j + 1;
fp->namelen = len - j - 1;
state = 8;
break;
case 8: /*
* twiddling thumbs
*/
break;
}
i = j + 1;
while ((i < len) && (buf[i] == ' '))
++i;
}
if (state != 8)
time_t parse_time(const char * str)
{
char * p;
struct tm tm;
time_t t;
if (!str)
return 0; return 0;
if ((p = strchr(str, ','))) fp->size = size;
fp->sizetype = FTPPARSE_SIZE_ASCII;
if (*buf == 'l')
for (i = 0; i + 3 < fp->namelen; ++i)
if (fp->name[i] == ' ')
if (fp->name[i + 1] == '-')
if (fp->name[i + 2] == '>')
if (fp->name[i + 3] == ' ')
{ {
fp->namelen = i;
break;
} }
/*
* eliminate extra NetWare spaces
*/
if ((buf[1] == ' ') || (buf[1] == '['))
if (fp->namelen > 3)
if (fp->name[0] == ' ')
if (fp->name[1] == ' ')
if (fp->name[2] == ' ')
{
fp->name += 3;
fp->namelen -= 3;
}
return 1;
}
/*
* MultiNet (some spaces removed from examples)
*/
/*
* "00README.TXT;1 2 30-DEC-1996 17:44 [SYSTEM] (RWED,RWED,RE,RE)"
*/
/*
* "CORE.DIR;1 1 8-SEP-1996 16:09 [SYSTEM] (RWE,RWE,RE,RE)"
*/
/*
* and non-MutliNet VMS:
*/
/*
* "CII-MANUAL.TEX;1 213/216 29-JAN-1996 03:33:12 [ANONYMOU,ANONYMOUS] (RWED,RWED,,)"
*/
for (i = 0; i < len; ++i)
if (buf[i] == ';')
break;
if (i < len)
{
fp->name = buf;
fp->namelen = i;
if (i > 4)
if (buf[i - 4] == '.')
if (buf[i - 3] == 'D')
if (buf[i - 2] == 'I')
if (buf[i - 1] == 'R')
{
fp->namelen -= 4;
fp->flagtrycwd = 1;
}
if (!fp->flagtrycwd)
fp->flagtryretr = 1;
while (buf[i] != ' ')
if (++i == len)
return 0;
while (buf[i] == ' ')
if (++i == len)
return 0;
while (buf[i] != ' ')
if (++i == len)
return 0;
while (buf[i] == ' ')
if (++i == len)
return 0;
j = i;
while (buf[j] != '-')
if (++j == len)
return 0;
mday = getlong(buf + i, j - i);
while (buf[j] == '-')
if (++j == len)
return 0;
i = j;
while (buf[j] != '-')
if (++j == len)
return 0;
month = getmonth(buf + i, j - i);
if (month < 0)
return 0;
while (buf[j] == '-')
if (++j == len)
return 0;
i = j;
while (buf[j] != ' ')
if (++j == len)
return 0;
year = getlong(buf + i, j - i);
while (buf[j] == ' ')
if (++j == len)
return 0;
i = j;
while (buf[j] != ':')
if (++j == len)
return 0;
hour = getlong(buf + i, j - i);
while (buf[j] == ':')
if (++j == len)
return 0;
i = j;
while ((buf[j] != ':') && (buf[j] != ' '))
if (++j == len)
return 0;
minute = getlong(buf + i, j - i);
fp->mtimetype = FTPPARSE_MTIME_REMOTEMINUTE;
initbase();
fp->mtime =
base + totai(year, month, mday) + hour * 3600 + minute * 60;
return 1;
}
/*
* Some useless lines, safely ignored:
*/
/*
* "Total of 11 Files, 10966 Blocks." (VMS)
*/
/*
* "total 14786" (UNIX)
*/
/*
* "DISK$ANONFTP:[ANONYMOUS]" (VMS)
*/
/*
* "Directory DISK$PCSA:[ANONYM]" (VMS)
*/
return 0; return 0;
} }

View File

@ -1,53 +1,75 @@
/******************************************************************************
libprozilla - a download accelerator library
Copyright (C) 2001 Kalum Somaratna
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
******************************************************************************/
/* FTP LIST command parsing code. */
/* $Id$ */
#ifndef FTPPARSE_H #ifndef FTPPARSE_H
#define FTPPARSE_H #define FTPPARSE_H
/*
ftpparse(&fp,buf,len) tries to parse one line of LIST output.
#include "common.h" The line is an array of len characters stored in buf.
#include "prozilla.h" It should not include the terminating CR LF; so buf[len] is typically CR.
#ifdef __cplusplus
extern "C" {
#endif
If ftpparse() can't find a filename, it returns 0.
typedef struct ftpparse { If ftpparse() can find a filename, it fills in fp and returns 1.
char *filename; fp is a struct ftpparse, defined below.
The name is an array of fp.namelen characters stored in fp.name;
fp.name points somewhere within buf.
*/
struct ftpparse {
char *name; /*
* not necessarily 0-terminated
*/
int namelen; int namelen;
off_t filesize; /* number of octets */ int flagtrycwd; /*
// int mtimetype; * 0 if cwd is definitely pointless, 1 otherwise
time_t mtime; /* modification time */ */
file_type_t filetype; int flagtryretr; /*
char *id; /* not necessarily 0-terminated */ * 0 if retr is definitely pointless, 1 otherwise
char *date_str; */
}ftpparse; int sizetype;
off_t size; /*
* number of octets
*/
int mtimetype;
time_t mtime; /*
* modification time
*/
int idtype;
char *id; /*
* not necessarily 0-terminated
*/
int idlen;
};
#define FTPPARSE_SIZE_UNKNOWN 0
#define FTPPARSE_SIZE_BINARY 1 /*
* size is the number of octets in TYPE I
*/
#define FTPPARSE_SIZE_ASCII 2 /*
* size is the number of octets in TYPE A
*/
uerr_t ftp_parse(ftpparse *fp, char *buf, int len); #define FTPPARSE_MTIME_UNKNOWN 0
#define FTPPARSE_MTIME_LOCAL 1 /*
* time is correct
*/
#define FTPPARSE_MTIME_REMOTEMINUTE 2 /*
* time zone and secs are unknown
*/
#define FTPPARSE_MTIME_REMOTEDAY 3 /*
* time zone and time of day are unknown
*/
/*
When a time zone is unknown, it is assumed to be GMT. You may want
to use localtime() for LOCAL times, along with an indication that the
time is correct in the local time zone, and gmtime() for REMOTE* times.
*/
#define FTPPARSE_ID_UNKNOWN 0
#define FTPPARSE_ID_FULL 1 /*
* unique identifier for files on this FTP server
*/
extern int ftpparse();
#ifdef __cplusplus
}
#endif #endif
#endif /* FTPPARSE_H */

View File

@ -31,10 +31,10 @@
# ifdef DEFAULT_TEXT_DOMAIN # ifdef DEFAULT_TEXT_DOMAIN
# undef gettext # undef gettext
# define gettext(Msgid) \ # define gettext(Msgid) \
dgettext (DEFAULT_TEXT_DOMAIN, Msgid) dgettext(DEFAULT_TEXT_DOMAIN, Msgid)
# undef ngettext # undef ngettext
# define ngettext(Msgid1, Msgid2, N) \ # define ngettext(Msgid1, Msgid2, N) \
dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N) dngettext(DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
# endif # endif
#else #else
@ -65,31 +65,31 @@
On pre-ANSI systems without 'const', the config.h file is supposed to On pre-ANSI systems without 'const', the config.h file is supposed to
contain "#define const". */ contain "#define const". */
# undef gettext # undef gettext
# define gettext(Msgid) ((const char *) (Msgid)) # define gettext(Msgid) ((const char *)(Msgid))
# undef dgettext # undef dgettext
# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) # define dgettext(Domainname, Msgid) ((void)(Domainname), gettext(Msgid))
# undef dcgettext # undef dcgettext
# define dcgettext(Domainname, Msgid, Category) \ # define dcgettext(Domainname, Msgid, Category) \
((void) (Category), dgettext (Domainname, Msgid)) ((void)(Category), dgettext(Domainname, Msgid))
# undef ngettext # undef ngettext
# define ngettext(Msgid1, Msgid2, N) \ # define ngettext(Msgid1, Msgid2, N) \
((N) == 1 \ ((N) == 1 \
? ((void) (Msgid2), (const char *) (Msgid1)) \ ? ((void)(Msgid2), (const char *)(Msgid1)) \
: ((void) (Msgid1), (const char *) (Msgid2))) : ((void)(Msgid1), (const char *)(Msgid2)))
# undef dngettext # undef dngettext
# define dngettext(Domainname, Msgid1, Msgid2, N) \ # define dngettext(Domainname, Msgid1, Msgid2, N) \
((void) (Domainname), ngettext (Msgid1, Msgid2, N)) ((void)(Domainname), ngettext(Msgid1, Msgid2, N))
# undef dcngettext # undef dcngettext
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N)) ((void)(Category), dngettext(Domainname, Msgid1, Msgid2, N))
# undef textdomain # undef textdomain
# define textdomain(Domainname) ((const char *) (Domainname)) # define textdomain(Domainname) ((const char *)(Domainname))
# undef bindtextdomain # undef bindtextdomain
# define bindtextdomain(Domainname, Dirname) \ # define bindtextdomain(Domainname, Dirname) \
((void) (Domainname), (const char *) (Dirname)) ((void)(Domainname), (const char *)(Dirname))
# undef bind_textdomain_codeset # undef bind_textdomain_codeset
# define bind_textdomain_codeset(Domainname, Codeset) \ # define bind_textdomain_codeset(Domainname, Codeset) \
((void) (Domainname), (const char *) (Codeset)) ((void)(Domainname), (const char *)(Codeset))
#endif #endif
@ -111,26 +111,26 @@
The letter 'p' stands for 'particular' or 'special'. */ The letter 'p' stands for 'particular' or 'special'. */
#ifdef DEFAULT_TEXT_DOMAIN #ifdef DEFAULT_TEXT_DOMAIN
# define pgettext(Msgctxt, Msgid) \ # define pgettext(Msgctxt, Msgid) \
pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) pgettext_aux(DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
#else #else
# define pgettext(Msgctxt, Msgid) \ # define pgettext(Msgctxt, Msgid) \
pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) pgettext_aux(NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
#endif #endif
#define dpgettext(Domainname, Msgctxt, Msgid) \ #define dpgettext(Domainname, Msgctxt, Msgid) \
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) pgettext_aux(Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \ #define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category) pgettext_aux(Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
#ifdef DEFAULT_TEXT_DOMAIN #ifdef DEFAULT_TEXT_DOMAIN
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) npgettext_aux(DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
#else #else
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) npgettext_aux(NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
#endif #endif
#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ #define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) npgettext_aux(Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \ #define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category) npgettext_aux(Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
#ifdef __GNUC__ #ifdef __GNUC__
__inline __inline
@ -140,11 +140,12 @@ inline
#endif #endif
#endif #endif
static const char * static const char *
pgettext_aux (const char *domain, pgettext_aux(const char *domain,
const char *msg_ctxt_id, const char *msgid, const char *msg_ctxt_id, const char *msgid,
int category) int category)
{ {
const char *translation = dcgettext (domain, msg_ctxt_id, category); const char *translation = dcgettext(domain, msg_ctxt_id, category);
if (translation == msg_ctxt_id) if (translation == msg_ctxt_id)
return msgid; return msgid;
else else
@ -159,15 +160,16 @@ inline
#endif #endif
#endif #endif
static const char * static const char *
npgettext_aux (const char *domain, npgettext_aux(const char *domain,
const char *msg_ctxt_id, const char *msgid, const char *msg_ctxt_id, const char *msgid,
const char *msgid_plural, unsigned long int n, const char *msgid_plural, unsigned long int n,
int category) int category)
{ {
const char *translation = const char *translation =
dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); dcngettext(domain, msg_ctxt_id, msgid_plural, n, category);
if (translation == msg_ctxt_id || translation == msgid_plural) if (translation == msg_ctxt_id || translation == msgid_plural)
return (n == 1 ? msgid : msgid_plural); return(n == 1 ? msgid : msgid_plural);
else else
return translation; return translation;
} }
@ -180,16 +182,16 @@ npgettext_aux (const char *domain,
#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \ #define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \
(((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \ (((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \
/* || __STDC_VERSION__ >= 199901L */ ) /* || __STDC_VERSION__ >= 199901L */)
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
#include <stdlib.h> #include <stdlib.h>
#endif #endif
#define pgettext_expr(Msgctxt, Msgid) \ #define pgettext_expr(Msgctxt, Msgid) \
dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES) dcpgettext_expr(NULL, Msgctxt, Msgid, LC_MESSAGES)
#define dpgettext_expr(Domainname, Msgctxt, Msgid) \ #define dpgettext_expr(Domainname, Msgctxt, Msgid) \
dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES) dcpgettext_expr(Domainname, Msgctxt, Msgid, LC_MESSAGES)
#ifdef __GNUC__ #ifdef __GNUC__
__inline __inline
@ -199,31 +201,32 @@ inline
#endif #endif
#endif #endif
static const char * static const char *
dcpgettext_expr (const char *domain, dcpgettext_expr(const char *domain,
const char *msgctxt, const char *msgid, const char *msgctxt, const char *msgid,
int category) int category)
{ {
size_t msgctxt_len = strlen (msgctxt) + 1; size_t msgctxt_len = strlen(msgctxt) + 1;
size_t msgid_len = strlen (msgid) + 1; size_t msgid_len = strlen(msgid) + 1;
const char *translation; const char *translation;
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
char msg_ctxt_id[msgctxt_len + msgid_len]; char msg_ctxt_id[msgctxt_len + msgid_len];
#else #else
char buf[1024]; char buf[1024];
char *msg_ctxt_id = char *msg_ctxt_id =
(msgctxt_len + msgid_len <= sizeof (buf) (msgctxt_len + msgid_len <= sizeof(buf)
? buf ? buf
: (char *) malloc (msgctxt_len + msgid_len)); : (char *)malloc(msgctxt_len + msgid_len));
if (msg_ctxt_id != NULL) if (msg_ctxt_id != NULL)
#endif #endif
{ {
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); memcpy(msg_ctxt_id, msgctxt, msgctxt_len - 1);
msg_ctxt_id[msgctxt_len - 1] = '\004'; msg_ctxt_id[msgctxt_len - 1] = '\004';
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); memcpy(msg_ctxt_id + msgctxt_len, msgid, msgid_len);
translation = dcgettext (domain, msg_ctxt_id, category); translation = dcgettext(domain, msg_ctxt_id, category);
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
if (msg_ctxt_id != buf) if (msg_ctxt_id != buf)
free (msg_ctxt_id); free(msg_ctxt_id);
#endif #endif
if (translation != msg_ctxt_id) if (translation != msg_ctxt_id)
return translation; return translation;
@ -232,9 +235,9 @@ dcpgettext_expr (const char *domain,
} }
#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \ #define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) dcnpgettext_expr(NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ #define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) dcnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
#ifdef __GNUC__ #ifdef __GNUC__
__inline __inline
@ -244,37 +247,38 @@ inline
#endif #endif
#endif #endif
static const char * static const char *
dcnpgettext_expr (const char *domain, dcnpgettext_expr(const char *domain,
const char *msgctxt, const char *msgid, const char *msgctxt, const char *msgid,
const char *msgid_plural, unsigned long int n, const char *msgid_plural, unsigned long int n,
int category) int category)
{ {
size_t msgctxt_len = strlen (msgctxt) + 1; size_t msgctxt_len = strlen(msgctxt) + 1;
size_t msgid_len = strlen (msgid) + 1; size_t msgid_len = strlen(msgid) + 1;
const char *translation; const char *translation;
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
char msg_ctxt_id[msgctxt_len + msgid_len]; char msg_ctxt_id[msgctxt_len + msgid_len];
#else #else
char buf[1024]; char buf[1024];
char *msg_ctxt_id = char *msg_ctxt_id =
(msgctxt_len + msgid_len <= sizeof (buf) (msgctxt_len + msgid_len <= sizeof(buf)
? buf ? buf
: (char *) malloc (msgctxt_len + msgid_len)); : (char *)malloc(msgctxt_len + msgid_len));
if (msg_ctxt_id != NULL) if (msg_ctxt_id != NULL)
#endif #endif
{ {
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); memcpy(msg_ctxt_id, msgctxt, msgctxt_len - 1);
msg_ctxt_id[msgctxt_len - 1] = '\004'; msg_ctxt_id[msgctxt_len - 1] = '\004';
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); memcpy(msg_ctxt_id + msgctxt_len, msgid, msgid_len);
translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); translation = dcngettext(domain, msg_ctxt_id, msgid_plural, n, category);
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
if (msg_ctxt_id != buf) if (msg_ctxt_id != buf)
free (msg_ctxt_id); free(msg_ctxt_id);
#endif #endif
if (!(translation == msg_ctxt_id || translation == msgid_plural)) if (!(translation == msg_ctxt_id || translation == msgid_plural))
return translation; return translation;
} }
return (n == 1 ? msgid : msgid_plural); return(n == 1 ? msgid : msgid_plural);
} }
#endif /* _LIBGETTEXT_H */ #endif /* _LIBGETTEXT_H */

View File

@ -67,6 +67,30 @@
#define DYNAMIC_LINE_BUFFER 40 #define DYNAMIC_LINE_BUFFER 40
/******************************************************************************
...
******************************************************************************/
// Chen Peng, added to convert time string to unix time
time_t parse_date(const char * input)
{
const char *cp;
time_t ret_t = 0;
struct tm *t = (struct tm *)kmalloc(sizeof(struct tm));
memset(t, , sizeof(*t));
// apache format, other server may diff... todo
cp = strptime(input, "%a, %d %b %Y %T %Z", t);
if (cp == NULL)
{
t->tm_year += 100; // somehow it misses 100 years. maybe a bug
ret_t = mktime(t);
}
else
proz_debug("Fail to parse time %s, unparsed part is %s", input, cp);
kfree(t);
return ret_t;
}
/****************************************************************************** /******************************************************************************
... ...
******************************************************************************/ ******************************************************************************/
@ -261,7 +285,7 @@ off_t hgetlen(const char *hdr)
for (len = 0; isdigit(*hdr); hdr++) for (len = 0; isdigit(*hdr); hdr++)
len = 10 * len + (*hdr - '0'); len = 10 * len + (*hdr - '0');
proz_debug("contenlen %s contentlen %lld", *hdr, len); proz_debug("contenlen %s contentlen %lld", hdr, len);
return len; return len;
} }
@ -700,6 +724,17 @@ uerr_t proz_http_get_url_info(connection_t * connection)
connection->resume_support = TRUE; connection->resume_support = TRUE;
else if (connection->hs.accept_ranges == -1) else if (connection->hs.accept_ranges == -1)
connection->resume_support = FALSE; connection->resume_support = FALSE;
// parse date and put it to urlinfo
time_t remote_time;
remote_time = parse_date(connection->hs.remote_time);
if (remote_time)
{
/ parse date ok
connection->u.remote_time = remote_time;
proz_debug("Remote unix time is %lld", connection->u.remote_time);
proz_debug("Remote time is %s", ctime(&(connection->u.remote_time)));
}
// end of parse date and put it to urlinfo
} }
@ -888,6 +923,15 @@ uerr_t ftp_get_url_info_from_http_proxy(connection_t * connection)
connection->resume_support = TRUE; connection->resume_support = TRUE;
else if (connection->hs.accept_ranges == -1) else if (connection->hs.accept_ranges == -1)
connection->resume_support = FALSE; connection->resume_support = FALSE;
// parse date and put it to urlinfo
time_t remote_time;
remote_time = parse_date(connection->hs.remote_time);
if (remote_time) // parse date ok
{
connection->u.remote_time = remote_time;
proz_debug("Remote mod time is %s", ctime(&(connection->u.remote_time)));
}
// end of parse date and put it to urlinfo
return FTPOK; return FTPOK;
} }

View File

@ -120,9 +120,8 @@ typedef struct _urlinfo {
char ftp_type; char ftp_type;
char *path, *dir, *file; /* Path, dir and file (properly decoded). */ char *path, *dir, *file; /* Path, dir and file (properly decoded). */
char *user, *passwd; /* For FTP. */ char *user, *passwd; /* For FTP. */
char *referer; /* The source from which the request URI was obtained. */
char *referer; /* The source from which the request time_t mtime; /* modification time, added by Chen Peng */
URI was obtained. */
} urlinfo; } urlinfo;
typedef enum { typedef enum {

View File

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: prozilla 2.0.5\n" "Project-Id-Version: prozilla 2.0.5\n"
"Report-Msgid-Bugs-To: prozilla-dev@disconnected-by-peer.at\n" "Report-Msgid-Bugs-To: prozilla-dev@disconnected-by-peer.at\n"
"POT-Creation-Date: 2010-09-01 18:53+0200\n" "POT-Creation-Date: 2010-09-01 18:53+0200\n"
"PO-Revision-Date: 2010-09-01 19:02+0100\n" "PO-Revision-Date: 2010-09-01 19:58+0100\n"
"Last-Translator: Mario Fetka <mario.fetka@gmail.com>\n" "Last-Translator: Mario Fetka <mario.fetka@gmail.com>\n"
"Language-Team: none\n" "Language-Team: none\n"
"Language: de\n" "Language: de\n"
@ -22,15 +22,8 @@ msgstr ""
#: src/download_win.cpp:533 #: src/download_win.cpp:533
#, c-format #, c-format
msgid "" msgid "A connection(s) of the download %s encountered a unrecoverable remote error, usually the file not being present in the remote server, therefore the download had to be aborted!\n"
"A connection(s) of the download %s encountered a unrecoverable remote error, " msgstr "Bei der Verbindung des Downloads %s ist ein nicht behebbarer Verbindungsfehler aufgetreten. In der Regel bedäutet dies das die Datei auf dem Remote-Server nicht vorhanden ist. Der Download musste abgeprochen werden!\n"
"usually the file not being present in the remote server, therefore the "
"download had to be aborted!\n"
msgstr ""
"Bei der Verbindung des Downloads %s ist ein nicht behebbarer "
"Verbindungsfehler aufgetreten. In der Regel bedäutet dies das die Datei auf "
"dem Remote-Server nicht vorhanden ist. Der Download musste abgeprochen "
"werden!\n"
#: src/init.cpp:83 #: src/init.cpp:83
msgid "unable to create the directory to store the config info in" msgid "unable to create the directory to store the config info in"
@ -102,15 +95,14 @@ msgstr ""
#: src/main.cpp:394 #: src/main.cpp:394
#, c-format #, c-format
msgid "" msgid ""
"Hey! Does waiting for a server response for Zero(0) seconds make and sense " "Hey! Does waiting for a server response for Zero(0) seconds make and sense to you!?\n"
"to you!?\n"
"Please type proz --help for help\n" "Please type proz --help for help\n"
msgstr "" msgstr ""
"Hey! Macht das Warten auf eine Antwort des Servers für Null (0) Sekunden " "Hey! Macht das Warten auf eine Antwort des Servers für Null (0) Sekunden irgendeinen Sinn für dich!?\n"
"irgendeinen Sinn für dich!?\n"
"Bitte geben sie proz --help für die Hilfe ein\n" "Bitte geben sie proz --help für die Hilfe ein\n"
#: src/main.cpp:407 src/main.cpp:426 #: src/main.cpp:407
#: src/main.cpp:426
#, c-format #, c-format
msgid "" msgid ""
"Error: Invalid arguments for the --pao option\n" "Error: Invalid arguments for the --pao option\n"
@ -125,19 +117,16 @@ msgid ""
"Hey you! Will pinging Zero(0) servers at once achive anything for me!?\n" "Hey you! Will pinging Zero(0) servers at once achive anything for me!?\n"
"Please type proz --help for help\n" "Please type proz --help for help\n"
msgstr "" msgstr ""
"Hey du! Keine (0) Server auf einmal zu erreichen hat für mich keine " "Hey du! Keine (0) Server auf einmal zu erreichen hat für mich keine Bedeutung!?\n"
"Bedeutung!?\n"
"Bitte geben sie proz --help für die Hilfe ein\n" "Bitte geben sie proz --help für die Hilfe ein\n"
#: src/main.cpp:432 #: src/main.cpp:432
#, c-format #, c-format
msgid "" msgid ""
"Hey! Will requesting Zero(0) servers at oncefrom the ftpearch achive " "Hey! Will requesting Zero(0) servers at oncefrom the ftpearch achive anything!?\n"
"anything!?\n"
"Please type proz --help for help\n" "Please type proz --help for help\n"
msgstr "" msgstr ""
"Hey! Keine (0) Servern von der FTP-Suche auf einmal zu erreichen hat für " "Hey! Keine (0) Servern von der FTP-Suche auf einmal zu erreichen hat für mich keine Bedeutung!?\n"
"mich keine Bedeutung!?\n"
"Bitte geben sie proz --help für die Hilfe ein\n" "Bitte geben sie proz --help für die Hilfe ein\n"
#: src/main.cpp:445 #: src/main.cpp:445
@ -170,12 +159,10 @@ msgstr ""
#: src/main.cpp:480 #: src/main.cpp:480
#, c-format #, c-format
msgid "" msgid ""
"The available servers are (0) filesearching.com and (1) ftpsearch.elmundo." "The available servers are (0) filesearching.com and (1) ftpsearch.elmundo.es\n"
"es\n"
"Please type proz --help for help\n" "Please type proz --help for help\n"
msgstr "" msgstr ""
"Die Server sind verfügbar Server sind (0) filesearching.com und (1) " "Die Server sind verfügbar Server sind (0) filesearching.com und (1) ftpsearch.elmundo.es\n"
"ftpsearch.elmundo.es\n"
"Bitte geben sie proz --help für die Hilfe ein\n" "Bitte geben sie proz --help für die Hilfe ein\n"
#: src/main.cpp:489 #: src/main.cpp:489
@ -219,9 +206,7 @@ msgstr "Gesamt Bytes empfangen %lld Kb (%.2f%%)"
#: src/interface.c:335 #: src/interface.c:335
#, c-format #, c-format
msgid "Current speed = %1.2fKb/s, Average D/L speed = %1.2fKb/s" msgid "Current speed = %1.2fKb/s, Average D/L speed = %1.2fKb/s"
msgstr "" msgstr "Aktuelle Geschwindigkeit = %1.2f Kb/s, Durchschnittliche D/L Geschwindigkeit = %1.2f Kb/s"
"Aktuelle Geschwindigkeit = %1.2f Kb/s, Durchschnittliche D/L Geschwindigkeit "
"= %1.2f Kb/s"
#: src/interface.c:343 #: src/interface.c:343
#, c-format #, c-format
@ -245,3 +230,4 @@ msgstr "Wiederaufnehmen Unterstützte"
#: src/interface.c:359 #: src/interface.c:359
msgid "Resume NOT Supported" msgid "Resume NOT Supported"
msgstr "Wiederaufnehmen NICHT unterstützt" msgstr "Wiederaufnehmen NICHT unterstützt"

View File

@ -25,6 +25,7 @@
#include <assert.h> #include <assert.h>
#include <limits.h> #include <limits.h>
#include <errno.h> #include <errno.h>
#include <utime.h>
#ifdef HAVE_NCURSES_H #ifdef HAVE_NCURSES_H
#include <ncurses.h> #include <ncurses.h>
#else #else
@ -326,6 +327,15 @@ DL_Window::start_download()
status = DL_ABORTED; status = DL_ABORTED;
return; return;
} }
// handle skipped files
if (ret == -2)
{
PrintMessage("Remote file is the same as local, skip it\n");
status = DL_ABORTED;
return;
}
// end of handle skipped files
/*Display resume status */ /*Display resume status */
if (download->resume_support) if (download->resume_support)
@ -507,6 +517,20 @@ DL_Window::handle_download_thread()
status = DL_JOINING; status = DL_JOINING;
proz_download_join_downloads(download); proz_download_join_downloads(download);
joining_thread_running = TRUE; joining_thread_running = TRUE;
// set correct mtime to server time
struct utimbuf times;
times.actime = times.modtime = download->u.remote_time;
if (!utime(download->u.file, &times))
{
proz_debug("update mtime for file %s as %s",
download->u.file, ctime(&(download->u.remote_time)));
}
else
{
proz_debug("fail to update mtime for file %s, errno=%d", download->u.file, errno);
}
// end of set correct mtime to server time
} }
if (err == CANTRESUME) if (err == CANTRESUME)
@ -520,7 +544,7 @@ DL_Window::handle_download_thread()
if (err == DLLOCALFATAL) if (err == DLLOCALFATAL)
{ {
PrintMessage("One connection of the download %s encountered a unrecoverable local error, usually lack of free space, or a write to bad medium, or a problem with permissions,so please fix this and retry\n", PrintMessage(" One connection of the download % s encountered a unrecoverable local error, usually lack of free space, or a write to bad medium, or a problem with permissions, so please fix this and retry \ n ",
connection->u.url); connection->u.url);
got_dl = FALSE; got_dl = FALSE;
status = DL_FATALERR; status = DL_FATALERR;
@ -530,7 +554,7 @@ DL_Window::handle_download_thread()
if (err == DLREMOTEFATAL) if (err == DLREMOTEFATAL)
{ {
PrintMessage(_ PrintMessage(_
("A connection(s) of the download %s encountered a unrecoverable remote error, usually the file not being present in the remote server, therefore the download had to be aborted!\n"), (" A connection(s) of the download % s encountered a unrecoverable remote error, usually the file not being present in the remote server, therefore the download had to be aborted !\ n "),
connection->u.url); connection->u.url);
got_dl = FALSE; got_dl = FALSE;
status = DL_FATALERR; status = DL_FATALERR;
@ -566,8 +590,8 @@ DL_Window::handle_joining_thread()
/*has the user pressed OK at the end of the download */ /*has the user pressed OK at the end of the download */
if (bDone == true) if (bDone == true)
{ {
PrintMessage("All Done.\n"); PrintMessage(" All Done.\ n ");
//curses_query_user_input("Press any key to exit."); //curses_query_user_input(" Press any key to exit.");
proz_download_delete_dl_file(download); proz_download_delete_dl_file(download);
proz_download_free_download(download, 0); proz_download_free_download(download, 0);
status = DL_IDLING; status = DL_IDLING;
@ -599,7 +623,7 @@ DL_Window::print_status(download_t *download, int quiet_mode)
for (int i = 0; i < download->num_connections; i++) for (int i = 0; i < download->num_connections; i++)
{ {
fprintf(stdout, fprintf(stdout,
"%2.2d %-30.30s %15.15s %10zd\n", " % 2.2d % -30.30s % 15.15s % 10zd \ n ",
i + 1, download->pconnections[i]->u.host, i + 1, download->pconnections[i]->u.host,
proz_connection_get_status_string(download-> proz_connection_get_status_string(download->
pconnections pconnections
@ -608,11 +632,11 @@ DL_Window::print_status(download_t *download, int quiet_mode)
(download->pconnections[i])); (download->pconnections[i]));
} }
fprintf(stdout, "Total Bytes received %zd Kb\n", fprintf(stdout, " Total Bytes received % zd Kb \ n ",
proz_download_get_total_bytes_got(download) / 1024); proz_download_get_total_bytes_got(download) / 1024);
fprintf(stdout, "Average Speed = %.3f Kb/sec\n", fprintf(stdout, " Average Speed = % .3f Kb / sec \ n ",
proz_download_get_average_speed(download) / 1024); proz_download_get_average_speed(download) / 1024);
} }
@ -625,23 +649,23 @@ DL_Window::print_status(download_t *download, int quiet_mode)
{ {
if (secs_left < 60) if (secs_left < 60)
{ {
snprintf(timeLeft, sizeof(timeLeft), "00:%.2d", secs_left); snprintf(timeLeft, sizeof(timeLeft), " 00 : % .2d ", secs_left);
} }
else if (secs_left < 3600) else if (secs_left < 3600)
{ {
snprintf(timeLeft, sizeof(timeLeft), "00:%.2d:%.2d", snprintf(timeLeft, sizeof(timeLeft), " 00 : % .2d : % .2d ",
secs_left / 60, secs_left % 60); secs_left / 60, secs_left % 60);
} }
else else
{ {
snprintf(timeLeft, sizeof(timeLeft), "%.2d:%.2d:00", snprintf(timeLeft, sizeof(timeLeft), " % .2d : % .2d : 00 ",
secs_left / 3600, secs_left / 3600,
(secs_left % 3600) / 60); (secs_left % 3600) / 60);
} }
} }
else else
{ {
sprintf(timeLeft, "??:??:??"); sprintf(timeLeft, " ? ? : ? ? : ? ? ");
} }
off_t totalDownloaded = 0; off_t totalDownloaded = 0;
@ -656,7 +680,7 @@ DL_Window::print_status(download_t *download, int quiet_mode)
//WGET looks like this: //WGET looks like this:
//xx% [=======> ] nnn,nnn,nnn XXXX.XXK/s ETA hh:mm:ss //xx% [=======> ] nnn,nnn,nnn XXXX.XXK/s ETA hh:mm:ss
fprintf(stdout, " %.2lf%% %zdKb/%zdkb %0.3fKb/s ETA %s \r", fprintf(stdout, " % .2lf % % % zdKb / % zdkb % 0.3fKb / s ETA % s \ r ",
((float)totalDownloaded) / ((float)totalFile / 100), ((float)totalDownloaded) / ((float)totalFile / 100),
totalDownloaded, totalFile, (float)aveSpeed, timeLeft); totalDownloaded, totalFile, (float)aveSpeed, timeLeft);
fflush(stdout); fflush(stdout);
@ -667,8 +691,8 @@ DL_Window::print_status(download_t *download, int quiet_mode)
int DL_Window::askUserResume(connection_t *connection, boolean resumeSupported) int DL_Window::askUserResume(connection_t *connection, boolean resumeSupported)
{ {
int ret = 0; int ret = 0;
const char msg[] = "Previous download of %s exists, would you like to (R)esume it or (O)verwrite it?"; const char msg[] = " Previous download of % s exists, would you like to(R) esume it or (O) verwrite it ? ";
const char msg2[] = "Previous download of %s exists, would you like to (A)bort it or (O)verwrite it?"; const char msg2[] = " Previous download of % s exists, would you like to(A) bort it or (O) verwrite it ? ";
do do
@ -679,7 +703,7 @@ int DL_Window::askUserResume(connection_t *connection, boolean resumeSupported)
} }
else else
{ {
fprintf(stdout, "\n"); fprintf(stdout, " \ n ");
fprintf(stdout, (resumeSupported == TRUE) ? msg : msg2, connection->u.file); fprintf(stdout, (resumeSupported == TRUE) ? msg : msg2, connection->u.file);
ret = getc(stdin); ret = getc(stdin);
ret = islower(ret) ? toupper(ret) : ret; ret = islower(ret) ? toupper(ret) : ret;
@ -717,7 +741,7 @@ int DL_Window::askUserResume(connection_t *connection, boolean resumeSupported)
int DL_Window::askUserOverwrite(connection_t *connectionb) int DL_Window::askUserOverwrite(connection_t *connectionb)
{ {
int ret = 0; int ret = 0;
const char msg[] = "File %s already exists, would you like to (A)bort it or (O)verwrite it?"; const char msg[] = " File % s already exists, would you like to(A) bort it or (O) verwrite it ? ";
do do
@ -728,7 +752,7 @@ int DL_Window::askUserOverwrite(connection_t *connectionb)
} }
else else
{ {
fprintf(stdout, "\n"); fprintf(stdout, " \ n ");
fprintf(stdout, msg, connection->u.file); fprintf(stdout, msg, connection->u.file);
ret = getc(stdin); ret = getc(stdin);
ret = islower(ret) ? toupper(ret) : ret; ret = islower(ret) ? toupper(ret) : ret;

View File

@ -31,10 +31,10 @@
# ifdef DEFAULT_TEXT_DOMAIN # ifdef DEFAULT_TEXT_DOMAIN
# undef gettext # undef gettext
# define gettext(Msgid) \ # define gettext(Msgid) \
dgettext (DEFAULT_TEXT_DOMAIN, Msgid) dgettext(DEFAULT_TEXT_DOMAIN, Msgid)
# undef ngettext # undef ngettext
# define ngettext(Msgid1, Msgid2, N) \ # define ngettext(Msgid1, Msgid2, N) \
dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N) dngettext(DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
# endif # endif
#else #else
@ -65,31 +65,31 @@
On pre-ANSI systems without 'const', the config.h file is supposed to On pre-ANSI systems without 'const', the config.h file is supposed to
contain "#define const". */ contain "#define const". */
# undef gettext # undef gettext
# define gettext(Msgid) ((const char *) (Msgid)) # define gettext(Msgid) ((const char *)(Msgid))
# undef dgettext # undef dgettext
# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) # define dgettext(Domainname, Msgid) ((void)(Domainname), gettext(Msgid))
# undef dcgettext # undef dcgettext
# define dcgettext(Domainname, Msgid, Category) \ # define dcgettext(Domainname, Msgid, Category) \
((void) (Category), dgettext (Domainname, Msgid)) ((void)(Category), dgettext(Domainname, Msgid))
# undef ngettext # undef ngettext
# define ngettext(Msgid1, Msgid2, N) \ # define ngettext(Msgid1, Msgid2, N) \
((N) == 1 \ ((N) == 1 \
? ((void) (Msgid2), (const char *) (Msgid1)) \ ? ((void)(Msgid2), (const char *)(Msgid1)) \
: ((void) (Msgid1), (const char *) (Msgid2))) : ((void)(Msgid1), (const char *)(Msgid2)))
# undef dngettext # undef dngettext
# define dngettext(Domainname, Msgid1, Msgid2, N) \ # define dngettext(Domainname, Msgid1, Msgid2, N) \
((void) (Domainname), ngettext (Msgid1, Msgid2, N)) ((void)(Domainname), ngettext(Msgid1, Msgid2, N))
# undef dcngettext # undef dcngettext
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N)) ((void)(Category), dngettext(Domainname, Msgid1, Msgid2, N))
# undef textdomain # undef textdomain
# define textdomain(Domainname) ((const char *) (Domainname)) # define textdomain(Domainname) ((const char *)(Domainname))
# undef bindtextdomain # undef bindtextdomain
# define bindtextdomain(Domainname, Dirname) \ # define bindtextdomain(Domainname, Dirname) \
((void) (Domainname), (const char *) (Dirname)) ((void)(Domainname), (const char *)(Dirname))
# undef bind_textdomain_codeset # undef bind_textdomain_codeset
# define bind_textdomain_codeset(Domainname, Codeset) \ # define bind_textdomain_codeset(Domainname, Codeset) \
((void) (Domainname), (const char *) (Codeset)) ((void)(Domainname), (const char *)(Codeset))
#endif #endif
@ -111,26 +111,26 @@
The letter 'p' stands for 'particular' or 'special'. */ The letter 'p' stands for 'particular' or 'special'. */
#ifdef DEFAULT_TEXT_DOMAIN #ifdef DEFAULT_TEXT_DOMAIN
# define pgettext(Msgctxt, Msgid) \ # define pgettext(Msgctxt, Msgid) \
pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) pgettext_aux(DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
#else #else
# define pgettext(Msgctxt, Msgid) \ # define pgettext(Msgctxt, Msgid) \
pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) pgettext_aux(NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
#endif #endif
#define dpgettext(Domainname, Msgctxt, Msgid) \ #define dpgettext(Domainname, Msgctxt, Msgid) \
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) pgettext_aux(Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \ #define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category) pgettext_aux(Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
#ifdef DEFAULT_TEXT_DOMAIN #ifdef DEFAULT_TEXT_DOMAIN
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) npgettext_aux(DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
#else #else
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) npgettext_aux(NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
#endif #endif
#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ #define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) npgettext_aux(Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \ #define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category) npgettext_aux(Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
#ifdef __GNUC__ #ifdef __GNUC__
__inline __inline
@ -140,11 +140,12 @@ inline
#endif #endif
#endif #endif
static const char * static const char *
pgettext_aux (const char *domain, pgettext_aux(const char *domain,
const char *msg_ctxt_id, const char *msgid, const char *msg_ctxt_id, const char *msgid,
int category) int category)
{ {
const char *translation = dcgettext (domain, msg_ctxt_id, category); const char *translation = dcgettext(domain, msg_ctxt_id, category);
if (translation == msg_ctxt_id) if (translation == msg_ctxt_id)
return msgid; return msgid;
else else
@ -159,15 +160,16 @@ inline
#endif #endif
#endif #endif
static const char * static const char *
npgettext_aux (const char *domain, npgettext_aux(const char *domain,
const char *msg_ctxt_id, const char *msgid, const char *msg_ctxt_id, const char *msgid,
const char *msgid_plural, unsigned long int n, const char *msgid_plural, unsigned long int n,
int category) int category)
{ {
const char *translation = const char *translation =
dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); dcngettext(domain, msg_ctxt_id, msgid_plural, n, category);
if (translation == msg_ctxt_id || translation == msgid_plural) if (translation == msg_ctxt_id || translation == msgid_plural)
return (n == 1 ? msgid : msgid_plural); return(n == 1 ? msgid : msgid_plural);
else else
return translation; return translation;
} }
@ -180,16 +182,16 @@ npgettext_aux (const char *domain,
#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \ #define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \
(((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \ (((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \
/* || __STDC_VERSION__ >= 199901L */ ) /* || __STDC_VERSION__ >= 199901L */)
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
#include <stdlib.h> #include <stdlib.h>
#endif #endif
#define pgettext_expr(Msgctxt, Msgid) \ #define pgettext_expr(Msgctxt, Msgid) \
dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES) dcpgettext_expr(NULL, Msgctxt, Msgid, LC_MESSAGES)
#define dpgettext_expr(Domainname, Msgctxt, Msgid) \ #define dpgettext_expr(Domainname, Msgctxt, Msgid) \
dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES) dcpgettext_expr(Domainname, Msgctxt, Msgid, LC_MESSAGES)
#ifdef __GNUC__ #ifdef __GNUC__
__inline __inline
@ -199,31 +201,32 @@ inline
#endif #endif
#endif #endif
static const char * static const char *
dcpgettext_expr (const char *domain, dcpgettext_expr(const char *domain,
const char *msgctxt, const char *msgid, const char *msgctxt, const char *msgid,
int category) int category)
{ {
size_t msgctxt_len = strlen (msgctxt) + 1; size_t msgctxt_len = strlen(msgctxt) + 1;
size_t msgid_len = strlen (msgid) + 1; size_t msgid_len = strlen(msgid) + 1;
const char *translation; const char *translation;
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
char msg_ctxt_id[msgctxt_len + msgid_len]; char msg_ctxt_id[msgctxt_len + msgid_len];
#else #else
char buf[1024]; char buf[1024];
char *msg_ctxt_id = char *msg_ctxt_id =
(msgctxt_len + msgid_len <= sizeof (buf) (msgctxt_len + msgid_len <= sizeof(buf)
? buf ? buf
: (char *) malloc (msgctxt_len + msgid_len)); : (char *)malloc(msgctxt_len + msgid_len));
if (msg_ctxt_id != NULL) if (msg_ctxt_id != NULL)
#endif #endif
{ {
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); memcpy(msg_ctxt_id, msgctxt, msgctxt_len - 1);
msg_ctxt_id[msgctxt_len - 1] = '\004'; msg_ctxt_id[msgctxt_len - 1] = '\004';
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); memcpy(msg_ctxt_id + msgctxt_len, msgid, msgid_len);
translation = dcgettext (domain, msg_ctxt_id, category); translation = dcgettext(domain, msg_ctxt_id, category);
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
if (msg_ctxt_id != buf) if (msg_ctxt_id != buf)
free (msg_ctxt_id); free(msg_ctxt_id);
#endif #endif
if (translation != msg_ctxt_id) if (translation != msg_ctxt_id)
return translation; return translation;
@ -232,9 +235,9 @@ dcpgettext_expr (const char *domain,
} }
#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \ #define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) dcnpgettext_expr(NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ #define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) dcnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
#ifdef __GNUC__ #ifdef __GNUC__
__inline __inline
@ -244,37 +247,38 @@ inline
#endif #endif
#endif #endif
static const char * static const char *
dcnpgettext_expr (const char *domain, dcnpgettext_expr(const char *domain,
const char *msgctxt, const char *msgid, const char *msgctxt, const char *msgid,
const char *msgid_plural, unsigned long int n, const char *msgid_plural, unsigned long int n,
int category) int category)
{ {
size_t msgctxt_len = strlen (msgctxt) + 1; size_t msgctxt_len = strlen(msgctxt) + 1;
size_t msgid_len = strlen (msgid) + 1; size_t msgid_len = strlen(msgid) + 1;
const char *translation; const char *translation;
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
char msg_ctxt_id[msgctxt_len + msgid_len]; char msg_ctxt_id[msgctxt_len + msgid_len];
#else #else
char buf[1024]; char buf[1024];
char *msg_ctxt_id = char *msg_ctxt_id =
(msgctxt_len + msgid_len <= sizeof (buf) (msgctxt_len + msgid_len <= sizeof(buf)
? buf ? buf
: (char *) malloc (msgctxt_len + msgid_len)); : (char *)malloc(msgctxt_len + msgid_len));
if (msg_ctxt_id != NULL) if (msg_ctxt_id != NULL)
#endif #endif
{ {
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); memcpy(msg_ctxt_id, msgctxt, msgctxt_len - 1);
msg_ctxt_id[msgctxt_len - 1] = '\004'; msg_ctxt_id[msgctxt_len - 1] = '\004';
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); memcpy(msg_ctxt_id + msgctxt_len, msgid, msgid_len);
translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); translation = dcngettext(domain, msg_ctxt_id, msgid_plural, n, category);
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
if (msg_ctxt_id != buf) if (msg_ctxt_id != buf)
free (msg_ctxt_id); free(msg_ctxt_id);
#endif #endif
if (!(translation == msg_ctxt_id || translation == msgid_plural)) if (!(translation == msg_ctxt_id || translation == msgid_plural))
return translation; return translation;
} }
return (n == 1 ? msgid : msgid_plural); return(n == 1 ? msgid : msgid_plural);
} }
#endif /* _LIBGETTEXT_H */ #endif /* _LIBGETTEXT_H */

View File

@ -57,7 +57,7 @@
* CONREJECTED, * CONREJECTED,
* REMOTEFATAL, * REMOTEFATAL,
* LOCALFATAL * LOCALFATAL
**} dl_status; ****} dl_status;
* *
* And here are the texts for the above enums. * And here are the texts for the above enums.
*/ */

View File

@ -9,7 +9,7 @@
/* Gettext */ /* Gettext */
#include "gettext.h" #include "gettext.h"
#define _(String) dgettext (PACKAGE, String) #define _(String) dgettext(PACKAGE, String)
/* Gettext */ /* Gettext */