Từ 1 tới 6 trên tổng số 6 kết quả

Đề tài: Lập trình C | Tìm hiểu về cấu trúc file ZIP

  1. #1
    Ngày gia nhập
    09 2006
    Nơi ở
    /usr/share/.hack@
    Bài viết
    1,433

    Talking Lập trình C | Tìm hiểu về cấu trúc file ZIP

    Hôm nay rảnh, X làm một hướng dẫn về cách đọc cấu trúc file ZIP nhé.

    1. Đề tài:

    TÌM HIỂU CẤU TRÚC FILE <ZIP>

    2. Yêu cầu

    - Có hiểu biết cơ bản về ngôn ngữ lập trình C (chú ý: C99)
    - Biết lập trình (hiểu biết thì chưa đủ )
    - Biết đọc tiếng Anh hoặc biết dịch
    - Có một bộ C compiler (VC++, GCC, Intel C Compiler...gì cũng được)

    3. Độ Khó

    - Medium

    4. Bắt đầu tìm hiểu



    [1] - Tìm hiểu sơ lược về cấu trúc file ZIP

    Thông tin tra cứu:
    Code:
    http://www.pkware.com/documents/casestudies/APPNOTE.TXT

    1. Cấu trúc chung của file ZIP:

    Code:
       [local file header 1]
        [file data 1]
        [data descriptor 1]
        . 
        .
        .
        [local file header n]
        [file data n]
        [data descriptor n]
        [archive decryption header] 
        [archive extra data record] 
        [central directory]
        [zip64 end of central directory record]
        [zip64 end of central directory locator] 
        [end of central directory record]


    - Chú ý: các giá trị được lưu dưới dạng little-endian byte order (nếu không biết nó là cái gì thì xin mời: GOOGLE.COM.VN)

    1-A. Local file header:

    Code:
           local file header signature     4 bytes  (0x04034b50)
            version needed to extract       2 bytes
            general purpose bit flag        2 bytes
            compression method              2 bytes
            last mod file time              2 bytes
            last mod file date              2 bytes
            crc-32                          4 bytes
            compressed size                 4 bytes
            uncompressed size               4 bytes
            file name length                2 bytes
            extra field length              2 bytes
    
            file name (variable size)
            extra field (variable size)


    ....đọc hết cái trong thông tin tra cứu ở trên -> tớ đỡ phải copy mệt lắm

    None!

  2. #2
    Ngày gia nhập
    09 2006
    Nơi ở
    /usr/share/.hack@
    Bài viết
    1,433

    Arrow Local File Header

    [2] Ví dụ xử lý khúc dạo đầu Local File Header

    - Đọc khúc trên cho hiểu nha

    - Giờ thực tập

    Bài 1:
    - Tạo một file ZIP
    - Viết chương trình C đơn giản trả về kích thước của file đầu tiên trong gói ZIP.
    - Kích thước bao gồm: kích thước sau khi nén và kích thước trước khi nén.
    - Viết thành dưới dạng hàm để re-use

    Cách làm:
    C Code:
    1. #include <stdio.h>
    2.  
    3. #define    COMPRESSED_SIZE_OFFSET   18
    4. #define    UNCOMPRESSED_SIZE_OFFSET 22
    5. #define BLOCK                    01
    6.  
    7. long get_csize(const char* file_name);
    8. long get_ucsize(const char* file_name);
    9.  
    10. // EP
    11. int main(void)
    12. {
    13.     // file location
    14.     const char* file_name = "C:\\test.zip";
    15.     // in ra
    16.     printf("Compressed   size: %d\n", get_csize (file_name));
    17.     printf("Uncompressed size: %d\n", get_ucsize(file_name));
    18.     return 0;
    19. }
    20.  
    21. long get_csize(const char* file_name)
    22. {
    23.     FILE* fp;
    24.     long size;
    25.     fp = fopen(file_name,"rb"); // doc file duoi dang binary
    26.     if(!fp)
    27.         return -1;
    28.     fseek(fp, COMPRESSED_SIZE_OFFSET, SEEK_SET); // nhay toi offset 18 <-- compressed
    29.     fread(&size, 4, BLOCK, fp); // lay kich thuoc: 4 bytes
    30.     fclose(fp);
    31.     return size;
    32. }
    33. long get_ucsize(const char* file_name)
    34. {
    35.     FILE* fp;
    36.     long size;
    37.     fp = fopen(file_name,"rb");
    38.     if(!fp)
    39.         return -1;
    40.     fseek(fp, UNCOMPRESSED_SIZE_OFFSET, SEEK_SET); // nhay toi offset 22 <-- uncompressed
    41.     fread(&size, 4, BLOCK, fp); // lay kich thuoc: 4 bytes
    42.     fclose(fp);
    43.     return size;
    44. }

    Code trên là mình chém địa chỉ (offset) để lấy giá trị (value). Dành cho các bạn mới nhập môn cho dễ hiểu.
    Về cơ bản thực dụng ta sẽ sử dụng kiểu Cấu Trúc (struct) để xử lý.

    Sau đây là một số bài tập để các bạn tập tành cho quen với xử lý header structure:

    Bài 2:
    - Tạo một gói file ZIP (1 file thôi). Ví dụ: test.zip (có 1 file: test.txt)
    - Viết chương trình C đơn giản lấy tên của file duy nhất trong gói ZIP.

    Bài 3:
    - Xác định độ nén của 1 file ZIP bất kì

    Bài 4:
    - Tạo một gói file ZIP (1 file thôi). Ví dụ: test.zip (có 1 file: test.txt)
    - In ra tất cả các trường trong cấu trúc Local File Header đầu tiên

    Xin mời ^^!

    Hướng dẫn giải các bài ở mục [2]

    Để đảm bào tính an toàn khi đọc cấu trúc, mình tạo một cấu trúc rồi đọc lần lượt từng byte một. Như vậy cả 3 bài sẽ được giải quyết gọn lẹ hơn.

    Để code đơn giản mình tạo 3 file: zip.h - zip.cpp - main.cpp

    A) zip.h
    C++ Code:
    1. /*
    2.  * @author Xcross87
    3.  * @date   10 Oct 2008
    4.  */
    5. #ifndef _ZIP_
    6. #define _ZIP_
    7.  
    8. #define SHORT short
    9. #define WORD  unsigned int
    10.  
    11. typedef struct _zip_local_file_header {
    12.     WORD signature;
    13.     SHORT version;
    14.     SHORT bit_flag;
    15.     SHORT compression_method;
    16.     SHORT lmf_time;
    17.     SHORT lmf_date;
    18.     WORD crc32;
    19.     WORD csize;
    20.     WORD ucsize;
    21.     SHORT fn_length;
    22.     SHORT ex_length;
    23. } ZIP_LOCAL_FILE_HEADER;
    24.  
    25. void  read_lfh(ZIP_LOCAL_FILE_HEADER* lfh, FILE* fp);
    26. char* get_fname(ZIP_LOCAL_FILE_HEADER* lfh, FILE* fp);
    27.  
    28. #endif // _ZIP_

    B) zip.cpp
    C++ Code:
    1. /*
    2.  * @author Xcross87
    3.  * @date   10 Oct 2008
    4.  */
    5. #include <stdio.h>
    6. #include <stdlib.h>
    7. #include "zip.h"
    8.  
    9. void read_lfh(ZIP_LOCAL_FILE_HEADER* lfh, FILE* fp)
    10. {
    11.     if(fp != (FILE*) NULL) {
    12.         fseek(fp, 0, SEEK_SET);
    13.         fread(&lfh->signature,          sizeof(WORD),  1, fp);
    14.         fread(&lfh->version,            sizeof(SHORT), 1, fp);
    15.         fread(&lfh->bit_flag,           sizeof(SHORT), 1, fp);
    16.         fread(&lfh->compression_method, sizeof(SHORT), 1, fp);
    17.         fread(&lfh->lmf_time,            sizeof(SHORT), 1, fp);
    18.         fread(&lfh->lmf_date,            sizeof(SHORT), 1, fp);
    19.         fread(&lfh->crc32,                sizeof(WORD),  1, fp);
    20.         fread(&lfh->csize,                sizeof(WORD),  1, fp);
    21.         fread(&lfh->ucsize,                sizeof(WORD),  1, fp);
    22.         fread(&lfh->fn_length,            sizeof(SHORT), 1, fp);
    23.         fread(&lfh->ex_length,            sizeof(SHORT), 1, fp);        
    24.     }
    25. }
    26.  
    27. char* get_fname(ZIP_LOCAL_FILE_HEADER* lfh, FILE* fp)
    28. {
    29.     int fn_len = lfh->fn_length; // lay do dai ten file
    30.     // khoi tao chuoi: do dai ten file + 1
    31.     char* fname = (char*) malloc( sizeof(char) * fn_len + sizeof(char));
    32.     fseek(fp, 30, SEEK_SET); // dat con tro voi OFFSET: 30
    33.     fread(fname, sizeof(char), fn_len, fp); // lay ten file
    34.     *(fname + fn_len) = 0; // ket thuc chuoi \0
    35.     return fname;
    36. }

    C) main.cpp
    C++ Code:
    1. /*
    2.  * @author Xcross87
    3.  * @date   10 Oct 2008
    4.  */
    5. #include <stdio.h>
    6. #include <stdlib.h>
    7. #include <malloc.h>
    8. #include "zip.h"
    9.  
    10. // EP
    11. int main(void)
    12. {
    13.     // file location
    14.     const char* file_name = "C:\\test.zip";
    15.  
    16.     ZIP_LOCAL_FILE_HEADER* lfh;
    17.     FILE* fp;
    18.  
    19.     fp = fopen(file_name, "rb");
    20.     lfh = (ZIP_LOCAL_FILE_HEADER*) malloc(sizeof(ZIP_LOCAL_FILE_HEADER));
    21.     if(!fp) return -1;
    22.  
    23.     read_lfh(lfh, fp);
    24.  
    25.     printf("name: %s \n", get_fname(lfh, fp));
    26.  
    27.     return 0;
    28. }

    Bài rất đơn giản không có gì phức tạp chuyên môn hóa cả
    Attached Thumbnails Attached Thumbnails ZIPformat.jpg  
    None!

  3. #3
    Ngày gia nhập
    09 2006
    Nơi ở
    /usr/share/.hack@
    Bài viết
    1,433

    Red face [Magic Bytes]

    Tạm dừng về cấu trúc của file ZIP, ta bàn sang một vấn đề khác về nhận dạng format.

    File ZIP được xác nhận trong Magic Bytes với mã:
    Code:
    504Bh
    0x504B
    Offset: 0x00
    => tương ứng với P K hay là 1 kí tự đầu của tác giả tạo ra file ZIP (Phil Katz)
    <chú ý: little-high byte order hoặc little-high word order [Intel]>

    Lấy ra 2 bytes này
    C++ Code:
    1. #include <stdio.h>
    2.  
    3. #define LOW_WORD 0x504B
    4.  
    5.  
    6. int main(void)
    7. {
    8.     FILE* fp;
    9.     char list[2];
    10.     fp = fopen("C:\\test.zip", "rb"); // ban tu them vao cai if(!fp) nhe
    11.  
    12.     // offset 0x00 : magic byte: 0x50 0x4B (PK)
    13.     fread(list, sizeof(char), 2, fp);
    14.     printf("%c %c", list[0], list[1]); // in ra
    15.     fclose(fp);
    16.  
    17.     return 0;
    18. }

    Từ điểm này bạn có thể tạo một ứng dụng kiểm tra xem một file có phải là file ZIP không ^^!

    Zui zẻ nha
    None!

  4. #4
    Ngày gia nhập
    09 2006
    Nơi ở
    /usr/share/.hack@
    Bài viết
    1,433

    Wink [2] Thống kê

    Code:
    LOCAL FILE HEADER
    -----------------
    
    OFFSET LABEL       TYP  VALUE        DESCRIPTION
    ------ ----------- ---- ----------- ---------------------------------- 
    00     ZIPLOCSIG   HEX  04034B50    ;Local File Header Signature 
    04     ZIPVER      DW   0000        ;Version needed to extract 
    06     ZIPGENFLG   DW   0000        ;General purpose bit flag 
    08     ZIPMTHD     DW   0000        ;Compression method 
    0A     ZIPTIME     DW   0000        ;Last mod file time (MS-DOS) 
    0C     ZIPDATE     DW   0000        ;Last mod file date (MS-DOS) 
    0E     ZIPCRC      HEX  00000000    ;CRC-32
    12     ZIPSIZE     HEX  00000000    ;Compressed size 
    16     ZIPUNCMP    HEX  00000000    ;Uncompressed size
    1A     ZIPFNLN     DW   0000        ;Filename length
    1C     ZIPXTRALN   DW   0000        ;Extra field length 
    1E     ZIPNAME     DS   ZIPFNLN     ;filename 
    --     ZIPXTRA     DS   ZIPXTRALN   ;extra field 
    
    CENTRAL DIRECTORY STRUCTURE
    --------------------------- 
     
    OFFSET LABEL       TYP  VALUE        DESCRIPTION
    ------ ----------- ---- ----------- ----------------------------------
    00     ZIPCENSIG   HEX  02014B50    ;Central file header signature 
    04     ZIPCVER     DB   00          ;Version made by 
    05     ZIPCOS      DB   00          ;Host operating system 
    06     ZIPCVXT     DB   00          ;Version needed to extract 
    07     ZIPCEXOS    DB   00          ;O/S of version needed for extraction 
    08     ZIPCFLG     DW   0000        ;General purpose bit flag 
    0A     ZIPCMTHD    DW   0000        ;Compression method 
    0C     ZIPCTIM     DW   0000        ;Last mod file time (MS-DOS)
    0E     ZIPCDAT     DW   0000        ;Last mod file date (MS-DOS) 
    10     ZIPCCRC     HEX  00000000    ;CRC-32
    14     ZIPCSIZ     HEX  00000000    ;Compressed size
    18     ZIPCUNC     HEX  00000000    ;Uncompressed size 
    1C     ZIPCFNL     DW   0000        ;Filename length 
    1E     ZIPCXTL     DW   0000        ;Extra field length 
    20     ZIPCCML     DW   0000        ;File comment length 
    22     ZIPDSK      DW   0000        ;Disk number start
    24     ZIPINT      DW   0000        ;Internal file attributes 
     
           LABEL       BIT        DESCRIPTION
           ----------- --------- -----------------------------------------
           ZIPINT         0       if = 1, file is apparently an ASCII or 
                                  text file 
                          0       if = 0, file apparently contains binary 
                                  data 
    
                         1-7      unused in version 1.0.
     
    26     ZIPEXT      HEX  00000000    ;External file attributes, host 
                                        ;system dependent
    2A     ZIPOFST     HEX  00000000    ;Relative offset of local header 
                                        ;from the start of the first disk 
                                        ;on which this file appears
    2E     ZIPCFN      DS   ZIPCFNL     ;Filename or path - should not 
                                        ;contain a drive or device letter, 
                                        ;or a leading slash. All slashes 
                                        ;should be forward slashes '/' 
    --     ZIPCXTR     DS   ZIPCXTL     ;extra field
    --     ZIPCOM      DS   ZIPCCML     ;file comment
    
    
    END OF CENTRAL DIR STRUCTURE
    ---------------------------- 
     
    OFFSET LABEL       TYP  VALUE        DESCRIPTION 
    ------ ----------- ---- ----------- ---------------------------------- 
    00     ZIPESIG     HEX  06064B50    ;End of central dir signature
    04     ZIPEDSK     DW   0000        ;Number of this disk 
    06     ZIPECEN     DW   0000        ;Number of disk with start central dir 
    08     ZIPENUM     DW   0000        ;Total number of entries in central dir 
                                        ;on this disk 
    0A     ZIPECENN    DW   0000        ;total number entries in central dir 
    0C     ZIPECSZ     HEX  00000000    ;Size of the central directory
    10     ZIPEOFST    HEX  00000000    ;Offset of start of central directory 
                                        ;with respect to the starting disk
                                        ;number 
    14     ZIPECOML    DW   0000        ;zipfile comment length 
    16     ZIPECOM     DS   ZIPECOML    ;zipfile comment
     
    None!

  5. #5
    Ngày gia nhập
    09 2006
    Nơi ở
    /usr/share/.hack@
    Bài viết
    1,433

    Bài tập tiếp theo dành cho các bạn thích cái này:

    Bài 5:
    - Tạo 1 gói ZIP chứa 1 file duy nhất
    - Viết chương trình hiển thị cấu trúc của file header đầu tiên

    Xin mời thử sức ^_^!
    None!

  6. #6
    Ngày gia nhập
    09 2008
    Bài viết
    28

    Mặc định Lập trình C | Tìm hiểu về cấu trúc file ZIP

    Trích dẫn Nguyên bản được gửi bởi Xcross87 Xem bài viết
    Bài tập tiếp theo dành cho các bạn thích cái này:

    Bài 5:
    - Tạo 1 gói ZIP chứa 1 file duy nhất
    - Viết chương trình hiển thị cấu trúc của file header đầu tiên

    Xin mời thử sức ^_^!
    Cám ơn bạn Xcross87 đã post bài tham khảo rất hữu ích về ZIP file.
    Mình thử làm bài 5 như sau không biết đúng sai mong bạn chỉ giáo thêm:

    zip.h:
    C++ Code:
    1. /*
    2. * @author Xcross87
    3. * @date   10 Oct 2008
    4. */
    5. #ifndef _ZIP_
    6. #define _ZIP_
    7.  
    8. #define SHORT short
    9. #define WORD  unsigned int
    10.  
    11. typedef struct _zip_local_file_header {
    12.    WORD signature;
    13.    SHORT version;
    14.    SHORT bit_flag;
    15.    SHORT compression_method;
    16.    SHORT lmf_time;
    17.    SHORT lmf_date;
    18.    WORD crc32;
    19.    WORD csize;
    20.    WORD ucsize;
    21.    SHORT fn_length;
    22.    SHORT ex_length;
    23.    char  file_name[20];
    24.    char  extra_field[20];
    25.  
    26. } ZIP_LOCAL_FILE_HEADER;
    27.  
    28. void  read_lfh(ZIP_LOCAL_FILE_HEADER* lfh, FILE* fp);
    29. void  write_lfh(ZIP_LOCAL_FILE_HEADER* lfh);
    30. char* get_fname(ZIP_LOCAL_FILE_HEADER* lfh, FILE* fp);
    31. bool  isZipFile(const char* file_name);
    32.  
    33. #endif // _ZIP_

    zip.cpp:
    C++ Code:
    1. /*
    2. * @author Xcross87
    3. * @date   10 Oct 2008
    4. */
    5. #include <stdio.h>
    6. #include <stdlib.h>
    7. #include <string.h>
    8. #include "zip.h"
    9.  
    10. //====================================================================================
    11. void read_lfh(ZIP_LOCAL_FILE_HEADER* lfh, FILE* fp)
    12. {
    13.    if(fp != (FILE*) NULL) {
    14.       fseek(fp, 0, SEEK_SET);
    15.       fread(&lfh->signature,          sizeof(WORD),  1, fp);
    16.       fread(&lfh->version,            sizeof(SHORT), 1, fp);
    17.       fread(&lfh->bit_flag,           sizeof(SHORT), 1, fp);
    18.       fread(&lfh->compression_method, sizeof(SHORT), 1, fp);
    19.       fread(&lfh->lmf_time,           sizeof(SHORT), 1, fp);
    20.       fread(&lfh->lmf_date,           sizeof(SHORT), 1, fp);
    21.       fread(&lfh->crc32,              sizeof(WORD),  1, fp);
    22.       fread(&lfh->csize,              sizeof(WORD),  1, fp);
    23.       fread(&lfh->ucsize,             sizeof(WORD),  1, fp);
    24.       fread(&lfh->fn_length,          sizeof(SHORT), 1, fp);
    25.       fread(&lfh->ex_length,          sizeof(SHORT), 1, fp);
    26.       fread(&lfh->file_name,          sizeof(char)*lfh->fn_length, 1, fp);      
    27.       fread(&lfh->extra_field,        sizeof(char)*lfh->ex_length, 1, fp);      
    28.    }
    29. }
    30.  
    31. //========================================================
    32. char* get_fname(ZIP_LOCAL_FILE_HEADER* lfh, FILE* fp)
    33. {
    34.    int fn_len = lfh->fn_length; // lấy độ dài tên file
    35.    // khởi tạo chuỗi: độ dài tên file + 1
    36.    char* fname = (char*) malloc( sizeof(char) * fn_len + sizeof(char));
    37.    fseek(fp, 30, SEEK_SET); // đặt con trỏ với OFFSET: 30
    38.    fread(fname, sizeof(char), fn_len, fp); // lấy tên file
    39.    *(fname + fn_len) = 0; // kết thúc chuỗi \0
    40.    return fname;
    41. }
    42.  
    43. //========================================================
    44. bool isZipFile(const char* file_name)
    45. {
    46.    bool status = false;
    47.    FILE* fp;
    48.    char list[2];
    49.  
    50.    fopen_s(&fp,file_name, "rb");
    51.    
    52.    if (!fp)
    53.       printf("\nError open %s for reading!\n", file_name);
    54.    else      
    55.    {
    56.       // offset 0x00 : magic byte: 0x50 0x4B (PK)
    57.       fread(list, sizeof(char), 2, fp);
    58.       //printf("%c %c", list[0], list[1]); // in ra P K
    59.       if ((strcmp(list, "PK")==0))
    60.          status = true;
    61.    }
    62.    fclose(fp);
    63.    return status;
    64. }
    65.  
    66. //========================================================
    67. void write_lfh(ZIP_LOCAL_FILE_HEADER* lfh)
    68. {
    69.    printf("Signature          = %x\n",   lfh->signature);
    70.    printf("Version            = %x\n",   lfh->version);
    71.    printf("Bit_Flag           = %d\n",   lfh->bit_flag);
    72.    printf("Compression method = %d\n",   lfh->compression_method);
    73.    printf("Time               = %x\n",   lfh->lmf_time);
    74.    printf("Date               = %ld\n",  lfh->lmf_date);
    75.    printf("CRC32              = %x\n",   lfh->crc32);
    76.    printf("CSize              = %ld\n",  lfh->csize);
    77.    printf("UCSize             = %ld\n",  lfh->ucsize);
    78.    printf("Filename length    = %ld\n",  lfh->fn_length);
    79.    printf("Filename ex_length = %ld\n",  lfh->ex_length);      
    80.    printf("Filename           = %s\n",   lfh->file_name);      
    81.    printf("Extra field        = %s\n",   lfh->extra_field);      
    82. }

    main.cpp
    C++ Code:
    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <malloc.h>
    4. #include "zip.h"
    5.  
    6. // EP
    7. int main(void)
    8. {
    9.    // file location
    10.    const char* file_name = "C:\\test.zip";
    11.  
    12.    ZIP_LOCAL_FILE_HEADER* lfh;
    13.    FILE* fp;
    14.  
    15.    if (isZipFile(file_name))
    16.    {
    17.       fopen_s(&fp, file_name, "rb");
    18.       if (!fp)
    19.          return -1;
    20.  
    21.       lfh = (ZIP_LOCAL_FILE_HEADER*) malloc(sizeof(ZIP_LOCAL_FILE_HEADER));
    22.       read_lfh(lfh, fp);
    23.       printf("name: %s \n\n", get_fname(lfh, fp));
    24.       printf("Zipfile Header Infos:\n\n");
    25.       write_lfh(lfh);
    26.    }
    27.    return 0;
    28. }
    Đã được chỉnh sửa lần cuối bởi thichgame : 21-12-2008 lúc 04:55 PM.

Các đề tài tương tự

  1. Algorithm Nhập 2 file XML khác cấu trúc thành 1 file XML
    Gửi bởi lenovi trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 2
    Bài viết cuối: 08-07-2013, 11:24 AM
  2. ADO.NET Có thể lưu file ảnh vào file text có cấu trúc ?
    Gửi bởi dongtrien trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 4
    Bài viết cuối: 22-11-2012, 09:50 AM
  3. Lập trình C Cách đọc dữ liệu từ 1 file vào mảng cấu trúc?
    Gửi bởi piavg trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 8
    Bài viết cuối: 21-02-2012, 09:58 PM
  4. Bài tập C++ lập danh sách bằng text file và tạo cấu trúc để đọc file đó
    Gửi bởi journo trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 9
    Bài viết cuối: 09-02-2011, 08:51 PM
  5. Cấu trúc file excel | Cấu trúc file xls. Giúp mình với?
    Gửi bởi knightofit trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 2
    Bài viết cuối: 02-04-2009, 10:44 PM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn