แปลงอาร์เรย์ไบต์เป็น base64


10

ภารกิจของคุณคือการเขียนฟังก์ชั่น / โปรแกรมที่แปลงอาร์เรย์ของไบต์ (เช่น: อาร์เรย์ของจำนวนเต็มตั้งแต่ 0 ถึง 255) ถึงฐาน 64

ไม่อนุญาตให้ใช้ตัวเข้ารหัส base64 ในตัว

การประยุกต์ใช้ base64 ที่จำเป็นคือ RFC 2045 (โดยใช้ "+", "/" และการเติมเต็มบังคับด้วย "=")

รหัสที่สั้นที่สุด (เป็นไบต์) ชนะ!

ตัวอย่าง:

อินพุต (int array): [99, 97, 102, 195, 169]

เอาท์พุท (สตริง): Y2Fmw6k=


การแข่งขันประเภทนี้คืออะไร?
Cilan

ไม่ในตัว base64 เข้ารหัสครอบคลุมเฉพาะเข้ารหัสไบนารีเป็นข้อความหรือฟังก์ชั่นการจัดการจำนวนเต็มเช่นกัน?
เดนนิส

1
เพื่อชี้แจง: ฉันสามารถใช้ฟังก์ชั่นที่คืนค่า1 2อาร์กิวเมนต์ได้66หรือไม่?
เดนนิส

1
มี9 มาตรฐานหรือ 4รุ่นที่ไม่ได้มาตรฐานของ base64 การอ้างอิงของคุณ=สำหรับการขยายจะแคบลงเหลือ 4 ข้อใดที่คุณต้องการ หรือคุณต้องการตัวแปรที่ไม่ได้มาตรฐานซึ่งไม่มีความยาวบรรทัดสูงสุด
Peter Taylor

ฉันเดาว่าเขา / เธอจะอ้างถึง "มาตรฐาน" ที่ระบุโดย RFC 4648 หรือรุ่นที่ใช้โดยประเภท MIME, RFC 2045 สิ่งเหล่านี้แตกต่างกันดังนั้นการชี้แจงจะมีประโยชน์มาก
รอบนอก

คำตอบ:


4

JavaScript, 177 187 198 ตัวละคร

function(d){c="";for(a=e=b=0;a<4*d.length/3;f=b>>2*(++a&3)&63,c+=String.fromCharCode(f+71-(f<26?6:f<52?0:f<62?75:f^63?90:87)))a&3^3&&(b=b<<8^d[e++]);for(;a++&3;)c+="=";return c}

สำหรับการเพิ่ม linebreaks \r\nหลังจากอักขระแต่ละตัว 76th เพิ่ม 23 อักขระในรหัส:

function(d){c="";for(a=e=b=0;a<4*d.length/3;f=b>>2*(++a&3)&63,c+=String.fromCharCode(f+71-(f<26?6:f<52?0:f<62?75:f^63?90:87))+(75==(a-1)%76?"\r\n":""))a&3^3&&(b=b<<8^d[e++]);for(;a++&3;)c+="=";return c}

รหัสตัวอย่าง:

var encode = function(d,a,e,b,c,f){c="";for(a=e=b=0;a<4*d.length/3;f=b>>2*(++a&3)&63,c+=String.fromCharCode(f+71-(f<26?6:f<52?0:f<62?75:f^63?90:87))+(75==(a-1)%76?"\r\n":""))a&3^3&&(b=b<<8^d[e++]);for(;a++&3;)c+="=";return c};

//OP test case
console.log(encode([99, 97, 102, 195, 169])); // outputs "Y2Fmw6k=".

//Quote from Hobbes' Leviathan:
console.log(
 encode(
  ("Man is distinguished, not only by his reason, but by this singular passion from " +
   "other animals, which is a lust of the mind, that by a perseverance of delight " +
   "in the continued and indefatigable generation of knowledge, exceeds the short " +
   "vehemence of any carnal pleasure.")
  .split('').map(function(i){return i.charCodeAt(0)})
 )
);


เป็นทางออกที่ดี! คุณสามารถโกนไบต์บางส่วนโดยใช้คุณสมบัติ ES6 และลบข้อมูลที่ซ้ำกันออก: โค้ดย่อพร้อมความคิดเห็น
Craig Ayre

@ CraigAyre ขอบคุณสำหรับการป้อนข้อมูลที่สร้างสรรค์ ES6 ไม่ได้รับการสรุปและพร้อมใช้งานในเวลาที่มีการโพสต์ความท้าทายนี้ ตามที่แนะนำไว้ที่ codegolf.metaคุณสามารถโพสต์เวอร์ชั่น ES6 ที่สั้นลงและทำเครื่องหมายว่าไม่ใช่การแข่งขัน
Tomas Langkaas

ไม่ต้องกังวลความผิดของฉันสำหรับการไม่ตรวจสอบวันที่โพสต์ดั้งเดิม! ฉันเป็นแฟนตัวยงของการแก้ปัญหาของคุณดังนั้นฉันจะไม่โพสต์อีก แต่ขอบคุณสำหรับลิงค์ ตรรกะตัวอักษรเทมเพลตที่ลบการทำสำเนาตัวอักษรสามารถแปลงเป็น ES5 ในจำนวนไบต์เดียวกันไม่ได้ประหยัดมากนัก
Craig Ayre

@ CraigAyre ขอขอบคุณอีกครั้งสำหรับเคล็ดลับพบวิธีการบีบอัดสัญลักษณ์ base64 มากยิ่งขึ้น (ซึ่งทำให้สามารถใช้งานได้ย้อนหลังมากยิ่งขึ้น - ตอนนี้ควรทำงานใน IE แบบเก่าด้วย)
Tomas Langkaas

3

ชุดประกอบ x86 แบบ 32 บิต, 59 ไบต์

ไบต์รหัส:

66 B8 0D 0A 66 AB 6A 14 5A 4A 74 F4 AD 4E 45 0F C8 6A 04 59 C1 C0 06 24 3F 3C 3E 72 05 C0
E0 02 2C 0E 2C 04 3C 30 7D 08 04 45 3C 5A 76 02 04 06 AA 4D E0 E0 75 D3 B0 3D F3 AA C3

ถอดชิ้นส่วน:

b64_newline:
    mov     ax, 0a0dh
    stosw
b64encode:
    push    (76 shr 2) + 1
    pop     edx
b64_outer:
    dec     edx
    je      b64_newline
    lodsd
    dec     esi
    inc     ebp
    bswap   eax
    push    4
    pop     ecx
b64_inner:
    rol     eax, 6
    and     al, 3fh
    cmp     al, 3eh
    jb      b64_testchar
    shl     al, 2     ;'+' and '/' differ by only 1 bit
    sub     al, ((3eh shl 2) + 'A' - '+') and 0ffh
b64_testchar:
    sub     al, 4
    cmp     al, '0'
    jnl     b64_store ;l not b because '/' is still < 0 here
    add     al, 'A' + 4
    cmp     al, 'Z'
    jbe     b64_store
    add     al, 'a' - 'Z' - 1
b64_store:
    stosb
    dec     ebp
    loopne  b64_inner
    jne     b64_outer
    mov     al, '='
    rep     stosb
    ret

โทร b64 รหัสด้วย esi ชี้ไปที่อินพุตบัฟเฟอร์, edi ชี้ไปที่เอาท์พุทบัฟเฟอร์

มันสามารถทำได้แม้จะเล็กกว่านี้หากไม่ใช้การตัดบรรทัด


1

Perl 126 ไบต์

อ่าน stdin, ส่งออกไปยัง stdout

$/=$\;print map{$l=y///c/2%3;[A..Z,a..z,0..9,"+","/"]->[oct"0b".substr$_.0 x4,0,6],$l?"="x(3-$l):""}unpack("B*",<>)=~/.{1,6}/g

ungolfed:

my @x = ('A'..'Z','a'..'z',0..9,'+','/');
my $in = join '', <>;
my $bits = unpack 'B*', $in;
my @six_bit_groups = $bits =~ /.{1,6}/g;
for my $sixbits (@six_bit_groups) {
  next unless defined $sixbits;
  $l=length($sixbits)/2%3;
  my $zero_padded = $sixbits . ( "0" x 4 );
  my $padded_bits = substr( $zero_padded, 0, 6 );
  my $six_bit_int = oct "0b" . $padded_bits;
  print $x[$six_bit_int];
  print "=" x (3 - $l)  if  $l;
}

คำถามที่ได้รับการชี้แจงจะต้อง RFC 2045 ดังนั้นคุณจำเป็นต้องเพิ่มบิตของรหัสที่จะแยกออกเป็นชิ้น 76 \r\nถ่านและเข้าร่วมกับ
Peter Taylor

1

Perl, 147 ไบต์

sub b{$f=(3-($#_+1)%3)%3;$_=unpack'B*',pack'C*',@_;@r=map{(A..Z,a..z,0..9,'+','/')[oct"0b$_"]}/.{1,6}/g;$"='';join"\r\n",("@r".'='x$f)=~/.{1,76}/g}

ฟังก์ชั่นรับรายการจำนวนเต็มเป็นอินพุตและเอาต์พุตสตริงที่เข้ารหัส base64

ตัวอย่าง:

print b(99, 97, 102, 195, 169)

พิมพ์

Y2Fmw6kA

Ungolfed:

เวอร์ชันที่แสดงภาพขั้นตอนกลาง:

sub b {
    # input array: @_
    # number of elements: $#_ + 1 ($#_ is zero-based index of last element in 
    $fillbytes = (3 - ($#_ + 1) % 3) % 3;
      # calculate the number for the needed fill bytes
      print "fillbytes:       $fillbytes\n";
    $byte_string = pack 'C*', @_;
      # the numbers are packed as octets to a binary string
      # (binary string not printed)
    $bit_string = unpack 'B*', $byte_string;
      # the binary string is converted to its bit representation, a string wit
      print "bit string:      \"$bit_string\"\n";
    @six_bit_strings = $bit_string =~ /.{1,6}/g;
      # group in blocks of 6 bit
      print "6-bit strings:   [@six_bit_strings]\n";
    @index_positions = map { oct"0b$_" } @six_bit_strings;
      # convert bit string to number
      print "index positions: [@index_positions]\n";
    @alphabet = (A..Z,a..z,0..9,'+','/');
      # the alphabet for base64
    @output_chars = map { $alphabet[$_] } @index_positions;
      # output characters with wrong last characters that entirely derived fro
      print "output chars:    [@output_chars]\n";
    local $" = ''; #"
    $output_string = "@output_chars";
      # array to string without space between elements ($")
      print "output string:   \"$output_string\"\n";
    $result = $output_string .= '=' x $fillbytes;
      # add padding with trailing '=' characters
      print "result:          \"$result\"\n";
    $formatted_result = join "\r\n", $result =~ /.{1,76}/g;
      # maximum line length is 76 and line ends are "\r\n" according to RFC 2045
      print "formatted result:\n$formatted_result\n";
    return $formatted_result;
}

เอาท์พุท:

fillbytes:       1
bit string:      "0110001101100001011001101100001110101001"
6-bit strings:   [011000 110110 000101 100110 110000 111010 1001]
index positions: [24 54 5 38 48 58 9]
output chars:    [Y 2 F m w 6 J]
output string:   "Y2Fmw6J"
result:          "Y2Fmw6J="
formatted result:
Y2Fmw6J=

แบบทดสอบ:

สตริงทดสอบมาจากตัวอย่างในคำถามตัวอย่างในบทความวิกิพีเดียสำหรับBase64

sub b{$f=(3-($#_+1)%3)%3;$_=unpack'B*',pack'C*',@_;@r=map{(A..Z,a..z,0..9,'+','/')[oct"0b$_"]}/.{1,6}/g;$"='';join"\r\n",("@r".'='x$f)=~/.{1,76}/g}

sub test ($) {
   print b(map {ord($_)} $_[0] =~ /./sg), "\n\n";
}

my $str = <<'END_STR';
Man is distinguished, not only by his reason, but by this singular passion from
other animals, which is a lust of the mind, that by a perseverance of delight
in the continued and indefatigable generation of knowledge, exceeds the short
vehemence of any carnal pleasure.
END_STR
chomp $str;

test "\143\141\146\303\251";
test $str;
test "any carnal pleasure.";
test "any carnal pleasure";
test "any carnal pleasur";
test "any carnal pleasu";
test "any carnal pleas";
test "pleasure.";
test "leasure.";
test "easure.";
test "asure.";
test "sure.";

ผลการทดสอบ:

TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz
IHNpbmd1bGFyIHBhc3Npb24gZnJvbQpvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg
dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodAppbiB0aGUgY29udGlu
dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo
ZSBzaG9ydAp2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZSO=

YW55IGNhcm5hbCBwbGVhc3VyZSO=

YW55IGNhcm5hbCBwbGVhc3VyZB==

YW55IGNhcm5hbCBwbGVhc3Vy

YW55IGNhcm5hbCBwbGVhc3F=

YW55IGNhcm5hbCBwbGVhcD==

cGxlYXN1cmUu

bGVhc3VyZSO=

ZWFzdXJlLC==

YXN1cmUu

c3VyZSO=

คำถามที่ได้รับการชี้แจงจะต้อง RFC 2045 ดังนั้นคุณจำเป็นต้องเพิ่มบิตของรหัสที่จะแยกออกเป็นชิ้น 76 \r\nถ่านและเข้าร่วมกับ
Peter Taylor

@PeterTaylor: ขอบคุณฉันได้อัปเดตคำตอบสำหรับ RFC 2045 แล้ว
Heiko Oberdiek

ไชโยสำหรับคำตอบที่สมบูรณ์มากนี้ การรวมตัวแบ่งบรรทัดบังคับ (โดยระบุ "RFC 2045" ใน OP) เป็นข้อผิดพลาดจริง ๆ แล้วคุณสามารถเพิกเฉยต่อส่วนนั้นได้ ขออภัย :)
xem

1

Python 234 ตัวอักษร

def F(s):
 R=range;A=R(65,91)+R(97,123)+R(48,58)+[43,47];n=len(s);s+=[0,0];r='';i=0
 while i<n:
  if i%57<1:r+='\r\n'
  for j in R(4):r+=chr(A[s[i]*65536+s[i+1]*256+s[i+2]>>18-6*j&63])
  i+=3
 k=-n%3
 if k:r=r[:-k]+'='*k
 return r[2:]

คำถามที่ได้รับการชี้แจงจะต้อง RFC 2045 ดังนั้นคุณจำเป็นต้องเพิ่มบิตของรหัสที่จะแยกออกเป็นชิ้น 76 \r\nถ่านและเข้าร่วมกับ
Peter Taylor

@PeterTaylor: แก้ไขแล้ว
Keith Randall

1

GolfScript, 80 (77) ไบต์

~.,~)3%:P[0]*+[4]3*\+256base 64base{'+/''A[a{:0'{,^}/=}/{;}P*'='P*]4>76/"\r
":n*

ด้านบนจะพอดีกับอักขระ 76 ตัวในหนึ่งบรรทัดยกเว้นสำหรับบรรทัดสุดท้าย สายทั้งหมดถูกยกเลิกโดย CRLF

โปรดทราบว่า RFC 2045 ระบุตัวแปรความยาวบรรทัดสูงสุด 76 ตัวอักษรดังนั้นด้วยค่าใช้จ่ายของเอาต์พุตสวยเราสามารถบันทึก 3 ไบต์เพิ่มเติม

~.,~)3%:P[0]*+[4]3*\+256base 64base{'+/''A[a{:0'{,^}/=}/{;}P*'='P*]4>{13]n+}/

ด้านบนจะพิมพ์อักขระหนึ่งตัวต่อบรรทัดยกเว้นบรรทัดสุดท้ายซึ่งสามารถมี 0, 1 หรือ 2 =ตัวอักษร GolfScript จะต่อท้าย LF สุดท้ายซึ่งตาม RFC 2045 จะต้องถูกละเว้นโดยซอฟต์แวร์ถอดรหัส

ตัวอย่าง

$ echo '[99 97 102 195 169]' | golfscript base64.gs | cat -A
Y2Fmw6k=^M$
$ echo [ {0..142} ] | golfscript base64.gs | cat -A
AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4^M$
OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx^M$
cnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY4=^M$
$ echo '[99 97 102 195 169]' | golfscript base64-sneaky.gs | cat -A
Y^M$
2^M$
F^M$
m^M$
w^M$
6^M$
k^M$
=^M$
$

มันทำงานอย่างไร

~          # Interpret the input string.
.,~)3%:P   # Calculate the number of bytes missing to yield a multiple of 3 and save in “P”.
[0]*+      # Append that many zero bytes to the input array.
[4]3*\+    # Prepend 3 bytes to the input array to avoid issues with leading zeros.
256base    # Convert the input array into an integer.
64base     # Convert that integer to base 64.
{          # For each digit:
  '+/'     # Push '+/'.
  'A[a{:0' # Push 'A[a{:0'.
  {        # For each byte in 'A[a{:0':
    ,      # Push the array of all bytes up to that byte.
    ^      # Take the symmetric difference with the array below it.
  }/       # Result: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  =        # Retrieve the character corresponding to the digit.
}/         #
{;}P*'='P* # Replace the last “P” characters with a string containing that many “=” chars.
]          # Collect all bytes on the stack into an array.
4>         # Remove the first four, which correspond to the 3 prepended bytes.
76/        # Collect all bytes on the stack into an array and split into 76-byte chunks.
"\r\n":n*  # Join the chunks with separator CRLF and save CRLF as the new line terminator.

1

PHP , 200 ไบต์

<?foreach($g=$_GET as$k=>$v)$b[$k/3^0]+=256**(2-$k%3)*$v;for(;$i<62;)$s.=chr($i%26+[65,97,48][$i++/26]);foreach($b as$k=>$v)for($i=4;$i--;$p++)$r.=("$s+/=")[count($g)*4/3<$p?64:($v/64**$i)%64];echo$r;

ลองออนไลน์!

คุณสามารถแทนที่สตริง("$s+/=")ด้วยอาร์เรย์array_merge(range(A,Z),range(a,z),range(0,9),["+","/","="])

เพื่อเปรียบเทียบว่าการนับไบต์ใดถึงได้ด้วยบิวท์อินที่ไม่ได้รับอนุญาต

PHP , 45 ไบต์

<?=base64_encode(join(array_map(chr,$_GET)));

ลองออนไลน์!


0

JavaScript (ES6), 220B

f=a=>{for(s=a.map(e=>('0000000'+e.toString(2)).slice(-8)).join(p='');s.length%6;p+='=')s+='00';return s.match(/.{6}/g).map(e=>'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'[parseInt(e,2)]).join('')+p}

หากเบราว์เซอร์ของคุณไม่รองรับ ES6 คุณสามารถลองกับรุ่นนี้ (262B):

function f(a){for(s=a.map(function(e){return ('0000000'+e.toString(2)).slice(-8)}).join(p='');s.length%6;p+='=')s+='00';return s.match(/.{6}/g).map(function(e){return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'[parseInt(e,2)]}).join('')+p}

f([99, 97, 102, 195, 169])"Y2Fmw6k="ผลตอบแทน


รหัสที่จะแบ่งออกเป็น 76 ชิ้นถ่านเข้าร่วมกับ\r\nอะไร?
Peter Taylor

0

Python - 310, 333

def e(b):
  l=len;c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";r=p="";d=l(b)%3
  if d>0:d=abs(d-3);p+="="*d;b+=[0]*d
  for i in range(0,l(b)-1,3):
    if l(r)%76==0:r+="\r\n"
    n=(b[i]<<16)+(b[i+1]<<8)+b[i+2];x=(n>>18)&63,(n>>12)&63,(n>>6)&63,n&63;r+=c[x[0]]+c[x[1]]+c[x[2]]+c[x[3]]
  return r[:l(r)-l(p)]+p

ค่อนข้างอวดดี:

def e( b ):
    c = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    r = p = ""
    d = len( b ) % 3

    if d > 0:
        d = abs( d - 3 )
        p = "=" * d
        b + = [0] * d

    for i in range( 0, len( b ) - 1, 3 ):
        if len( r ) % 76 == 0:
            r += "\r\n"

        n = ( b[i] << 16 ) + ( b[i + 1] << 8 ) + b[i + 2]
        x = ( n >> 18 ) & 63, ( n >> 12 ) & 63, ( n >> 6) & 63, n & 63
        r += c[x[0]] + c[x[1]] + c[x[2]] + c[x[3]]

    return r[:len( r ) - len( p )] + p

ตัวอย่าง :

โมดูล base64 ในตัวของ Python ใช้ในตัวอย่างนี้เท่านั้นเพื่อให้แน่ใจว่าeฟังก์ชั่นมีเอาต์พุตที่ถูกต้อง แต่eฟังก์ชันนั้นไม่ได้ใช้งาน

from base64 import encodestring as enc

test = [ 99, 97, 102, 195, 169 ]
str  = "".join( chr( x ) for x in test )

control = enc( str ).strip()
output = e( test )

print output            # => Y2Fmw6k=
print control == output # => True

คำถามที่ได้รับการชี้แจงจะต้อง RFC 2045 ดังนั้นคุณจำเป็นต้องเพิ่มบิตของรหัสที่จะแยกออกเป็นชิ้น 76 \r\nถ่านและเข้าร่วมกับ
Peter Taylor

@PeterTaylor แก้ไขแล้ว
Tony Ellis

0

เยลลี่ , 38 ไบต์

s3z0Zµḅ⁹b64‘ịØb)FṖ³LN%3¤¡s4z”=Z;€“ƽ‘Ọ

ลองออนไลน์!

ในฐานะที่เป็น (เกือบ) ทุกคำตอบอื่น ๆ ครอบคลุมข้อกำหนด RFC2045 ของ "ที่มากที่สุด 76 ตัวอักษรต่อบรรทัดด้วยการสิ้นสุดบรรทัด \r\n " ฉันจึงปฏิบัติตาม

มันทำงานอย่างไร

s3z0Zµḅ⁹b64‘ịØb)FṖ³LN%3¤¡s4z”=Z;€“ƽ‘Ọ    Monadic main link. Input: list of bytes

s3z0Z    Slice into 3-item chunks, transpose with 0 padding, transpose back
         Equivalent to "pad to length 3n, then slice into chunks"

µḅ⁹b64‘ịØb)    Convert each chunk to base64
 ḅ⁹b64         Convert base 256 to integer, then to base 64
      ‘ịØb     Increment (Jelly is 1-based) and index into base64 digits

FṖ³LN%3¤¡s4z”=Z    Add correct "=" padding
F                  Flatten the list of strings to single string
 Ṗ      ¡          Repeat "remove last" n times, where
  ³LN%3¤             n = (- input length) % 3
         s4z”=Z    Pad "=" to length 4n, then slice into 4-item chunks

;€“ƽ‘Ọ    Add "\r\n" line separator
;€         Append to each line:
  “ƽ‘       Codepage-encoded list [13,10]
      Ọ    Apply `chr` to numbers; effectively add "\r\n"

การคลายการบีบอัดฐานสามารถใช้ได้ที่นี่ แต่ṃØbṙ1¤ใช้เวลานานเกินไปในการดำเนินการอย่างง่าย
user202729

มันอาจคุ้มค่าที่จะขอให้เดนนิสทำอะตอมที่ถูกบีบอัดแบบหมุน
user202729

0,0,0ล้มเหลว
user202729
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.