##################################################################### */
/*}}}*/
// Includes /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/strutl.h"
-#endif
-
#include <apt-pkg/strutl.h>
#include <apt-pkg/fileutl.h>
#include <apt-pkg/error.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h>
+#include <algorithm>
#include <unistd.h>
#include <regex.h>
#include <errno.h>
#include <stdarg.h>
+#include <iconv.h>
#include "config.h"
using namespace std;
/*}}}*/
+// UTF8ToCodeset - Convert some UTF-8 string for some codeset /*{{{*/
+// ---------------------------------------------------------------------
+/* This is handy to use before display some information for enduser */
+bool UTF8ToCodeset(const char *codeset, const string &orig, string *dest)
+{
+ iconv_t cd;
+ const char *inbuf;
+ char *inptr, *outbuf, *outptr;
+ size_t insize, outsize;
+
+ cd = iconv_open(codeset, "UTF-8");
+ if (cd == (iconv_t)(-1)) {
+ // Something went wrong
+ if (errno == EINVAL)
+ _error->Error("conversion from 'UTF-8' to '%s' not available",
+ codeset);
+ else
+ perror("iconv_open");
+
+ // Clean the destination string
+ *dest = "";
+
+ return false;
+ }
+
+ insize = outsize = orig.size();
+ inbuf = orig.data();
+ inptr = (char *)inbuf;
+ outbuf = new char[insize+1];
+ outptr = outbuf;
+
+ iconv(cd, &inptr, &insize, &outptr, &outsize);
+ *outptr = '\0';
+
+ *dest = outbuf;
+ delete[] outbuf;
+
+ iconv_close(cd);
+
+ return true;
+}
+ /*}}}*/
// strstrip - Remove white space from the front and back of a string /*{{{*/
// ---------------------------------------------------------------------
/* This is handy to use when parsing a file. It also removes \n's left
{
if (Sec > 60*60*24)
{
- sprintf(S,"%lid %lih%lim%lis",Sec/60/60/24,(Sec/60/60) % 24,(Sec/60) % 60,Sec % 60);
+ //d means days, h means hours, min means minutes, s means seconds
+ sprintf(S,_("%lid %lih %limin %lis"),Sec/60/60/24,(Sec/60/60) % 24,(Sec/60) % 60,Sec % 60);
break;
}
if (Sec > 60*60)
{
- sprintf(S,"%lih%lim%lis",Sec/60/60,(Sec/60) % 60,Sec % 60);
+ //h means hours, min means minutes, s means seconds
+ sprintf(S,_("%lih %limin %lis"),Sec/60/60,(Sec/60) % 60,Sec % 60);
break;
}
if (Sec > 60)
{
- sprintf(S,"%lim%lis",Sec/60,Sec % 60);
+ //min means minutes, s means seconds
+ sprintf(S,_("%limin %lis"),Sec/60,Sec % 60);
break;
}
-
- sprintf(S,"%lis",Sec);
+
+ //s means seconds
+ sprintf(S,_("%lis"),Sec);
break;
}
return Final;
}
/*}}}*/
-// stringcmp - Arbitary string compare /*{{{*/
+// stringcmp - Arbitrary string compare /*{{{*/
// ---------------------------------------------------------------------
-/* This safely compares two non-null terminated strings of arbitary
+/* This safely compares two non-null terminated strings of arbitrary
length */
int stringcmp(const char *A,const char *AEnd,const char *B,const char *BEnd)
{
}
#endif
/*}}}*/
-// stringcasecmp - Arbitary case insensitive string compare /*{{{*/
+// stringcasecmp - Arbitrary case insensitive string compare /*{{{*/
// ---------------------------------------------------------------------
/* */
int stringcasecmp(const char *A,const char *AEnd,const char *B,const char *BEnd)
// ---------------------------------------------------------------------
/* This pulls full messages from the input FD into the message buffer.
It assumes that messages will not pause during transit so no
- fancy buffering is used. */
+ fancy buffering is used.
+
+ In particular: this reads blocks from the input until it believes
+ that it's run out of input text. Each block is terminated by a
+ double newline ('\n' followed by '\n'). As noted below, there is a
+ bug in this code: it assumes that all the blocks have been read if
+ it doesn't see additional text in the buffer after the last one is
+ parsed, which will cause it to lose blocks if the last block
+ coincides with the end of the buffer.
+ */
bool ReadMessages(int Fd, vector<string> &List)
{
char Buffer[64000];
char *End = Buffer;
+ // Represents any left-over from the previous iteration of the
+ // parse loop. (i.e., if a message is split across the end
+ // of the buffer, it goes here)
+ string PartialMessage;
while (1)
{
// Pull the message out
string Message(Buffer,I-Buffer);
+ PartialMessage += Message;
// Fix up the buffer
for (; I < End && *I == '\n'; I++);
memmove(Buffer,I,End-Buffer);
I = Buffer;
- List.push_back(Message);
+ List.push_back(PartialMessage);
+ PartialMessage.clear();
}
- if (End == Buffer)
- return true;
+ if (End != Buffer)
+ {
+ // If there's text left in the buffer, store it
+ // in PartialMessage and throw the rest of the buffer
+ // away. This allows us to handle messages that
+ // are longer than the static buffer size.
+ PartialMessage += string(Buffer, End);
+ End = Buffer;
+ }
+ else
+ {
+ // BUG ALERT: if a message block happens to end at a
+ // multiple of 64000 characters, this will cause it to
+ // terminate early, leading to a badly formed block and
+ // probably crashing the method. However, this is the only
+ // way we have to find the end of the message block. I have
+ // an idea of how to fix this, but it will require changes
+ // to the protocol (essentially to mark the beginning and
+ // end of the block).
+ //
+ // -- dburrows 2008-04-02
+ return true;
+ }
if (WaitFd(Fd) == false)
return false;
va_start(args,format);
// sprintf the description
- char S[400];
+ char S[4096];
vsnprintf(S,sizeof(S),format,args);
out << S;
}
/*}}}*/
+// strprintf - C format string outputter to C++ strings /*{{{*/
+// ---------------------------------------------------------------------
+/* This is used to make the internationalization strings easier to translate
+ and to allow reordering of parameters */
+void strprintf(string &out,const char *format,...)
+{
+ va_list args;
+ va_start(args,format);
+
+ // sprintf the description
+ char S[4096];
+ vsnprintf(S,sizeof(S),format,args);
+ out = string(S);
+}
+ /*}}}*/
// safe_snprintf - Safer snprintf /*{{{*/
// ---------------------------------------------------------------------
/* This is a snprintf that will never (ever) go past 'End' and returns a
}
/*}}}*/
+// tolower_ascii - tolower() function that ignores the locale /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+int tolower_ascii(int c)
+{
+ if (c >= 'A' and c <= 'Z')
+ return c + 32;
+ return c;
+}
+ /*}}}*/
+
// CheckDomainList - See if Host is in a , seperate list /*{{{*/
// ---------------------------------------------------------------------
/* The domain list is a comma seperate list of domains that are suffix