1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

(Does not compile yet)

This commit is contained in:
Werner Koch 1998-11-03 19:38:58 +00:00
parent 5ccb92591e
commit b9dd2ebb2c
27 changed files with 1216 additions and 695 deletions

View File

@ -53,7 +53,7 @@ tobold-get:
tobold:gnupg/ .
tobold-put:
rsync -Cavuzb --excude scratch --exclude .deps \
rsync -Cavuzb --exclude scratch --exclude .deps \
. tobold:gnupg/

2
NEWS
View File

@ -15,6 +15,8 @@
* A Russian language file in the distribution (alternatives are in
the contrib directory of the FTP servers)
* commandline option processing now works as expected for GNU programs
with the execption that you can't mix options and normal arguments.
Noteworthy changes in version 0.4.2

View File

@ -8,3 +8,7 @@
of other keys (processing of the sdir hintlist). The signatures
may then be verified by a maintainence pass.
* Not GnupG replated: What about option completion in bash?
Can "--dump-options" be used for this or should we place the
options in a special ELF segment?

4
THANKS
View File

@ -12,9 +12,11 @@ Charles Levert charles@comm.polymtl.ca
Christian von Roques roques@pond.sub.org
Christopher Oliver oliver@fritz.traverse.net
Daniel Eisenbud eisenbud@cs.swarthmore.edu
David Ellement ellement@sdd.hp.com
Detlef Lannert lannert@lannert.rz.uni-duesseldorf.de
Ed Boraas ecxjo@esperanto.org
Ernst Molitor ernst.molitor@uni-bonn.de
Fabio Coatti cova@felix.unife.it
Frank Heckenbach heckenb@mi.uni-erlangen.de
Gaël Quéri gqueri@mail.dotcom.fr
Greg Louis glouis@dynamicro.on.ca
@ -49,9 +51,11 @@ Paul D. Smith psmith@baynetworks.com
Peter Gutmann pgut001@cs.auckland.ac.nz
QingLong qinglong@bolizm.ihep.su
Ralph Gillen gillen@theochem.uni-duesseldorf.de
Roddy Strachan roddy@satlink.com.au
Roland Rosenfeld roland@spinnaker.rhein.de
Serge Munhoven munhoven@mema.ucl.ac.be
SL Baur steve@xemacs.org
Stefan Karrmann S.Karrmann@gmx.net
Steffen Ullrich ccrlphr@xensei.com
Steffen Zahn zahn@berlin.snafu.de
Thomas Roessler roessler@guug.de

36
TODO
View File

@ -1,4 +1,27 @@
* rmove assert in random.c:160 4096 bit keys need more random.
* list all matching user ids
* use zlib 1.1.13 to avoid a bug with 13 bit windows
* FreeBSD:
#define USE_DYNAMIC_LINKING
#define HAVE_DL_DLOPEN
and the ld option -export-dynamic.
*
Well, there was one thing extra I needed to do. While configure found the
gdbm library, it didn't add the path the the include file list. I had to
re-run configure with CPPFLAGS set:
env CPPFLAGS='-I/usr/local/include' configure ...
* clearsig: keep lineendings as they are. Remember that trailings
blanks are not hashed.
* Fix ;) revocation and expire stuff.
* check preferences (cipher and compress)
@ -11,13 +34,9 @@
* prefer a type 16 subkey for encryption because pgp cannot handle
type 20?
* calculation of marginals never yields a completely trusted key.
* The critical bit of signature subpackets is not yet supported; i.e.
it is ignored.
* Exportable Certification Flag is ignored
* We need a maintainence pass over the trustdb which flags
signatures as expired if the key used to make the signature has
expired. Maybe it is a good idea to store the exiration time
@ -58,6 +77,15 @@
* add an option to re-create a public key from a secret key; we
can do this in trustdb.c:verify_own_keys.
* signature verification is done duplicated on import: in import.c and
tehn in trustdb.c too. Maybe we can use a flag to skip the actual
verification process (this should work if we use the same keyblock,
but I'm not sure how to accomplish that). Another way is to allow
the import of bogus data and let trustdb mark these keys as invalid;
I see an advantage in this that it may help to prevent a DoS on a
keyserver by sending him a lot of bogus signatures which he has
to check - Needs further investigation.
* change the fake_data stuff to mpi_set_opaque
* Is it okay to use gettext for the help system?

View File

@ -44,9 +44,9 @@ else
fi
if test "$use_m_guard" = yes ; then
AC_DEFINE(M_GUARD)
CFLAGS="-g -Wall"
CFLAGS="$CFLAGS -g -Wall"
else
CFLAGS="-O2 -Wall"
CFLAGS="$CFLAGS -O2 -Wall"
fi

View File

@ -249,8 +249,12 @@ B<-z> I<n>
compression level of zlib (which is 6).
B<-t>, B<--textmode>
Use canonical text mode. Used to make clear-text
signatures.
Use canonical text mode. If B<-t> (but not
B<--textmode>) is used together with armoring
and signing, this enables clearsigned messages.
This kludge is needed for PGP compatibility;
normally you would use B<--sign> or b<--clearsign>
to selected the type os signatures.
B<-n>, B<--dry-run>
Don't make any changes (not yet implemented).

View File

@ -1,3 +1,30 @@
Tue Nov 3 16:19:21 1998 Werner Koch (wk@isil.d.shuttle.de)
* keygen.c (ask_user_id): Now converted to UTF-8
* g10.c (main): Kludge for pgp clearsigs and textmode.
Fri Oct 30 16:40:39 1998 me,,, (wk@tobold)
* signal.c (block_all_signals): New.
(unblock_all_signals): New
* tdbio.c (tdbio_end_transaction): Now blocks all signals.
* trustdb.c (new_lid_table): Changed the represenation of the
former local_lid_info stuff.
* trustdb.c (update_trust_record): Reorganized the whole thing.
* sig-check.c (check_key_signature): Now handles class 0x28
Wed Oct 28 18:56:33 1998 me,,, (wk@tobold)
* export.c (do_export): Takes care of the exportable sig flag.
Tue Oct 27 14:53:04 1998 Werner Koch (wk@isil.d.shuttle.de)
* trustdb.c (update_trust_record): New "fast" parameter.
Sun Oct 25 19:32:05 1998 Werner Koch (wk@isil.d.shuttle.de)
* openfile.c (copy_options_File): New.

View File

@ -128,6 +128,15 @@ do_export( STRLIST users, int secret )
* secret keyring */
if( !secret && node->pkt->pkttype == PKT_COMMENT )
continue;
/* do not export packets which are marked as not exportable */
if( node->pkt->pkttype == PKT_SIGNATURE ) {
const char *p;
p = parse_sig_subpkt2( node->pkt->pkt.signature,
SIGSUBPKT_EXPORTABLE, NULL );
if( p && !*p )
continue; /* not exportable */
}
if( (rc = build_packet( out, node->pkt )) ) {
log_error("build_packet(%d) failed: %s\n",
node->pkt->pkttype, g10_errstr(rc) );

View File

@ -60,7 +60,7 @@ enum cmd_and_opt_values { aNull = 0,
oQuiet = 'q',
oRemote = 'r',
aSign = 's',
oTextmode = 't',
oTextmodeShort= 't',
oUser = 'u',
oVerbose = 'v',
oCompress = 'z',
@ -100,6 +100,7 @@ enum cmd_and_opt_values { aNull = 0,
aEnArmor,
aGenRandom,
oTextmode,
oFingerprint,
oAnswerYes,
oAnswerNo,
@ -205,6 +206,7 @@ static ARGPARSE_OPTS opts[] = {
{ oUser, "local-user",2, N_("use this user-id to sign or decrypt")},
{ oRemote, "remote-user", 2, N_("use this user-id for encryption")},
{ oCompress, NULL, 1, N_("|N|set compress level N (0 disables)") },
{ oTextmodeShort, NULL, 0, "@"},
{ oTextmode, "textmode", 0, N_("use canonical text mode")},
#endif
{ oOutput, "output", 2, N_("use as output file")},
@ -734,6 +736,7 @@ main( int argc, char **argv )
sl->next = remusr;
remusr = sl;
break;
case oTextmodeShort: opt.textmode = 2; break;
case oTextmode: opt.textmode=1; break;
case oUser: /* store the local users */
sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str));
@ -839,7 +842,7 @@ main( int argc, char **argv )
/* kludge to let -sat generate a clear text signature */
if( opt.textmode && !detached_sig && opt.armor && cmd == aSign )
if( opt.textmode == 2 && !detached_sig && opt.armor && cmd == aSign )
cmd = aClearsign;
if( opt.verbose > 1 )

View File

@ -465,7 +465,7 @@ import_one( const char *fname, KBNODE keyblock, int fast )
(ulong)keyid[1], g10_errstr(rc) );
}
else if( mod_key )
rc = update_trust_record( keyblock_orig, NULL );
rc = update_trust_record( keyblock_orig, 1, NULL );
else
rc = clear_trust_checked_flag( new_key? pk : pk_orig );
}

View File

@ -647,7 +647,7 @@ keyedit_menu( const char *username, STRLIST locusr )
}
else
tty_printf(_("Key not changed so no update needed.\n"));
rc = update_trust_record( keyblock, NULL );
rc = update_trust_record( keyblock, 0, NULL );
if( rc )
log_error(_("update of trust db failed: %s\n"),
g10_errstr(rc) );
@ -705,7 +705,7 @@ keyedit_menu( const char *username, STRLIST locusr )
sec_modified = modified = 1;
/* must update the trustdb already here, so that preferences
* get listed correctly */
rc = update_trust_record( keyblock, NULL );
rc = update_trust_record( keyblock, 0, NULL );
if( rc ) {
log_error(_("update of trust db failed: %s\n"),
g10_errstr(rc) );

View File

@ -689,6 +689,11 @@ ask_user_id( int mode )
break;
m_free(uid); uid = NULL;
}
if( uid ) {
char *p = native_to_utf8( uid );
m_free( uid );
uid = p;
}
return uid;
}

View File

@ -633,7 +633,8 @@ dump_sig_subpkt( int hashed, int type, int critical,
printf("sig expires %s", strtimestamp( buffer_to_u32(buffer) ) );
break;
case SIGSUBPKT_EXPORTABLE:
p = "exportable";
if( length )
printf("%sexportable", *buffer? "":"not ");
break;
case SIGSUBPKT_TRUST:
p = "trust signature";
@ -759,6 +760,10 @@ parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, size_t *ret_n )
if( n < 4 )
break;
return buffer;
case SIGSUBPKT_EXPORTABLE:
if( !n )
break;
return buffer;
case SIGSUBPKT_ISSUER:/* issuer key ID */
if( n < 8 )
break;

View File

@ -278,12 +278,27 @@ check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
rc = do_check( pk, sig, md );
md_close(md);
}
else if( sig->sig_class == 0x28 ) { /* subkey revocation */
KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY );
if( snode ) {
md = md_open( algo, 0 );
hash_public_key( md, pk );
hash_public_key( md, snode->pkt->pkt.public_key );
rc = do_check( pk, sig, md );
md_close(md);
}
else {
log_error("no subkey for subkey revocation packet\n");
rc = G10ERR_SIG_CLASS;
}
}
else if( sig->sig_class == 0x18 ) {
KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY );
if( snode ) {
if( is_selfsig ) {
u32 keyid[2];
if( is_selfsig ) { /* does this make sense????? */
u32 keyid[2]; /* it should always be a selfsig */
keyid_from_pk( pk, keyid );
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )

View File

@ -121,3 +121,42 @@ pause_on_sigusr( int which )
#endif
}
static void
do_block( int block )
{
#ifndef __MINGW32__
static int is_blocked;
static sigset_t oldmask;
if( block ) {
sigset_t newmask;
if( is_blocked )
log_bug("signals are already blocked\n");
sigfillset( &newmask );
sigprocmask( SIG_BLOCK, &newmask, &oldmask );
is_blocked = 1;
}
else {
if( !is_blocked )
log_bug("signals are not blocked\n");
sigprocmask( SIG_SETMASK, &oldmask, NULL );
is_blocked = 0;
}
#endif /*__MINGW32__*/
}
void
block_all_signals()
{
do_block(1);
}
void
unblock_all_signals()
{
do_block(0);
}

View File

@ -320,10 +320,15 @@ tdbio_begin_transaction()
int
tdbio_end_transaction()
{
int rc;
if( !in_transaction )
log_bug("tdbio: no active transaction\n");
block_all_signals();
in_transaction = 0;
return tdbio_sync();
rc = tdbio_sync();
unblock_all_signals();
return rc;
}
int

File diff suppressed because it is too large Load Diff

View File

@ -60,7 +60,7 @@ ulong lid_from_keyblock( KBNODE keyblock );
int query_trust_record( PKT_public_key *pk );
int clear_trust_checked_flag( PKT_public_key *pk );
int insert_trust_record( PKT_public_key *pk );
int update_trust_record( KBNODE keyblock, int *modified );
int update_trust_record( KBNODE keyblock, int fast, int *modified );
int update_ownertrust( ulong lid, unsigned new_trust );
/*-- pkclist.c --*/

View File

@ -152,6 +152,8 @@ const char *memistr( const char *buf, size_t buflen, const char *sub );
char *mem2str( char *, const void *, size_t);
char *trim_spaces( char *string );
int string_count_chr( const char *string, int c );
char *native_to_utf8( const char *string );
char *utf8_to_native( const char *string );
#define stricmp(a,b) strcasecmp((a),(b))

View File

@ -1,6 +1,10 @@
Tue Oct 27 12:37:46 1998 Werner Koch (wk@isil.d.shuttle.de)
* config.links (freebsd): Fixes for FreeBSD 3.0
Wed Oct 14 09:59:30 1998 Werner Koch (wk@isil.d.shuttle.de)
* config-links (freebsd): ELF patches from Jun Kuriyama.
* config.links (freebsd): ELF patches from Jun Kuriyama.
Thu Oct 8 13:28:17 1998 Werner Koch (wk@isil.d.shuttle.de)

View File

@ -10,12 +10,12 @@ test -d ./mpi || mkdir ./mpi
echo '/* created by config.links - do not edit */' >./mpi/asm-syntax.h
case "${target}" in
i[34]86*-*-freebsd*-elf)
i[34]86*-*-freebsd*-elf | i[34]86*-*-freebsd3*)
echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h
cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h
path="i386"
;;
i[56]86*-*-freebsd*-elf)
i[56]86*-*-freebsd*-elf | i[56]86*-*-freebsd3*)
echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h
cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h
path="i586 i386"

View File

@ -1,3 +1,7 @@
Fri Oct 30 20:03:17 1998 Werner Koch (wk@isil.d.shuttle.de)
* fr.po: Imported new version
Mon Oct 12 09:08:09 1998 Werner Koch (wk@isil.d.shuttle.de)
* it.po: Imported new version.

773
po/fr.po

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,17 @@
Tue Nov 3 16:17:56 1998 Werner Koch (wk@isil.d.shuttle.de)
* strgutil.c (native_to_utf8): New.
(utf8_to_native): New, but only as a stub.
* argparse.c (optfile_parse): Trimmed spaces from args.
Wed Oct 28 08:01:49 1998 me,,, (wk@tobold)
* argparse.c (find_long_option): New.
(arg_parse): option=value is now allowed. Add a new internal
option "--dump-options".
Thu Oct 22 16:25:49 1998 Michael Roth (mroth@nessie.de)
* fileutil.c (make_basename): New.

View File

@ -1,13 +1,13 @@
/* [argparse.c wk 17.06.97] Argument Parser for option handling
* Copyright (C) 1998 Free Software Foundation, Inc.
* This file is part of WkLib.
* This file is part of GnuPG.
*
* WkLib is free software; you can redistribute it and/or modify
* GnuPG 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.
*
* WkLib is distributed in the hope that it will be useful,
* GnuPG 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.
@ -73,8 +73,8 @@
* Bit 4 : Do not skip the first arg.
* Bit 5 : allow usage of long option with only one dash
* Bit 6 : ignore --version
* all other bits must be set to zero, this value is modified by the function
* so assume this is write only.
* all other bits must be set to zero, this value is modified by the
* function, so assume this is write only.
* Local flags (for each option):
* Bit 2-0 : 0 = does not take an argument
* 1 = takes int argument
@ -83,8 +83,8 @@
* 4 = takes ulong argument
* Bit 3 : argument is optional (r_type will the be set to 0)
* Bit 4 : allow 0x etc. prefixed values.
* Bit 7 : this is an command and not an option
* If can stop the option processing by setting opts to NULL, the function will
* Bit 7 : this is a command and not an option
* You stop the option processing by setting opts to NULL, the function will
* then return 0.
* @Return Value
* Returns the args.r_opt or 0 if ready
@ -167,8 +167,14 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
else {
if( arg->r_opt == -3 )
s = "Missing argument for option \"%.50s\"\n";
else if( arg->r_opt == -6 )
s = "Option \"%.50s\" does not expect an argument\n";
else if( arg->r_opt == -7 )
s = "Invalid command \"%.50s\"\n";
else if( arg->r_opt == -8 )
s = "Option \"%.50s\" is ambiguous\n";
else if( arg->r_opt == -9 )
s = "Command \"%.50s\" is ambiguous\n";
else
s = "Invalid option \"%.50s\"\n";
log_error(s, arg->internal.last? arg->internal.last:"[??]" );
@ -186,10 +192,15 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
* Lines starting with '#' are comment lines.
* Syntax is simply a keyword and the argument.
* Valid keywords are all keywords from the long_opt list without
* the leading dashes. The special keywords help, warranty and version
* the leading dashes. The special keywords "help", "warranty" and "version"
* are not valid here.
* Caller must free returned strings.
* If called with FP set to NULL command line args are parse instead.
*
* Q: Should we allow the syntax
* keyword = value
* and accept for boolean options a value of 1/0, yes/no or true/false?
* Note: Abbreviation of options is here not allowed.
*/
int
optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
@ -229,7 +240,7 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
arg->r_opt = (opts[index].flags & 256)? -7:-2;
else if( (opts[index].flags & 8) ) /* no argument */
arg->r_opt = -3; /* error */
else /* no or optiona argument */
else /* no or optional argument */
arg->r_type = 0; /* okay */
break;
}
@ -253,6 +264,7 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
else
buffer[i] = 0;
trim_spaces( buffer );
if( !set_opt_arg(arg, opts[index].flags, buffer) )
m_free(buffer);
}
@ -331,6 +343,37 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
static int
find_long_option( ARGPARSE_OPTS *opts, const char *keyword )
{
int i;
size_t n;
/* Would be better if we can do a binary search, but it is not
possible to reorder our option table because we would mess
up our help strings - What we can do is: Build a nice option
lookup table wehn this function is first invoked */
if( !*keyword )
return -1;
for(i=0; opts[i].short_opt; i++ )
if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
return i;
/* not found, see whether it is an abbreviation */
n = strlen( keyword );
for(i=0; opts[i].short_opt; i++ ) {
if( opts[i].long_opt && !strncmp( opts[i].long_opt, keyword, n ) ) {
int j;
for(j=i+1; opts[j].short_opt; j++ ) {
if( opts[j].long_opt
&& !strncmp( opts[j].long_opt, keyword, n ) )
return -2; /* abbreviation is ambiguous */
}
return i;
}
}
return -1;
}
int
arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
{
@ -369,6 +412,8 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
goto leave;
}
else if( *s == '-' && s[1] == '-' ) { /* long option */
char *argpos;
arg->internal.inarg = 0;
if( !s[2] && !(arg->flags & (1<<3)) ) { /* stop option processing */
arg->internal.stopped = 1;
@ -376,29 +421,49 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
goto next_one;
}
for(i=0; opts[i].short_opt; i++ )
if( opts[i].long_opt && !strcmp( opts[i].long_opt, s+2) )
break;
argpos = strchr( s+2, '=' );
if( argpos )
*argpos = 0;
i = find_long_option( opts, s+2 );
if( argpos )
*argpos = '=';
if( !opts[i].short_opt && !strcmp( "help", s+2) )
if( i < 0 && !strcmp( "help", s+2) )
show_help(opts, arg->flags);
else if( !opts[i].short_opt && !strcmp( "version", s+2) ) {
else if( i < 0 && !strcmp( "version", s+2) ) {
if( !(arg->flags & (1<<6)) ) {
show_version();
exit(0);
}
}
else if( !opts[i].short_opt && !strcmp( "warranty", s+2) ) {
else if( i < 0 && !strcmp( "warranty", s+2) ) {
puts( strusage(16) );
exit(0);
}
else if( i < 0 && !strcmp( "dump-options", s+2) ) {
for(i=0; opts[i].short_opt; i++ )
if( opts[i].long_opt )
printf( "--%s\n", opts[i].long_opt );
exit(0);
}
arg->r_opt = opts[i].short_opt;
if( !opts[i].short_opt ) {
if( i == -2 ) /* ambiguous option */
arg->r_opt = (opts[i].flags & 256)? -9:-8;
else if( i == -1 ) {
arg->r_opt = (opts[i].flags & 256)? -7:-2;
arg->r.ret_str = s+2;
}
else
arg->r_opt = opts[i].short_opt;
if( i < 0 )
;
else if( (opts[i].flags & 7) ) {
if( argpos ) {
s2 = argpos+1;
if( !*s2 )
s2 = NULL;
}
else
s2 = argv[1];
if( !s2 && (opts[i].flags & 8) ) { /* no argument but it is okay*/
arg->r_type = 0; /* because it is optional */
@ -406,7 +471,7 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
else if( !s2 ) {
arg->r_opt = -3; /* missing argument */
}
else if( *s2 == '-' && (opts[i].flags & 8) ) {
else if( !argpos && *s2 == '-' && (opts[i].flags & 8) ) {
/* the argument is optional and the next seems to be
* an option. We do not check this possible option
* but assume no argument */
@ -414,10 +479,15 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
}
else {
set_opt_arg(arg, opts[i].flags, s2);
if( !argpos ) {
argc--; argv++; index++; /* skip one */
}
}
}
else { /* does not take an argument */
if( argpos )
arg->r_type = -6; /* argument not expected */
else
arg->r_type = 0;
}
argc--; argv++; index++; /* set to next one */

View File

@ -179,6 +179,52 @@ string_count_chr( const char *string, int c )
return count;
}
/****************
* Convert string, which is in native encoding to UTF8 and return the
* new allocated UTF8 string.
* This code assumes that native is iso-8859-1.
*/
char *
native_to_utf8( const char *string )
{
const byte *s;
char *buffer;
byte *p;
size_t length=0;
for(s=string; *s; s++ ) {
length++;
if( *s & 0x80 )
length++;
}
buffer = m_alloc( length + 1 );
for(p=buffer, s=string; *s; s++ ) {
if( *s & 0x80 ) {
*p++ = 0xc0 | ((*s >> 6) & 3);
*p++ = 0x80 | ( *s & 0x3f );
}
else
*p++ = *s;
}
*p = 0;
return buffer;
}
/****************
* Convert string, which is in UTF8 to native encoding. Replace
* illegal encodings by some "\xnn".
* This code assumes that native is iso-8859-1.
*/
char *
utf8_to_native( const char *string )
{
/* FIXME: Not yet done */
return m_strdup(string);
}
/*********************************************
********** missing string functions *********
*********************************************/