libcdio-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Libcdio-devel] [PATCH] Add UDF Unicode support


From: Rocky Bernstein
Subject: Re: [Libcdio-devel] [PATCH] Add UDF Unicode support
Date: Fri, 21 Feb 2014 19:06:03 -0500

Patch applied in commit 7029581 - thanks.

git-apply didn't work while patch mostly worked. So the test image test
hasn't been added. Add it as an attachment in
https://savannah.gnu.org/patch/?group=libcdio And please double check that
the changes are what you expect.


On Wed, Feb 19, 2014 at 9:27 PM, Pete Batard <address@hidden> wrote:

> Hi,
>
> Having recently found that the unicode16_decode() call we use in udf_fs
> isn't actually doing any actual Unicode decoding (just strips the MSB from
> UTF-16), please find attached a patch that adds Unicode support to udf_fs
> and will ensure we always return UTF-8 strings where relevant.
>
> The patch also contains an associated test as well as the required UDF
> image (which was created using ImgBurn).
>
> Regards,
>
> /Pete
>
> From 6310430dd712e9769e49dd942d2200cb27951cec Mon Sep 17 00:00:00 2001
> From: Pete Batard <address@hidden>
> Date: Thu, 20 Feb 2014 02:21:27 +0000
> Subject: [PATCH] Add Unicode support for UDF
>
> ---
>  lib/driver/utf8.c      |   3 --
>  lib/udf/udf_fs.c       | 104
> ++++++++++++++++++++++++++++++++-----------------
>  test/check_fuzzyiso.sh |   2 +-
>  test/data/udf102.iso   | Bin 784384 -> 1245184 bytes
>  test/testudf.c.in      |  32 +++++++++++----
>  5 files changed, 94 insertions(+), 47 deletions(-)
>
> diff --git a/lib/driver/utf8.c b/lib/driver/utf8.c
> index db68d5b..b94b833 100644
> --- a/lib/driver/utf8.c
> +++ b/lib/driver/utf8.c
> @@ -113,7 +113,6 @@ FILE* fopen_utf8(const char* filename, const char*
> mode)
>  }
>  #endif
>
> -#ifdef HAVE_JOLIET
>  #ifdef HAVE_ICONV
>  #include <iconv.h>
>  struct cdio_charset_coverter_s
> @@ -344,5 +343,3 @@ bool cdio_charset_to_utf8(const char *src, size_t
> src_len, cdio_utf8_t **dst,
>    return (*dst != NULL);
>  }
>  #endif /* HAVE_ICONV */
> -
> -#endif /* HAVE_JOLIET */
> diff --git a/lib/udf/udf_fs.c b/lib/udf/udf_fs.c
> index 81719b6..e21571a 100644
> --- a/lib/udf/udf_fs.c
> +++ b/lib/udf/udf_fs.c
> @@ -70,6 +70,9 @@ const char VSD_STD_ID_NSR03[] = {'N', 'S', 'R', '0',
> '3'};
>  const char VSD_STD_ID_TEA01[] = {'T', 'E', 'A', '0', '1'};
>
>  #include <cdio/bytesex.h>
> +#include <cdio/utf8.h>
> +#include <cdio/util.h>
> +
>  #include "udf_private.h"
>  #include "udf_fs.h"
>  #include "cdio_assert.h"
> @@ -274,23 +277,32 @@ udf_fopen(udf_dirent_t *p_udf_root, const char
> *psz_name)
>    return p_udf_file;
>  }
>
> -/* Convert unicode16 to 8-bit char by dripping MSB.
> -   Wonder if iconv can be used here
> +/* Convert unicode16 to UTF-8.
> +   The returned string is allocated and must be freed by the caller
>  */
> -static int
> -unicode16_decode( const uint8_t *data, int i_len, char *target )
> +static char*
> +unicode16_decode(const uint8_t *data, int i_len)
>  {
> -  int p = 1, i = 0;
> -
> -  if( ( data[ 0 ] == 8 ) || ( data[ 0 ] == 16 ) ) do {
> -    if( data[ 0 ] == 16 ) p++;  /* Ignore MSB of unicode16 */
> -    if( p < i_len ) {
> -      target[ i++ ] = data[ p++ ];
> -    }
> -  } while( p < i_len );
> +  int i;
> +  char* r = NULL;
>
> -  target[ i ] = '\0';
> -  return 0;
> +  switch (data[0])
> +  {
> +  case 8:
> +    r = (char*)calloc(i_len, 1);
> +    if (r == NULL)
> +      return r;
> +    for (i=0; i<i_len-1; i++)
> +      r[i] = data[i+1];
> +    return r;
> +  case 16:
> +    cdio_charset_to_utf8((char*)&data[1], i_len-1, &r, "UCS-2BE");
> +    return r;
> +  default:
> +    /* Empty string, as some existing sections can't take a NULL pointer
> */
> +    r = (char*)calloc(1, 1);
> +    return r;
> +  }
>  }
>
>
> @@ -431,18 +443,24 @@ udf_open (const char *psz_path)
>  }
>
>  /**
> - * Gets the Volume Identifier string, in 8bit unicode (latin-1)
> + * Gets the Volume Identifier, as an UTF-8 string
>   * psz_volid, place to put the string
>   * i_volid, size of the buffer psz_volid points to
>   * returns the size of buffer needed for all data
> + * Note: this call accepts a NULL psz_volid, to retrieve the length
> required.
>   */
> -int
> -udf_get_volume_id(udf_t *p_udf, /*out*/ char *psz_volid,  unsigned int
> i_volid)
> +int
> +udf_get_volume_id(udf_t *p_udf, /*out*/ char *psz_volid, unsigned int
> i_volid)
>  {
>    uint8_t data[UDF_BLOCKSIZE];
>    const udf_pvd_t *p_pvd = (udf_pvd_t *) &data;
> +  char* r;
>    unsigned int volid_len;
>
> +  /* clear the output to empty string */
> +  if (psz_volid != NULL)
> +    psz_volid[0] = 0;
> +
>    /* get primary volume descriptor */
>    if ( DRIVER_OP_SUCCESS != udf_read_sectors(p_udf, &data,
> p_udf->pvd_lba, 1) )
>      return 0;
> @@ -452,10 +470,17 @@ udf_get_volume_id(udf_t *p_udf, /*out*/ char
> *psz_volid,  unsigned int i_volid)
>      /* this field is only UDF_VOLID_SIZE bytes something is wrong */
>      volid_len = UDF_VOLID_SIZE-1;
>    }
> -  if(i_volid > volid_len) {
> -    i_volid = volid_len;
> +
> +  r = unicode16_decode((uint8_t *) p_pvd->vol_ident, volid_len);
> +  if (r == NULL)
> +    return 0;
> +
> +  volid_len = strlen(r)+1;     /* +1 for NUL terminator */
> +  if (psz_volid != NULL) {
> +    strncpy(psz_volid, r, MIN(volid_len, i_volid));
> +    psz_volid[i_volid-1] = 0;  /* strncpy does not always terminate the
> dest */
>    }
> -  unicode16_decode((uint8_t *) p_pvd->vol_ident, i_volid, psz_volid);
> +  free(r);
>
>    return volid_len;
>  }
> @@ -490,27 +515,39 @@ udf_get_volumeset_id(udf_t *p_udf, /*out*/ uint8_t
> *volsetid,
>  }
>
>  /**
> - * Gets the Logical Volume Identifier string, in 8bit unicode (latin-1)
> + * Gets the Logical Volume Identifier string, as an UTF-8 string
>   * psz_logvolid, place to put the string (should be at least 64 bytes)
>   * i_logvolid, size of the buffer psz_logvolid points to
> - * returns the size of buffer needed for all data
> + * returns the size of buffer needed for all data, including NUL
> terminator
>   * A call to udf_get_root() should have been issued before this call
> + * Note: this call accepts a NULL psz_volid, to retrieve the length
> required.
>   */
>  int
> -udf_get_logical_volume_id(udf_t *p_udf, /*out*/ char *psz_logvolid,
>  unsigned int i_logvolid)
> +udf_get_logical_volume_id(udf_t *p_udf, /*out*/ char *psz_logvolid,
> unsigned int i_logvolid)
>  {
>    uint8_t data[UDF_BLOCKSIZE];
>    logical_vol_desc_t *p_logvol = (logical_vol_desc_t *) &data;
> +  char* r;
>    int logvolid_len;
>
> -  if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, p_logvol,
> p_udf->lvd_lba, 1) )
> +  /* clear the output to empty string */
> +  if (psz_logvolid != NULL)
> +    psz_logvolid[0] = 0;
> +
> +  if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, p_logvol,
> p_udf->lvd_lba, 1) )
>      return 0;
>
> -  logvolid_len = (p_logvol->logvol_id[127]+1)/2;
> -  if (i_logvolid > logvolid_len)
> -    i_logvolid = logvolid_len;
> +  r = unicode16_decode((uint8_t *) p_logvol->logvol_id,
> p_logvol->logvol_id[127]);
> +  if (r == NULL)
> +    return 0;
> +
> +  logvolid_len = strlen(r)+1;  /* +1 for NUL terminator */
> +  if (psz_logvolid != NULL) {
> +    strncpy(psz_logvolid, r, MIN(logvolid_len, i_logvolid));
> +    psz_logvolid[i_logvolid-1] = 0;    /* strncpy does not always
> terminate the dest */
> +  }
> +  free(r);
>
> -  unicode16_decode((uint8_t *) p_logvol->logvol_id, 2*i_logvolid,
> psz_logvolid);
>    return logvolid_len;
>  }
>
> @@ -651,6 +688,7 @@ udf_dirent_t *
>  udf_readdir(udf_dirent_t *p_udf_dirent)
>  {
>    udf_t *p_udf;
> +  uint8_t* p;
>
>    if (p_udf_dirent->dir_left <= 0) {
>      udf_dirent_free(p_udf_dirent);
> @@ -710,13 +748,9 @@ udf_readdir(udf_dirent_t *p_udf_dirent)
>                 return NULL;
>         }
>
> -       if (strlen(p_udf_dirent->psz_name) < i_len)
> -         p_udf_dirent->psz_name = (char *)
> -           realloc(p_udf_dirent->psz_name, sizeof(char)*i_len+1);
> -
> -       unicode16_decode(p_udf_dirent->fid->u.imp_use.data
> -                        + p_udf_dirent->fid->u.i_imp_use,
> -                        i_len, p_udf_dirent->psz_name);
> +       free_and_null(p_udf_dirent->psz_name);
> +       p = (uint8_t*)p_udf_dirent->fid->u.imp_use.data +
> p_udf_dirent->fid->u.i_imp_use;
> +       p_udf_dirent->psz_name = unicode16_decode(p, i_len);
>        }
>        return p_udf_dirent;
>      }
> diff --git a/test/check_fuzzyiso.sh b/test/check_fuzzyiso.sh
> index 0eb71d9..cef7a5a 100755
> --- a/test/check_fuzzyiso.sh
> +++ b/test/check_fuzzyiso.sh
> @@ -22,7 +22,7 @@ fi
>  cd $srcdir; src_dir=`pwd`
>  for file in $src_dir/data/*.bin $src_dir/data/*.iso $src_dir/data/*.nrg ;
> do
>    case "$file" in
> -  $src_dir/data/p1.nrg | $src_dir/data/p1.bin | $src_dir/data/cdda.bin |
> $src_dir/data/cdda-mcn.nrg | $src_dir/data/svcdgs.nrg |
> $src_dir/data/cdtext.bin )
> +  $src_dir/data/p1.nrg | $src_dir/data/p1.bin | $src_dir/data/cdda.bin |
> $src_dir/data/cdda-mcn.nrg | $src_dir/data/svcdgs.nrg |
> $src_dir/data/cdtext.bin | $src_dir/data/udf102.iso )
>      good_rc=1
>      ;;
>    *)
> diff --git a/test/data/udf102.iso b/test/data/udf102.iso
> index
> 9e088313db7e397052e6a764757643078a41c8f7..2639d0d451f920c69511b6a58bc453a3b05b03b1
> 100644
> GIT binary patch
> delta 1545
> zcmd5+O-vI}5T4mxwvUZ9+q7V*2B}CiMoVca6fQy&address@hidden&Hnvf>m
> address@hidden@`7^V$bcw~pgoE?)_Px%VdEd-8Z(4BL
> z3x&address@hidden)2qKYPq+7FmlSl7O08|$KbQpr7plUOu-e%(bpqEBp-zal9HzhoitK3
> z<B*|mKdqIKAbocU&tp`^)1prb#G%eZCniQSH>R$(OebQgSUMK>+|address@hidden
> zsMy+gUAF{k`g_8h>6M1S{RpyMU^ehaxFsCNU<oHg)m!S8N#3pGJ#0(E#Aksa1wd!K
> zs#Vfwg;Dc=A*)address@hidden&=~XzJ{6DBz!p&v;k1Ug_m{{p1z!0
> zp#$dKoBDsvd;J<kJk#r7hx7}K{yX*cNxERzb}%9RCO-WO`#;H$*-sL4+s^)7V!!Ps
> zA;{)w=;PveUYlDi){z8CxYsg;Hb1Bc|E6a$ci~o~m{*E<wV2n6`MP3WFXnx=>C9~Z
> address@hidden)?7}MI)E6UlRa|obM5BsM<K7TL)1S
> zKL`%M!RM2+w>8_$saBuRMn96)*|$uMzb+arWXB6h3;Zg}!%+FvllGE(R{iZIdyD<t
> zwb{mvzNH$ph3O885_BTs10fo(gc}3vc`^pYPOW=fXbtbkB6~3m+>vDKx+?N(Rs>V8
> zN%45?aQO(Rc{idbW0o2nXyc-f(;s_7-izm!EBU%BrC+!1Sv!4#cZKP6g=-fuLXFY>
> z`f~bBJ5EMp-u>L<Y=bBNT}LW^DqbGA7R&>aU*Unl>X-*3-jPUlrn<V*JvM&NT1!GR
> R+Q|V|9UM_!>=fU8zX2rRFfafB
>
> literal 784384
> zcmeI*Yj<4Nec$l`Em8Eusg%^YDA!{;jz}4zNXn8$Q*k^5h9qnfpmCAHUOfN~h_Qef
> zWCkFG-c}yx9rOh>t6g2oD{0?AS6)E-AXzIfp!YUy)%(address@hidden
> z00(Ez+559E|GoFw1GHLvAb<address@hidden<address@hidden
> zfB*srAb<address@hidden<address@hidden<address@hidden
> z0tg_000IagfB*srAb<address@hidden<address@hidden
> zAb<address@hidden|s;address@hidden&address@hidden|L^)!gq?-#_WIPMh<;
> z*12=7b~>r;1L<S#j6a`mJ)N%hbnBeIKiAql`~0)7x6bLO>address@hidden
> address@hidden)hn;Q`r2iEoO|qmkIsIyX20>*uDE<4fB*uY
> z1c5U-{<n(v{IAtoZgpE5N^$*pldM$n|0^$dC&%i(P&YW|f3xxbb2^Yd=AQEB^R2US
> zWbW*f;(x0?H9xGQt<address@hidden)Edg+M(apl4O)Hud!X-ETPv-*AG6N~^Z!7J_&_H;
> address@hidden&>E;(S5?0R(=;0)JA){~vKWxIF?0Ab<address@hidden>cKQZge|d|K|e%1Q0*~
> z0R%on0?TWwm#-54KSL!>RuMn|0R#|ewbq&cQw<P6009ILKmY**5I_I{1Q0*~0R#|0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL__G$6Yn^HR?bclD_x|ABxnkzx
> z&rSZ|@65sJm(address@hidden|8ju;oqOf-;<c~ey!zUL{=KfRr|14KzWRyQ%G!FTSQzdf
> zjLPx2+%7f-{jK44`GIf#QD6UoZ<J1a<GDY4=Iry&Ui*T-eX(address@hidden
> address@hidden@P<(pcgk5Zx(mnES3g4vjOSMT#iQ{F;>3M
> z*y7J9XHUG$Gf(`<$MFMV`^TZmH4#7n0R%pxz|)HV&address@hidden&=XI?!`WIt>uf`t+
> address@hidden<G#fcVl1=gkI$bgBY*$`2z<H)&MM+Rqlkaz#UIRlSy}m<address@hidden
> z-=9++UW`n5A;S*^_WHfSp|f^oE^?>`7XEJfaaLcZwU1BuTKsdZ*0-G2vys|q2KWjA
> address@hidden<=4P~_Wx_FU^%^tz`$#A`Vf0R#|0009I(odV|+|address@hidden
> zsYU<+1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
> z1Q0;r6DOd*{L}h-`u)address@hidden
> zzt{Ek%(Z?9U;address@hidden@avxN_X}Gs{(|address@hidden
> z4=C`IVt8LseEpB#ox7sfq`!gZKbv>w&0=Y=Gn~23nYkQ~KJ9-Wa3)V5`<KM_kDZts
> zAb<address@hidden>frxpJ%D(c_+!Mk%;_3|_N7h{00F0ZX#_K{EKhtsG<h}Mrgc~6M3%$`4)
> zWk;$IKmY**e)Ixo74d&Y5&z7KKbU((address@hidden<^l6{ppHm)Qj7)eTV_~>|u-ESm4xP0#
> zbCE+mu<&=&kF)wRt$lQEcRP#4aygn^`p{25A)|@sTCHz6t!E>(`ic((5I_I{1U|gL
> address@hidden@4Iuae#+8LauGlP0R#|0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#~EqzZgq
> zzyJ5=^!tC$-Fp~+S7!F_($D^dnJ>Oi27K<Ne9i~?n|was|IW<$zx+ZzA%Fk^2q1vK
> address@hidden|address@hidden|0009ILKmY**5I_I{1Q0*~0R#|0009IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0;L|E_rgf(EPg--Wxj%YW
> z|EFC1R;yJwGx~hlpZP!l0R#|00D;B{%(b3Y)OX<L0|5jOKmY**J}Ux_{But;0Qjtw
> zH~B;W0R#|0zyfovv&{dg3J4&800Ibn#sp&if0p_GXRO%CE&>Q3fWT*5;Cwv)k7oeq
> zOmVKYd-nNfUvHf|address@hidden<brmu1H_U>H!%*(&v3wm+k^9w8Y
> z?k_Fhx_-q!<pTi(5I_I{1b);4=VSd}LHevhzdq{Xzn>7i#~E{9d!P9KldXl;O6y+h
> zeru_<+`84e-eMqNQ9ckr009IL_>address@hidden;WJtQxb_8o{W<;T
> zgYg6Z&>t&n>address@hidden;hTCQO;rsvpa~c73TO03x;>UBwGaqyMpZUni
> z)+p?R_lp6(v3N7k_xioTq3?0##7Q6du3P{C1Q0;rGbZq~;{U%;#ChTA-<`yrr(~e;
> z;!pbcQtMCh$KUzlG&X%Nem4DncHHo!uWLiri=Eru&SJ4#j)address@hidden>GSvW
> zPmd<}KmY**5I_Kdk03Co`2P<T?c2Zovk_PIl^+63#sbx)ecmtX=-<70A)nWJ*5`e$
> zIw3wkcWR~o#1Huf0R#|0009I(Ap)NN|0BiqfBf3-PGWhU|address@hidden;~pY!24
> ze{A~G_fPuzPc#4j$r&fl|9#)QFfsEJzC-{41Q0*~fe$0_`Og>nxV5}d-0CiOS37r#
> zdmA_IEG-oJ*Ii!gw$lkZ=go37?hgmW)%oJvM}xAsa_!occ3V%S4~|Fu2fK&address@hidden
> z`1-Z^_)&3lRF=isaOdz*Z&VgHhew0$-k~lqUn~u_F13Bz;?--#dbxkFR~Gm7dRygu
> zv3AryEQ?oOxjbLo7>*Bp_T5fVT)ukc%9WR{ymI;LMX|BgX&2px<>address@hidden
> zA0BEi!r`#kQgVvkV7u7vj}J%v%_Ch-=WgoO`~G3S9Jh<%PI0)aSMK$<%E7oSwuf6s
> z`{m$pzR>x_)^2a`pg(v}^bdXc!SJx??d=U8mD`uv;s~&Nqq4WZxmOCHSl=zHD~*et
> z;i%YG%8PN8bLW1$9QPj#QVI`yZ<address@hidden|!%IbR
> z<5=k)9FBTprSDMpioz-f<*2t;+&kJ-Cfav$MwHzC;IJHQr&~QZ>W#EtK;__D74LN`
> z|Eyi5`K6bXnti8pe54flrqz!u;&address@hidden)address@hidden
> zC(address@hidden(aU;+<6@|address@hidden(3!s`PqChr7ekSW5e<2RgHT
> zG)~2*Bwbh=?w9#xC+;;<Bd2##=C+2aF5=rfZdcfM`kSNP=(u=7&iaG#VcFZhbg?Mz
> address@hidden;address@hidden&D6psXZQ1;$-jSSU_dEP&AZ5Wk1<!I#W
> zNWiD4uFShmwhu-sbmeeGC0n1eaa>address@hidden@3N;qHK_nB!ssmVN+zT!fz
> address@hidden@address@hidden;}*>o%AWvlG#ZevwOo#kyqg_?`O9+YZphwbWx
> zs<irc=A}L-H;NOrQ7>2JE7YvFRJWw)address@hidden;YmqVE8DK=<99|UBh)1
> z<zet(9Hp~9bR|11w*qNYL=UIZQ>address@hidden
> zdTWk!lXNBLTR-cK-%dYL<3AdW+;DYV%`KgEsl6TvJ9!s1>G57q{hBVYRgMmO%COEj
> zP!jr^{k{I7o0<C|-!zG~YfIEOnpQZyAoK4JxBEM;address@hidden&ZxcI_-Jdl
> z=v9qVR=cI{Flwu*9;$NaGEP*l*eP`(r)~d8{p17Jh{$re)mJ$V)StLti9?Pn$<@uM
> za9vf6zhAxfRCU%%j-!FiPpX=3SXD3mR2|%;=IJ^e^(&KfjCWNfbdGxBR2dXi+z0vF
> z<02}IzUq(KRnfQ&tL8mkOH}U<cZ<VED$~RAVEm2Z!j+4v>{Xc5Rc6%HjM^8jUR2dp
> zJ5P0CHZnch?F-dL<M`oT`9QsXM7(iCW7h#)dVaQqb<address@hidden)>Q5I#-
> zB^KSM`rDip$9OkxQKbt1$gNTL3GH0r)ZSIs%PI;hwkrZ0>SehV=%(address@hidden
> zbR4&ge!^YNB-p4RmK=|#Dt=ugz90RtwDwCkrgG1{y^?m&i>address@hidden)FQo
> zQgU;VDVdL)address@hidden>EeaE2+vp?wV&Fda1OAa!EP-s`_E0&Ii+ecd|84-KNDqYo1
> address@hidden>B6Aq3JW6YB}m7BiRo~o#C65YM-6oE_`KHSxiLZMstQn<I}
> zp+d;address@hidden@gM)address@hidden
> zw)+qJ+ec1RG2D!fB;8~(o>7Y*6s78>@~QHVIHYz|T}Gc3hRQ=lM<r|Bou=x9tBWde
> z^p+7`_Iv8-6%Duc%AWf-rBDPpL#Z3soQ$EiQ`O8>OZ76O+{>address@hidden)N
> address@hidden;`tHV~<address@hidden(}4NZYavZ{4~Dhy53H;Z7a%3r+Tz^sr`jK_I;1Rv4*hg
> address@hidden|1>@2)H^-CSDe_<)B3
> zmoLT0scxv0t7B9W<address@hidden@d8|G3>VjbrbD2htwCM5UN^JG;address@hidden
> z1TKtyjX<S7sVL=kJDPF4E*ZucO?9(=c;ONk`}upR5}()TxfI-dJH{-k(P_vQVWFxp
> z%7atyCZO^w&PP@@d)`Q#n^ASO_I{~2SCr~Yb4<)XaWycDa?^jP5>xnytE9wFGrZS(
> z^o`V}-MZ8n_uTT*xtT3j=VJEC#ldjoDw75i^X;5~$sEEtaQ{AAWfZYem#a~Fip|^Z
> zJDmS0vG$(Y=27o~gV%-I>KWA$?1)&wD!;%tR5JU6t-T`;-hGRq<|2E24QW%g><^Ti
> zRJ)7wvv)address@hidden(bpINo`RBt0%RK6Pb*`
> zr1I0Aj*z37SJn2qD~{$~>i3oMaX*^8BB-wJe7maj+*|address@hidden
> zILEr0`cZWQo+at~Tv~0tq)N(g;NiAMe?I0JQ2Jtg*gy0PFc<r5MQc}uenH(}dElX!
> z`YqLX^;k~aW~uRcbX;mmH7UM$sjVTr(vv$hSF+KOr+U7Y`dp3fbKI#?tdVA!BEgkQ
> zX%M3(X#8jm(address@hidden>^Mea$QT(^gKH0))n~hf>?;Z!X|`}M8mgODt%{yk
> zRY65K7$5Yvj)q5L!9`m<&{^us6=QVdz|%?v7-b^H2sx3S*HmZe8r6s<address@hidden
> z>+efNiLN65_2TWaJaCh64alRrc6ym3UqmdAf7E1RfH0Xf>XLCxMYuUG2kPH+S?6tX
> zX^phE(;(7^Q>~sE2%Mx-MTo4#QI%M}PrJ7_RFS7~+q8zM!NgG0rKG93W;!u=&Ept#
> address@hidden@+p1M9ONFxd9HHeV)BF|x&pbsljl2=L30GU
> ztJ9hjeLz}8$hnFT=h6SET<0D$_iSzbG)=CKA};address@hidden)
> z@@INu*V;)aS<9Kb((Y|)l3i0TRW&r=-Y+#7bR|i-P()XC&address@hidden
> address@hidden(%dqPmf+0xK6#&gP}n|H2qaSaWz4pT3biY3o4(_kuH!Bxu_*22}K;-ylF
> zvM7qp$I=mX)A6}#Ycm1Xkt?^XJhfGy?(AqCLrY-#sT%G<Z=``z4(oAjoI;)Rb*c-@
> zp)address@hidden<#5N7AjkIUNJ$YY-$j|#m^{~Kot9c-f3!WhiYw5QMgqCP<m_)<tcLCr
> zdR5{WtPF;ueO+2zr<O+2+Ke>Q^3+J}MPYmIIA>lRtvcA5IbkYN*HO(address@hidden;
> zVYdiZy?D9TyYdBNDL{m&address@hidden&80-*B2M*4F+1D+$y~Y
> zn1gUMidf01dc0_4G5f2=TCN|xxIpd#qtK%ePS1TV=%${(address@hidden|X9h2VR
> zV)V*!Qmn4UaBXH-pK5%i9mN$_(9KUYm>fpSy}eY|%UG-{VzN6d9`?0Ra<Wg1t5n6T
> z;Y#<Ntunf+Z#cl3_Fgq<IUJXJ>Pk)&s#j3s5{`8d(kC?`;ipvs2dF7|6nz>Q7FCR{
> zax=YMHA48!qrMmDRCm)AHG-MF*rkgaxv%GSlQ`F<ss<2ia(b2XFsZN6St*3(=AnVg
> z(oS2&address@hidden;address@hidden)DG1K#>0WG7E8Gv8aV^A
> z;||xPaj7=!p2jyYs>address@hidden>Y;a5^>k&`%u$t8jBSka$)aqz^lKf~&3O}<Q
> zl5gMv#K~I=;f4lW)eB~OeA|tCT2Y-`R<Dk(M><s(lcpxB7qda7t+9k(ooi2IXquEf
> z;PwfrGmNz%(dAcFK}00eu<h=_3&7LmkTlOrgMi%msTP*+cu71DB-$=o6<*vXw~k!}
> zLRE~k9HKL0T_a^{qy?AJw!%pSRlTTq<S?xOsy=XCFVtvj@|eKMcYl-yl9ANx<jcpv
> zD6j0f4~l{6_%JOHr&T4N7S-#~$WJsh3W&t2-e?f2vb$cWf~b#AdihoY(K2)SPB}``
> zUnL^-Qog6391QnDeloz!*fSHT;Yh=|J+Ed|)2Z>KA<mYX^1P(hww<E!yh61kdk-F1
> zshTw9IZw)address@hidden>deot~6RE)7^`Q!#zE&(eOaCUOgikX=0W8
> z^z_8X`AcKp7;#6d*i38avPrcglvB6qQj1wi8gNYOS46p2rUR~O2sEv>sTZy~L}%f2
> z>J`NDw0bQMf3(=A7&YAdzP?xaq&0Ar-j>#i+}|j=?bpQLc7FZ1xDuh^sz$^bMLj;a
> zPlG6R23|address@hidden>c71iHKY53S)srtP&)N-`flodfADEMq?ZM=NR
> z!Q6?A&Ut1r)h*G>address@hidden(qg}0^k;o*L7)K~pi5KIe0)q-_2
> zv{4$3U03nXr;(address@hidden|{uBHH(q8=Gf|;y<+9{F^|TMwMgX-cQ~C^
> zs40)U>^M5qI3f+m^9V{~sr{iEfg<%F2KRA^Ek6O2eKkW+2GmKpWUZOuCP=EU>WD<1
> z?Bfcj#r0Fo6LWE%ESwYNpj2<BY)mfy-eqvAI?ec}oct-uK*Pev%OLfQCP+PnBT=5S
> zY7iCuuTO~riaRSO(=42-k26{JlFGV+LT^t&VxWtwQRp$GOHu<+Kekm%Pyx8u2E&1$
> z61u0<v~6;EcNmVq)iQ$87O$VA&nY{ohCT1wc%wB<address@hidden@3
> zd~Y)~W({3Da;YjvbPlPuMR%1}#8O(~v0!Qv`&G4wlXQMNuhgELnaMMrC*O20<@x2L
> z$MNgtC)F?CT>(K|address@hidden;address@hidden(&HW_EjusOnqVTBsk&+N1XvsPAZT
> zQe&o_{vg(6(@ZU&?~IMNM*RZ~X`;C+s#WpJZKJP;UR6o?nX6JY2|9l5G)Jlvw^i_3
> zvs1fLLfU%B8YQktbsEg306J5Rrj<cSjYoVAU3opuPxI6TsOiRlT$ODysGZayy-X`f
> z)p}*VvZyy>2GUls>|dPrv-`d8>u1iDdTEbNFQgng#c!(address@hidden&$
> zpQX7AIo7i!6}%Uj-0_~wzh_G7!HxzoZizHcZq?R^(ZhDvMEC#kO#Y;vg8a_Z!{oaE
> zRM)X~HhhVrS|^K&uJpBabq|?T=c3<=iEB><?`;rK8)BI{N+CB7=c?3jU0t(4PG2DE
> z#`NLcbS4~w(YToIbQI(address@hidden(|+pJ^B&-NG&($bV7jVrH-(okRr0EM`v;mdsZ^^x
> z%v|Kua?uQipBfa!*QR3z*CG>WtQ1dGHUEn(8{T&^e`3^fVl1KIoNKCUZ~0FAstt#b
> zY8|f%sWU?rKh5+4lWN7mVLQe+dPJmarV^;T{gdzR{?pHuQXPzEMS7^EP^>2mF{$@(
> zT=iPx1a+0w)A329pGj7G(heOw4eTLwJQSLAuHw-T0waxr6=J>6;RsQU(59DE8&a=h
> z*0_pFr9Y|`I#l7RglRf8EMiqpgwYpQ2^f|address@hidden&4eh1y2;$XLbh#QR
> zLQQ9zuG1<K)address@hidden>xa#DsKGE4uvacUR2NKUPwL;>W>I_cjE-tE6M^rG=
> zDtw|^xX3)?n;E*h^G<tjJn{F+iXV3={eDQds|^9}do_E|<B-YI`#e#6JU{9<*S&<K
> z-b%GoTVPUx+%|RRNnhvh-5gE~e7z{^g|FG+eznN1T_Db^A2{kETdp<9)AFf*o3ffh
> z16V(%Rwt;{*}cehngqIAR9JYQ2YV^SljO&vlPbB&N~lefnzuT<b}2na(O$7srjISS
> zRF{aM{`=(ELX(wfKW3k4K)Ld(psKn%>C)address@hidden>Sbg6TRd4)o!
> zZtwPA^DtDUd|##E6=}DlzJidej<U0JG}6no$6<C`i~9c)SsB0JV2~!8c|e+HuTig6
> z-CTwGgG;e`K5a>Phf12_XlAQQw&j{MZGq{j<!pBx`IuIWXrf=gq&address@hidden
> address@hidden;|address@hidden|3O8}(FVOp;#E?6g?z@;#dpN;p&
> z<D+tXao&TIsuntz$uS;ey0Tx;`iU`}sgx>>{9;6+>2h`BX-|Do$XZ;A0Z&iOBz7$L
> z+v*lUJ*9})si&aPmK`p<3hw((7KxwyT2%l=c%Q5VDtB2k^-A4l8jX+D+mE#kXx!gF
> address@hidden&dJ^n(E>-W{E|S>C1BH_vp--oD`xiui<N|
> address@hidden>%(`Zhm7~QNMFAk42O*nojwiL`X
> z?wN5ybr*Gh?sqgukgJ1MZn8?P!<9Ni9q<+nCBpq${!Y`#7*!}ADT~qb#Ka<R`P2oR
> zs)address@hidden)d=5!-ZW*i_VK948g3pMFM+05hYxO_F`P)*t`
> zm5%-(O@@^X?dpw2S;jg<address@hidden)m9P)gNiAtaqn)x2{WNv!{pKRTr)Se4f$h
> address@hidden<v6NPd-k?|g1U5K$?f216g^ngLaH>V
> z+f>PD`%YB#_%5}2H}z^ejmt0BQ!VtXs_KzNY-f(;x_F=!-LIDQG^Y=%zRuCTe34kq
> zPG|c0w{l(GeAlf=K4U-HnMvV6e#)0Zs5+v<@_`m7CUg6!nv+G26GfZ`{nc8F+M9YD
> z?Nd^vNFhF+Ep1H#%0WC9(KuX9<!+Q?IrLWR$(Ee<18>z;vvv!dES*iJ;address@hidden
> zlFsepNz#Uqs<ubhmFFZXG*!_UQF(si#;v_bZvHM*$Nx!n?P;(S6PfF70m3^vaI7<1
> z+C=s8_E0me7!GIx=N$!lJ|address@hidden)|N^lG&$
> zb%Qw)address@hidden>4^xkk6E=zMQGn3ZdE~?cK+2^J<o9gHt^B*O}T5)7MPH6}qi<e6pj9
> address@hidden&pOmb#8rQDnQ+}r0%R6UmNSjBDKQ;!d-&7m<d(l)KhZW=|T
> z)Kf<Fj`)<H<;M#(X7D`SYha#qsyS$^?~!u#z(4OLa<3RuuT;~kbUZ#gi5^|address@hidden
> zGpYnC?gyox6dq{$dU`2lX48w}nl{8l2}egf$%=REDS3(oCv;?xx_UQ>w49?pM6rEe
> z5BL?ZHA4&t$Am*K`==XdYrjIGo-}$3>z1}7IqSMs70@)uAF7Y>)0uH}=rc)FJ6El&
> z78q6gqgNbm=N3J^N(^4Ed9T;0ZSS*N(H;A$-51(RrzxD(qR73eSxXw;_Br-5eBY;j
> zXI35qcoggAq|eIUn)5b$jc7csn2PXPTZyO7+7+VCsA`0sc)H={yQa5CIEC6D?5zvR
> z?6x-l_4i!E^M<3ig*v&kgHrVB08|kN?zUr-Qofj5ulKcjLElBFGCtCl6Md>~R}7B!
> address@hidden@Ty`mARG`CTdL+{Y#oX>}wz9-S@>WzKE?ygP3#A1M?03fjKr0Z}!n
> zobJ)k*wD*}PMF2(2GrFiu_zQ($tqFGy$-qaIdQA1fK{|=d%oyRuRX6-z1H+y5Rc`3
> z`amO=v@|@cAy5sS*1G&yU4^!_JFLd}RRX<4R-c;address@hidden
> zF;<92WzJUBBdE*NI+l*4_n=hUM`JNS{n&{Xtm;yYcs;02HBFUJVNW$PRcKv0#RvEM
> z-b3%<d$jx56fHFm4JT1x@;q|VgT24}soS}LCL}ZM^?JO8L;I86$i`lH^*Ur;WK2&Z
> zT^LHyiiXYG-k|DEJk~JO@>JzL;address@hidden
> zivV%R<MNY(2UYZRrQyEzhUN?TO-BCOtzcB<FfyTv5rHm#tg_B;by{92-s-Hbc9z%g
> zdx7MN_O9LNE_625y2bkKZgFpQ<<@HFZn3mhy=82%xVhTx7AyLVrMEk)x4QE_Z?)?)
> zX0PQvvNIRZSu62<_czwN%j?BG?W<i{U+*p!H|`gmd-wEyw9bt?-QrH?EopXtW1)L*
> zy?E<(ce%ad%fGdx^ypX9`UOkN#apY|iMxC&F6fQ8t4p_TuNSvh?ksj!W4G?hx_i8^
> zxYt=-U+S*4m611>7EfmCd}mF`K3}}Gw0?VKL-)%N&Rl2te({~9<;D4;tDkmPm8N^E
> z-L<vuVq4c<x~mj-^~0s*g*zLIN{imnrYkJ3tjkF`Q##jIf~GpRy1Ejh>$mTASLL_7
> address@hidden<address@hidden>ax3%34=4CY9fkz*m>nzEgD8+8Oq{
> z8=c98q$~fso#llnsF`wbF*&=%{gn+}ZcX{Vqom&M8YoKIP~Bp&d$YT+zVxPwS7+)r
> zYa4eH-hzH(Z2;Z5Q!IBEl-|address@hidden;{!Locb2+Zd2i@
> zmUQ2A9oSgD<J_)xzq_IQ)YJrDqjO8O&6qRg-hOLIH+Ko0F8uj;iGDCG{QIg#D|(yZ
> z{USDIhqS7Pk~!JAeX>@lQcP=S=Y}*?wyK#+Q9+dugSdJxcJ6j=b=T(GlS&Y2%I~z)
> zyB+U!7nVAAqLQfUsjTlL6}|address@hidden>jgRX1KRUOg2Pq)hp
> z(|ez)f36pIR^+RzEq3%<og>Bie5328v)Wx&V~OU}Sy<RuRnzhreuXON+J+k2(sC3^
> z+xgXx)^9JZE>`Wy2Rg;g&eEL?RmGg(stW1OD<bqIqprE6qCl!jwx$(B*MVZ`rf#)x
> zJ2zclbhhAbt0-=Cby{cfO?3c^`95v6g|(&JZglIoLUxRf%?}6FO49i?8~DBV-=}E#
> z)address@hidden|d)address@hidden<address@hidden&pZ
> z4YL#kV$`5mpj9W&G25EU>Wy5QsJV02jT}kS)Gp7sJ!SA>f`gx)%j;e`M-gBD)1in#
> zdK=uySde0%<9)address@hidden<u)<3-ZH+k1-HGZEgA4c0;pDxKBY8!8Q<TM=`X+W*%(q!(K
> zv#bteDJFK~-j1{86i;3q?|F6RVt=0*VgpWobmkqHksUuuPwzlUdj>T?c&L5meqjvW
> zBcSTV)jrzvR=>address@hidden>@+rur~NU8KR+1`oY$OLn<Z?ZHKd_ucroeJ3Z8}_
> zzEeCZNO?5#jwTX*H?Zr-8{TITuUGCS?`F#Ydi%=2+ojT_wF#xvhPmys=iH`gq9!oj
> z75>e**1}|p<u_Bm;hhNI)E(jydPN%ad^6p5-9?^n6KV1gr3&address@hidden;(>I63
> zO?7Zm<av0jdpXzf&X*^=omclxo5W-M5*PAIo;*;RzL6qI>}pl-^Bl|1f8r_^R7h$h
> z8al_eLvMsUHGa<UrvWCzNTn!G!*;address@hidden&d1ICe(x%{yA!GcyvB9;
> z9T;jdX-enC7QZ2_s%J`nT;g<address@hidden@VWZR{^e^Q`plfwX)-Td(ul
> zq^qwhbw&H+3&(v=JjR?>CN0M7c+vE|hQRUqn{EZMoRi+uKmVtGKfm6Y;address@hidden
> zWRHkO%DbrtR-=#i4!HN!Xu0%Owb4+2dLUZXK~IB!b$orl87xm0XIe(I=d|Zo&p|yz
> zS8d4eD$x!yE#Fi-!_|&address@hidden<OM_yq)USKqG9;)jhPY
> zrdF?An?Lot5!{-K)E!LPaw`9sm+N7OdePV)(z&s=a%W?`d*}Y_xcPcac5-zn4v$sA
> zzZdUaee^>5r3%q3+(*s!2h-T&N!6or&-ZcndLjrYYPd&address@hidden>!nltrun!
> address@hidden;P}zWTlKBz;j<DY1HWuD_9X_Z*s}S39k>HapT&&Z-xx?ST|p
> zR(5m`y-PJ#YrJJG-_MoAu~RD*Uf%E{YqeXyi&SA!Q=c>wRktvxPg;H_ldi3}5$#`F
> zs`j-`TE4WUwJYt-b*n4~dZ4Mt?c<kTa!>Bis`Vp3osHfr*FVABS8{S@<NXbOuX~*0
> z-+VDV*2^xa!8y_K{4^HD^Q*N}Nt-|7eZiyl*b{i|3(?8y5;Ydk6H;address@hidden
> z8*t7?`B*kz%&address@hidden>o|JwSjnhw<4$aP(|18kTZ_zeSdhY#jJslm-Kr(
> z=Hua>nqYM!y<BtANhnQC#3Pj41?QWqVtsF>nY`e~W3gjU&address@hidden(u$<M#M(MO9q
> z+ANdz?CECTc4~^-y)EsHiQfN>w2{QWokF!_{a8(HIQXW1^N7Z3+AkQtheWr`KbY4T
> zO<address@hidden|IeZu<LWb=AjOjKT~^*`62+46OMhhEUoZR35gmA2>n>WWUD8`ejg
> zS}yhzG4(d_izOyYG=8EOyTjc<MYo?~m5Vy3L<address@hidden&address@hidden
> zj1ObX5mn7YP+fLg&)D5oTu&S>PW`Tn_PyAxGP4jGzw073O<address@hidden<vTV
> z`TkS={=d0DdUx)N{sn!%)oK;ah(2HTXFd=>009ILK%j8~j{pBG$N!%q{x`0C$q)hv
> zAb<address@hidden|2)V4pC<m-5pfIw1Q0*~fyN0q{`>F$dj0=ri2sc%UowOM0tg_0K%Ic&
> z|G&)f|7VH+bwnIP009ILK%j8~j{pBE$N%Sv|BWkOGK2sE2q1t!oq*&2zs~Xh=ZODx
> zL>xl^0R#|0pm73@|Nkb(|address@hidden;8ApX}8aSQ<j5I_Kd
> z#tAt7|8b80zexOVT=|kA1Q0*~0R-v<9RL4aj{m<z{I4V87y<|&fB*uG6L9?h_c{Lm
> zGV#B0<x7STKmY**5U3My{QnO*{ujjmIwFoCfB*srAka7g$NzV8{Qna1zj5VDh7dpi
> z0R#}J6L9?hk2(IIC;rzFaSQ<j5I_Kd#tAt7|EC=PzfAmZT=|kA1Q0*~0R-v<9RL4w
> zj{m<x{I4V87y<|&fB*uG6L9?hFFF2yh4|address@hidden<address@hidden;|9_SEUq{3-
> z1Q0*~0R$Q+;Q0UFa{PaR_}{qlB|``xfB*sr)CoBL|MwjKFA)Fhh&YA-0tg_0K;r})
> z|Nlph{}+k>jVoU=ga85vAb>!ffaCxF%<=z4;(r|x#}GgO0R#|eoPgv1|H|?ItHl4t
> zl`k1W009ILK%h>*@&AA4_&address@hidden&y{BK<Ok|6{TKmY**
> z>I5AB|8I`}mx%v$L>xl^0R#|0pm73@|Nk$?|CfpXjVoU=ga85vAb>!ffaCw4<oJJ?
> z_+LlFF$54m009IVC*b(address@hidden(8D)GOLh+_yKfB*sr
> zG)}<rKSlt5^zPg%#Q(;XFBw7r0R#|0piaQi|8sf%|25)&9TCS6KmY**5NMo$<Ns4R
> z{=Z86Z(RA3Ap{UW009K*1RVdL&hh^>;(r|x#}GgO0R#|eoPgv1*&P4BPW*3N`H~?7
> z5I_I{1nLAF|DVb6|8?Sj9TCS6KmY**5NMo$<NvuF|F04M8&|$$2mu5TKmdU{0muK(
> z=lK5(;(r|x#}GgO0R#|eoPgthJIDX)#Q(;XFBw7r0R#|0piaQ?|HpFte}nj6N5nA%
> z5I_I{1R5vc`2U3*|9_46-?;K6LkJ*%00Icq2{``$c#i+yB>vYCaSQ<j5I_Kd#tAt7
> z|G6Chf1UW>xbh`K2q1s}0tnOzIQ~DI<Nvpa|8+zhLjVB;address@hidden<@nzr{x`0C
> z$q)hvAb<address@hidden<t5yucf009ILXq<rK|4-)lzd-zNT=|kA1Q0*~0R-v<
> z9RL4(j{l3q|address@hidden)hvAb<address@hidden
> z5yucf009ILXq<rK|4--me~b9vxbh`K2q1s}0tnOzIR5`kj{mob|8+zhLjVB;address@hidden
> address@hidden&YA-0tg_0K;r})|9>vW|L+k0
> z8&|$$2mu5TKmdU{0muKJ&address@hidden;zK`H~?75I_I{
> z1nLAF|9>&Z|7GHT9TCS6KmY**5NMo$<Nq(address@hidden(RA3Ap{UW009K*1RVc=ImiEd
> z#Q!=Xjv;address@hidden|address@hidden
> z0*w=J{6C-L{~GbXapg;f5I_I{1Q4hbaQy#rj{ob#|2iU$A%Fk^2q4fn0muJe$?<=K
> z_}{qlB|``xfB*sr)CoBLe<jENH;MmsL>xl^0R#|0pm73@|G%2!|69cW#+5G_LI42-
> z5I~?#!14cu9RGiV_+LlFF$54m009IVC*b&hA;<sw#Q(;XFBw7r0R#|0piaQ?|6-2+
> ze}VX4N5nA%5I_I{1R5vc`2S*#|9_GA-?;K6LkJ*%00Icq2{`_LHOK$IMEtKK;ur!5
> zAb<address@hidden|00D(FI$N!gd{QoP&|2iU$A%Fk^2q4fn0muJK
> zIsX4u;(z1Hmkc3*00IagP$%H{|8kE1-y{Cl5pfIw1Q0*~fyN0q{$I}VzeoIUT=|kA
> z1Q0*~0R-v<address@hidden<address@hidden>0
> zCCC45;(r|x#}GgO0R#|eoPgv1*K+(XiT{l&UowOM0tg_0K%Ic&|EoFv?-2j%h&YA-
> z0tg_0K;r})|6j}T{{iv8apg;f5I_I{1Q4hbaQy#zj{m#F|2iU$A%Fk^2q4fn0muK>
> zbNufU{~K4nWC#HS5I_KdIswQ3YdQXZpZH%##4!XAKmY**8YkfR|BW2~-zNSyu6)T5
> z0tg_000MOaj{nzl{NE$~*Aa0H0R#|00D;B{IR3wp<NrSKzj5VDh7dpi0R#}J6L9?h
> zwH*Hk#Q!=Xjv;^m0tg_`I0481Z|3+vB>p$9e8~_32q1s}0(An8|G%E&{{iv8j)-Fj
> zAb<address@hidden>@&8*n{{JTNzj5VDh7dpi0R#}J6L9?R<oG`#{?`$43;_fXKmdWp2{``W
> z$nk$n{BK<Ok|6{TKmY**>I5AB7jpbRB>vYCaSQ<j5I_Kd#tAt7FXs4vMEq}D`H~?7
> z5I_I{1nLAF|GPQ<address@hidden;{}J)Oapg;f5I_I{1Q4hbaQwfO
> z<NrIv|2iU$A%Fk^2q4fn0muK_IsP9L{~K4nWC#HS5I_KdIswQ3r5ykN8u7o5h+_yK
> zfB*srG)}<r|JynK|8?Sj<I0x|A%Fk^2p~`=;address@hidden
> address@hidden<address@hidden@=~<|8Eih>xejp00IagfI#B}{y!Oxwp0KB
>
> diff --git a/test/testudf.c.in b/test/testudf.c.in
> index 210bd12..3d22c6e 100644
> --- a/test/testudf.c.in
> +++ b/test/testudf.c.in
> @@ -1,6 +1,6 @@
>  /*
>    Copyright (C) 2013 Rocky Bernstein <address@hidden>
> -  Copyright (C) 2013 Pete Batard <address@hidden>
> +  Copyright (C) 2013-2014 Pete Batard <address@hidden>
>
>    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
> @@ -44,18 +44,22 @@
>  #include <cdio/cdio.h>
>  #include <cdio/udf.h>
>
> +#define EXPECTED_NAME    "FÃ(c)жÎ~vrier"
> +#define EXPECTED_LENGTH  10
> +
>  int
>  main(int argc, const char *argv[])
>  {
>    char const *psz_fname = UDF_IMAGE;
>    char volume_id[192];         /* 3*64 to account for UTF-8 */
>    udf_t* p_udf = NULL;
> -  udf_dirent_t* p_udf_root;
> +  udf_dirent_t *p_udf_root, *p_udf_file;
> +  int64_t file_length;
>
>    p_udf = udf_open(psz_fname);
>
>    if (NULL == p_udf) {
> -    fprintf(stderr, "Sorry, couldn't open %s as an UDF image\n",
> +    fprintf(stderr, "Couldn't open %s as an UDF image\n",
>        psz_fname);
>      return 1;
>    }
> @@ -66,14 +70,26 @@ main(int argc, const char *argv[])
>      return 2;
>    }
>
> -  if (udf_get_logical_volume_id(p_udf, volume_id, sizeof(volume_id)) <=
> 0) {
> -    fprintf(stderr, "UDF image %s has no logical volume ID\n",
> -      psz_fname);
> +  if ( (udf_get_logical_volume_id(p_udf, volume_id, sizeof(volume_id)) <=
> 0)
> +    || (strcmp(EXPECTED_NAME, volume_id) != 0) ) {
> +    fprintf(stderr, "Unexpected UDF logical volume ID\n");
>      return 3;
>    }
> -  printf("-- Volume id: %s\n", volume_id);
> +  printf("-- Good! Volume id matches expected UTF-8 data\n");
>
> -  udf_close(p_udf);
> +  p_udf_file = udf_fopen(p_udf_root, EXPECTED_NAME);
> +  if (!p_udf_file) {
> +    fprintf(stderr, "Could not locate expected file in UDF image\n");
> +    return 4;
> +  }
> +  printf("-- Good! File name matches expected UTF-8 data\n");
> +
> +  file_length = udf_get_file_length(p_udf_file);
> +  if (file_length != EXPECTED_LENGTH) {
> +    fprintf(stderr, "Unexpected UDF file length\n");
> +    return 5;
> +  }
> +  printf("-- Good! File length matches expected length\n");
>
>    return 0;
>  }
> --
> 1.8.5.2.msysgit.0
>
>
>


reply via email to

[Prev in Thread] Current Thread [Next in Thread]