Ticket #458: win32_read_dir.patch

File win32_read_dir.patch, 5.9 KB (added by Kroward 1, 13 years ago)

Win32: WCHAR support it ngx_read_dir() to enable Unicode in autoindex

  • src/os/win32/ngx_files.c

    # HG changeset patch
    # User K
    # Date 1386335779 -7200
    #      Fri Dec 06 15:16:19 2013 +0200
    # Node ID da3b8749f162ff4849633e32bd19eabb4370a688
    # Parent  fedf777c6b24651d4dd86310334521ace0b2139b
    Win32: WCHAR support it ngx_read_dir() to enable Unicode in autoindex
    
    Functions ngx_open_dir() and ngx_read_dir() are refactored to use WCHAR file names.
    UTF-8 version of file name is cached in additional buffer.
    
    diff -r fedf777c6b24 -r da3b8749f162 src/os/win32/ngx_files.c
    a b  
    426426ngx_int_t
    427427ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir)
    428428{
     429    size_t      len;
     430    u_short    *u;
     431    u_short     utf16[NGX_UTF16_BUFLEN];
     432
    429433    ngx_cpystrn(name->data + name->len, NGX_DIR_MASK, NGX_DIR_MASK_LEN + 1);
    430434
    431     dir->dir = FindFirstFile((const char *) name->data, &dir->finddata);
     435    len = NGX_UTF16_BUFLEN;
     436    u = ngx_utf8_to_utf16(utf16, name->data, &len);
     437
     438    if (u == NULL) {
     439        return NGX_ERROR;
     440    }
     441   
     442    dir->namelen = 0; // clear cached utf-8 buffer
     443    dir->dir = FindFirstFileW(u, &dir->finddata);
    432444
    433445    if (dir->dir == INVALID_HANDLE_VALUE) {
    434446        return NGX_ERROR;
     
    441453}
    442454
    443455
     456
     457
    444458ngx_int_t
    445459ngx_read_dir(ngx_dir_t *dir)
    446460{
     
    449463        return NGX_OK;
    450464    }
    451465
    452     if (FindNextFile(dir->dir, &dir->finddata) != 0) {
     466    dir->namelen = 0; // clear cached utf-8 buffer
     467    if (FindNextFileW(dir->dir, &dir->finddata) != 0) {
    453468        dir->type = 1;
    454469        return NGX_OK;
    455470    }
     
    574589    }
    575590}
    576591
     592static u_char *
     593ngx_utf8_encode_char(u_long ch, u_char *str) {
     594    if (ch <= 0x7f) {
     595        *str++ = (u_char)ch;
     596    } else if (ch <= 0x0007ff) {
     597        *str++ = (u_char)(0xc0 | (ch >>  6) & 0x1f);
     598        *str++ = (u_char)(0x80 | (ch & 0x3f));
     599    } else if (ch <= 0x00ffff) {
     600        *str++ = (u_char)(0xe0 | (ch >> 12) & 0x0f);
     601        *str++ = (u_char)(0x80 | (ch >>  6) & 0x3f);
     602        *str++ = (u_char)(0x80 | (ch & 0x3f));
     603    } else if (ch <= 0x10ffff) {
     604        *str++ = (u_char)(0xf0 | (ch >> 18) & 0x07);
     605        *str++ = (u_char)(0x80 | (ch >> 12) & 0x3f);
     606        *str++ = (u_char)(0x80 | (ch >>  6) & 0x3f);
     607        *str++ = (u_char)(0x80 | (ch & 0x3f));
     608    }
     609    return str;
     610}
     611
     612static u_char *
     613ngx_utf16_to_utf8(u_char *utf8, u_short *utf16, size_t *len)
     614{
     615    u_short   *u;
     616    u_char    *p;
     617    u_long    surrogate;
     618
     619    p = utf8;
     620    u = utf16;
     621
     622    for ( ;; ) {
     623
     624        if ((*u >= 0xd800) && (*u <= 0xdbff)) {
     625            surrogate = (*u - 0xd800) << 10;
     626            if (!((*(u+1) >= 0xdc00) && (*(u+1) <= 0xdfff))) {
     627                // Broken surrogate pair, out as is
     628                p = ngx_utf8_encode_char(*u, p);
     629            }
     630        } else if ((*u >= 0xdc00) && (*u <= 0xdfff)) {
     631            surrogate |= *u - 0xdc00;
     632            p = ngx_utf8_encode_char(surrogate + 0x10000, p);
     633        } else {
     634            p = ngx_utf8_encode_char(*u, p);
     635        }
     636       
     637        if (*u == 0) {
     638            *len = p - utf8 - 1;
     639            return utf8;
     640        }
     641       
     642        u++;
     643    }
     644
     645    /* unreachable */
     646}
     647
     648
     649u_char *
     650ngx_de_name(ngx_dir_t *dir)
     651{
     652    size_t   len;
     653    u_char  *u;
     654   
     655    if (!dir->namelen) {
     656        len = NGX_UTF8_BUFLEN;
     657        u = ngx_utf16_to_utf8(dir->name, dir->finddata.cFileName, &len);
     658        dir->namelen = len;
     659    }
     660    return dir->name;
     661}
     662
     663
     664size_t
     665ngx_de_namelen(ngx_dir_t *dir)
     666{
     667    if (!dir->namelen) {
     668        ngx_de_name(dir);
     669    }
     670    return dir->namelen;
     671}
     672
    577673
    578674ngx_int_t
    579675ngx_de_info(u_char *name, ngx_dir_t *dir)
     
    801897
    802898        n = ngx_utf8_decode(&p, 4);
    803899
    804         if (n > 0xffff) {
     900        if (n > 0x10ffff) {
    805901            ngx_set_errno(NGX_EILSEQ);
    806902            return NULL;
    807903        }
    808904
    809         *u++ = (u_short) n;
     905        if (n > 0xffff) {
     906            // LE order
     907            *u++ = (u_short) (0xd800 | ( ((n >> 16) & 0x1f) - 1 ) << 6 | (n & 0xffff) >> 10); // high surrogate
     908            // ??? check buffer length ???
     909            *u++ = (u_short) (0xdc00 | n & 0x3ff); // low surrogate
     910        } else {
     911            *u++ = (u_short) n;
     912        }
    810913    }
    811914
    812915    /* the given buffer is not enough, allocate a new one */
     
    838941
    839942        n = ngx_utf8_decode(&p, 4);
    840943
    841         if (n > 0xffff) {
     944        if (n > 0x10ffff) {
    842945            free(utf16);
    843946            ngx_set_errno(NGX_EILSEQ);
    844947            return NULL;
    845948        }
    846949
    847         *u++ = (u_short) n;
     950        if (n > 0xffff) {
     951            // LE order
     952            *u++ = (u_short) (0xd800 | ( ((n >> 16) & 0x1f) - 1 ) << 6 | (n & 0xffff) >> 10); // high surrogate
     953            // ??? check buffer length ???
     954            *u++ = (u_short) (0xdc00 | n & 0x3ff); // low surrogate
     955        } else {
     956            *u++ = (u_short) n;
     957        }
    848958    }
    849959
    850960    /* unreachable */
  • src/os/win32/ngx_files.h

    diff -r fedf777c6b24 -r da3b8749f162 src/os/win32/ngx_files.h
    a b  
    2828} ngx_file_mapping_t;
    2929
    3030
     31/* Windows defines MAX_PATH as 260 */
     32#define NGX_UTF8_BUFLEN  ((MAX_PATH-1)*4+1) /* utf-8 char takes at most 4 bytes for U+10FFFF range */
     33
     34
    3135typedef struct {
    3236    HANDLE                          dir;
    33     WIN32_FIND_DATA                 finddata;
     37    WIN32_FIND_DATAW                finddata;
     38    u_char                          name[NGX_UTF8_BUFLEN];
     39    size_t                          namelen;
    3440
    3541    unsigned                        valid_info:1;
    3642    unsigned                        type:1;
     
    208214#define ngx_dir_access(a)           (a)
    209215
    210216
    211 #define ngx_de_name(dir)            ((u_char *) (dir)->finddata.cFileName)
    212 #define ngx_de_namelen(dir)         ngx_strlen((dir)->finddata.cFileName)
     217u_char *ngx_de_name(ngx_dir_t *dir);
     218size_t ngx_de_namelen(ngx_dir_t *dir);
    213219
    214220ngx_int_t ngx_de_info(u_char *name, ngx_dir_t *dir);
    215221#define ngx_de_info_n               "dummy()"