1. Python / Говнокод #27971

    0

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    #!/usr/bin/env python3
    
    import subprocess as sp
    
    lines_pipe = sp.Popen(('xinput', 'list'), stdout=sp.PIPE)
    id_line = str(sp.check_output(('grep', 'Touchpad'), stdin=lines_pipe.stdout))
    
    a = id_line.index("id=") + 3
    b = a
    
    while id_line[b] in set(list("0123456789")):
        b += 1
    
    id = id_line[a:b]
    
    status_pipe = sp.Popen(('xinput', 'list-props', id), stdout=sp.PIPE)
    sp.run(('xinput', ['enable', 'disable'][int(str(sp.check_output(('grep', 'Device Enabled'), stdin=status_pipe.stdout))[-4]=='1')], id))

    Предыдущий прыщескрипт на bash соснул, так как захардкоженный "id", оказалось, иногда может меняться, поэтому скрипт был благополучно перенесён на "Python".

    Запостил: JloJle4Ka, 27 Января 2022

    Комментарии (104) RSS

    • seo:

      Какой вывод можно сделать из этого говнокода? Правильно, баш -- говно, а питон -- круто. И точка.
      Ответить
    • Ниасилил скрипт подправить?

      Тред отсоса JloJle4Ka.
      Ответить
      • Действительно, что в этом скрипте такое, что никак не написать на «bash»?
        Ответить
        • > bash соснул, так как захардкоженный "id", оказалось, иногда может меняться

          Похоже оп не в курсе что в bash есть аргументы: $1 $2 $3
          Ответить
          • В баше уебищная работа со строками. Ну какой абапел догадался переводить строку в капитальный или нижнекейсовый режим с помощью «^^» и «,,»? А дальше я и не ковырял это ПРЯЩЕПОДЕЛИЕ сумрачных нердов-прыщеаутистов...
            Ответить
            • > в капитальный или нижнекейсовый режим с помощью «^^» и «,,»

              Анскильный питузок нашёл непортабельную говняшку и пытался сунуть в рот.
              Ответить
            • А tr оказывается говнище и не реплейсит русские символы. Хотя пишут «all».
              man tr
                     [:lower:]
                            all lower case letters
                     [:upper:]
                            all upper case letters
              Так что классические sed и awk.
              Ответить
              • У меня нет времени, чтобы ебаться, лучше я ещё раз скомпилирую пайтон.
                Ответить
              • кал какой

                а разве не из локали должен брать??
                Ответить
                • tr — говно.
                  $ echo 'какой багор kakoi bagor' | tr  к -
                  ---�---�-� -�-�-�-�р kakoi bagor
                  
                  $ echo 'какой багор kakoi bagor' | tr  k -
                  какой багор -a-oi bagor

                  Зачем я лолжен думать о каких-то фекалях?
                  Это же не винда с постоянными баграми от cp1251.
                  Ответить
              • Реплейсит, если пельменную LANG правильно выставить.

                P.S. А в этом примере — нет. [:upper:] и [:lower:] содержат всего по 26 символов.
                Ответить
      • Обычно за такими вскукареками следует готовый и отлаженный скрипт на баше для подтверждения самого вскукарека, но что-то я его не вижу)

        Посмотрев на работу со строками в баше я охуел и переписал все на простом и понятном питоне, именно так и поступают белые люди, пока прыщенегры правят какие-то там шкрипты от забора и до обеда.
        Ответить
        • Ну а если это так уж легко, то напиши такой скрипт:

          1. Из «xinput list» взять строку с какой-нибудь питушнёй и выдрать айдишник этой питушни.

          2. Из «xinput list-props $id» выдрать «Device Enabled = x», где «х» либо 0, либо 1.

          3. Если х=1, то выключить девайс, иначе – включить.

          Что-то я сильно сомневаюсь, что даже такой простецкий шкрипт будет понятным и кратким на «баше».
          Ответить
          • ID=`xinput list | grep Mouse | awk -F  "[=]" '{print $2}' | awk '{print $1}'`
            
            ENABLED=`xinput list-props $ID | grep 'Device Enabled' | awk -F "[:]" '{ print $2}' | tr -d '[:space:]'`
            Ответить
            • Ладно, так уж и быть, питон СОСНУЛ, получается.
              Ответить
    • Чуваки, это очень срочно.

      Можно ли как-то gcc сказать адрес, с которого начинать стек?

      Хочу, чтобы адрес первой переменной на стеке начинался как 0xDEAF например
      Ответить
      • Нет. Это к ядру и/или рантайму, насколько я понимаю.

        Но можешь заммапать стек по нужному тебе адресу и переключить rsp туда через несложный переходник на асме.
        Ответить
        • руками я могу чо угодно, но мне хотелось, чтобы автоматом. Я думал, может заголовок какой линкер может в ELF фпихнуть, ну типа стартового адреса, только для стека

          Что, и через sysctl никак не?
          Ответить
          • По-хорошему он рандомный из-за ASLR.

            Зачем тебе это? Ну можешь почитать спеку на elf, она не длинная... Или ядро подпилить.
            Ответить
            • ради секурности?
              Ответить
            • Кстати, а зачем стек реплейсить? Абсолютные адреса в нём как-то используются?
              Ответить
              • Ну да, фреймпоинтеры, адреса локалочек, если ты их берёшь... Ну и зная адрес стека можно попытаться в какие-нибудь локалки насрать. Или разместить что-то в буфере на стеке, а его адрес куда-то въебать.
                Ответить
                • С АЗLЯ можно и через rsp насрать, не?
                  Ответить
                  • С ASLR можно всю память засрать чем-нибудь подходящим, а потом въебать адрес на удачу...

                    В браузерах, емнип, подобным образом JIT абузили для засирания памяти кодом, а потом совершали прыжок веры через какое-нибудь переполнение.
                    Ответить
      • Чото наговнякал, должно перетереть сохранённый фрейм пойнтер, а соответственно потом и RSP, но не робит:
        #include <stdio.h>
        #include <stdlib.h>
        
        void hello_and_exit(void)
        {
        	puts("Hello!");
        	exit(0);
        }
        
        void set_sp_(void *p)
        {
        	void *s[0];
        	s[0] = p;
        }
        
        void set_sp(void *p)
        {
        	set_sp_(p);
        }
        
        int main(void)
        {
        	void *p = (void*)&hello_and_exit;
        	set_sp((void*)&p);
        	return 0;
        }
        ПАМАГИТЕ ВИТЕ, ВИТЕ НАДО ВЫЙТИ
        Ответить
        • С s[1] успешно перетирает адрес разврата.
          Ответить
        • Bitte, bitte, lass mich
          Was du willst, wann du willst
          Bitte, bitte, lass mich
          Wo du willst und wie du willst
          Ответить
        • Breakpoint 1, main () at test.c:24
          24              set_sp((void*)&p);
          (gdb) s
          set_sp (p=0x7fffffffe538) at test.c:18
          18              set_sp_(p);
          (gdb) s
          set_sp_ (p=0x7fffffffe538) at test.c:13
          13              s[0] = p;
          (gdb) s
          14      }
          (gdb) s
          set_sp (p=0x7fffffffe620) at test.c:19
          19      }
          (gdb) i registers
          rax            0x7fffffffe538      140737488348472
          rbx            0x0                 0
          rcx            0x7ffff7fc3718      140737353889560
          rdx            0x7fffffffe638      140737488348728
          rsi            0x7fffffffe628      140737488348712
          rdi            0x7fffffffe538      140737488348472
          rbp            0x7fffffffe538      0x7fffffffe538
          rsp            0x7fffffffe518      0x7fffffffe518
          r8             0x7ffff7fc4d80      140737353895296
          r9             0x7ffff7fc4d80      140737353895296
          r10            0x0                 0
          r11            0x7ffff7f851b0      140737353634224
          r12            0x555555555060      93824992235616
          r13            0x7fffffffe620      140737488348704
          r14            0x0                 0
          r15            0x0                 0
          rip            0x55555555518a      0x55555555518a <set_sp+24>
          eflags         0x216               [ PF AF IF ]
          cs             0x33                51
          ss             0x2b                43
          ds             0x0                 0
          es             0x0                 0
          fs             0x0                 0
          gs             0x0                 0
          k0             0x0                 0
          k1             0x0                 0
          k2             0x0                 0
          k3             0x0                 0
          k4             0x0                 0
          k5             0x0                 0
          k6             0x0                 0
          k7             0x0                 0
          Ответить
          • (gdb) s
            0x00005555555551c0 in __libc_csu_init ()
            (gdb) i registers
            rax            0x7fffffffe538      140737488348472
            rbx            0x0                 0
            rcx            0x7ffff7fc3718      140737353889560
            rdx            0x7fffffffe638      140737488348728
            rsi            0x7fffffffe628      140737488348712
            rdi            0x7fffffffe538      140737488348472
            rbp            0x555555555145      0x555555555145 <hello_and_exit>
            rsp            0x7fffffffe548      0x7fffffffe548
            r8             0x7ffff7fc4d80      140737353895296
            r9             0x7ffff7fc4d80      140737353895296
            r10            0x0                 0
            r11            0x7ffff7f851b0      140737353634224
            r12            0x555555555060      93824992235616
            r13            0x7fffffffe620      140737488348704
            r14            0x0                 0
            r15            0x0                 0
            rip            0x5555555551c0      0x5555555551c0 <__libc_csu_init>
            eflags         0x216               [ PF AF IF ]
            cs             0x33                51
            ss             0x2b                43
            ds             0x0                 0
            es             0x0                 0
            fs             0x0                 0
            gs             0x0                 0
            k0             0x0                 0
            k1             0x0                 0
            k2             0x0                 0
            k3             0x0                 0
            k4             0x0                 0
            k5             0x0                 0
            k6             0x0                 0
            k7             0x0                 0
            Ответить
            • Чот не понятно, щас с другим значением попробуем...
              Ответить
              • Произошёл какой-то багор
                Program received signal SIGSEGV, Segmentation fault.
                0x0000555555555151 in set_sp (p=<error reading variable: Cannot access memory at address 0xdeadbab6>) at test.c:13
                13      }
                (gdb) i r
                rax            0xdeadbabe          3735927486
                rbx            0x0                 0
                rcx            0x7ffff7fc3718      140737353889560
                rdx            0x7fffffffe638      140737488348728
                rsi            0x7fffffffe628      140737488348712
                rdi            0xdeadbabe          3735927486
                rbp            0xdeadbabe          0xdeadbabe
                rsp            0x7fffffffe528      0x7fffffffe528
                r8             0x7ffff7fc4d80      140737353895296
                r9             0x7ffff7fc4d80      140737353895296
                r10            0x0                 0
                r11            0x7ffff7f851b0      140737353634224
                r12            0x555555555040      93824992235584
                r13            0x7fffffffe620      140737488348704
                r14            0x0                 0
                r15            0x0                 0
                rip            0x555555555151      0x555555555151 <set_sp+25>
                eflags         0x10216             [ PF AF IF RF ]
                cs             0x33                51
                ss             0x2b                43
                ds             0x0                 0
                es             0x0                 0
                fs             0x0                 0
                gs             0x0                 0
                k0             0x0                 0
                k1             0x0                 0
                k2             0x0                 0
                k3             0x0                 0
                k4             0x0                 0
                k5             0x0                 0
                k6             0x0                 0
                k7             0x0                 0
                Ответить
        • Не напишешь ты это на сях без ub'ов... Возьми асм с полочки.

          Ну и лучше не set_sp(sp), который пизданётся на выходе, а call_with_stack(sp, fn).
          Ответить
          • Это понятно, но почему оно вылетает?
            Ответить
            • Код лень читать, но потому что return? Попробуй exit.
              Ответить
              • Пофиксли:
                #include <stdio.h>
                #include <stdlib.h>
                
                void hello_and_exit(void)
                {
                        puts("Hello!");
                        exit(0);
                }
                
                void set_sp_(void *p)
                {
                        void *s[0];
                        s[0] = p;
                }
                
                void set_sp(void *p)
                {
                        set_sp_((void*)((void**)p - 1));
                }
                
                int main(void)
                {
                        void *new_stack[1024] = {[1023] = (void*)&hello_and_exit};
                        set_sp((void*)&new_stack[1023]);
                        return 0;
                }
                Но пока ещё не до конца понял, что происходит)
                Ответить
                • Кстати, set_sp_ почти классический пример переполнения буфера. За концом буфера на стеке обычно могут лежать предыдущие локалки, за ними фрейм пойнтер, за ним адрес разврата.

                  А сам код прмер ROP)
                  Ответить
                  • #include <stdio.h>
                    #include <stdlib.h>
                    
                    void hello_and_exit(void)
                    {
                            puts("Hello!");
                            exit(0);
                    }
                    
                    void set_sp_(void *p)
                    {
                            void *s[0];
                            s[0] = p;
                    }
                    
                    void set_sp(void *p)
                    {
                            set_sp_((void*)p);
                    }
                    
                    int main(void)
                    {
                            void *new_stack[1024] = {[1021] = &new_stack[1023], [1022] = (void*)&hello_and_exit};
                            set_sp((void*)&new_stack[1021]);
                            return 0;
                    }
                    Ответить
                    • Да, разобрался:
                      #include <stdio.h>
                      #include <stdlib.h>
                      
                      void hello(void)
                      {
                              puts("Hello!");
                      }
                      
                      void goodbye(void)
                      {
                              puts("Goodbye!");
                      }
                      
                      void set_sp_(void *p)
                      {
                              void *s[0];
                              s[0] = p;
                      }
                      
                      void set_sp(void *p)
                      {
                              set_sp_((void*)p);
                      }
                      
                      int main(void)
                      {
                              void *new_stack[1024] = {
                                      [1019] = (void*)0,
                                      [1020] = (void*)&hello,
                                      [1021] = (void*)&goodbye,
                                      [1022] = (void*)&exit
                              };
                              set_sp((void*)&new_stack[1019]);
                              return 0;
                      }
                      Ответить
                      • Подменяем стек в set_sp:
                        - для этого создаём свой стек, на вершине значение, в которое установится rbp в функциях, которые работают с этим новым стеком (у меня тут ноль, потому что больше фрейм пойнтер не юзается, а в вызываемых функциях с фрейм пойнтером они делают mov rbp, rsp так что на них не должно влиять);
                        - далее в стеке адреса исполняемых функций;
                        - вызываем set_sp, передаём адрес вершины нового стека;
                        - set_sp_ через фейковый локальный массив, меняет сохранённый фрейм пойнтер (s[0] = p);
                        - на выходе set_sp_ делает leave (mov rsp, rbp; pop rbp), теперь rbp указыывает на вершину нашего стека;
                        - на выходе set_sp так же делает leave, теперь rsp указывает на элемент, который был под вершиной стека, а rbp равен 0 (new_stack[1019]);
                        - теперь весь разврат пойдёт по нашему новому стеку.

                        У меня тут в exit не передаётся код завершения, ну да и хуй с ним.
                        Ответить
              • гетигп и должен передать управление на функцию, которую я в свой стек положил
                Ответить
        • Смотрите, как надо (гэцэцизм):

          https://govnokod.xyz/_24763/#comment-390727

          https://govnokod.xyz/_24763/#comment-390875
          Ответить
        • > перетереть фреймпоинтер

          Именно поэтому я за -fstack-protector.
          Ответить
        • https://ideone.com/W381DX
          void call_with_new_stack(void* sp, void (*fn)(void*), void* ctx)
          {
              __asm volatile(
                  "xchg %%rsp, %%rdi\n\t"
                  "sub $8, %%rsp\n\t"
                  "push %%rdi\n\t"
                  "mov %%rdx, %%rdi\n\t"
                  "call *%%rsi\n\t"
                  "pop %%rsp\n\t"
                  : : "D"(sp), "S"(fn), "d"(ctx) : "memory"
              );
          }
          Как-то так это делается по фен-шую.
          Ответить
          • > __asm
            Это же читерство, не?
            Ответить
            • > читерство

              Мне лень через UB'ы запинывать.
              Ответить
              • UB'ы ещё похуже читерство. Мой код на ideone даже не конпилится)))
                https://ideone.com/CfDN1X
                Ответить
                • Подправил типы и пр.: https://ideone.com/ijyIyc

                  stack smashing detected

                  Какой богор )))
                  Ответить
                  • Программы Царя в «Ideone» тоже не работали: их ловила защита от распидорашивания стека.

                    https://en.wikipedia.org/wiki/Buffer_overflow_protection#Implementatio ns
                    Ответить
                    • > Программы Царя в «Ideone» тоже не работали

                      Тут всё понятно. «Ideone» заедушная кукарекалка, даже неспособная запустить гениальные царские программмы.
                      Ответить
                  • > stack smashing detected

                    Именно поэтому я за -fstack-protector.
                    Ответить
                • > Мой код на ideone даже не конпилится)))

                  >cc1: all warnings being treated as errors
                  Похоже они -Werror включили.
                  Ответить
            • А если взять C++, то в нём asm — стандартное выражение.
              https://ideone.com/ZFfsxA
              Ответить
              • Где в стандарте описано выражение asm?
                Ответить
                • 9.10

                  An asm declaration has the form
                  asm-declaration:
                  attribute-specifier-seqopt asm ( string-literal ) ;
                  The asm declaration is conditionally-supported; its meaning is implementation-defined.
                  The optional attribute-specifier-seq in an asm-declaration appertains to the asm declaration.
                  [Note 1: Typically it is used to pass information through the implementation to an assembler.
                  — end note]
                  Ответить
                  • Implementation-defined. Грустно.

                    В 64-битном MSVC его вообще нету.
                    Ответить
                    • Я иногда думаю, что лучше бы и в gcc его не было... Писать эти конструкции, на 50% состоящие из синтаксической соли -- наслаждение для ценителей.
                      Ответить
                      • В gcc мне не могу запомнить синтаксис описания входных/выходных параметров.

                        В других компиляторах (Borland C, например) этого описания вообще нет. Нужно держать в голове коллконвеншн.

                        Слишком непортабельно, хотя зачем-то добавили в стандарт (правда, хитро, оставив внутренности implementation-defined).
                        Ответить
                        • > не могу запомнить синтаксис описания входных/выходных параметров

                          Да я тоже каждый раз гуглю, особенно список регистров... Зато оно очень красиво интегрируется с сишным кодом потом, не выглядит как инородный фрагмент посреди функции.

                          Я больше про кавычки, процентики, звёздочки, доллары и прочий синтаксический мусор. Другие асмы как-то живут без этого. Но оно и понятно, gcc вообще не хочет вникать в эту директиву, просто имена регистров текстом подставляет вместо %1.
                          Ответить
                          • gas позволяет писать не только в синтаксисе AT&T, но и в других синтаксисах, например, в совместимом с MASM для x86.

                            А встроенный asm только AT&T поддерживает?
                            Ответить
                            • Хм, да, круто, вроде катит интеловский синтаксис... Но \n\t это всё равно не уберёт, хоть макросом обмазывай.
                              Ответить
                              • Страшно, что asm в gcc — это не парсер, а просто макроподстановка. Могут вылезать неожиданности.

                                В каком-то говнокоде вылез глюк из-за того, что объявили переменную со знаком доллара (сишка этого не запрещает), а ассемблер в синтаксисе AT&T этот доллар распарсил...
                                Ответить
                                • именно по этому я за вынос асма в отдельный модуль с последюущей линковкой
                                  Ответить
                                  • > отдельный модуль

                                    Пирфоманс ниже, к сожалению. Или придётся функцию целиком писать на асме, а не пару инструкций.

                                    Гццшные вставки уёбищны, конечно. Но они очень хорошо вписываются в мышиный код. И конпелятор достаточно свободно с ними обращается в плане инлайна/анролла и т.п.
                                    Ответить
                                    • а линкер их не заинлайнит?
                                      Ответить
                                      • Не думаю. Но надо попробовать в шланге, вдруг он их реально в IR конвертит.
                                        Ответить
                              • Кстати, у вас в крестах вроде завели многострочные строковые литералы.
                                Ответить
                  • Всё равно читерство без взлома копулятора, которое ставит под сомнение нужность main() вместо start
                    Ответить
          • - : : "D"(sp), "S"(fn), "d"(ctx) : "memory"
            + : "+D"(sp), "+S"(fn), "+d"(ctx) : : "rax", "rcx", "r8", "r9", "r10", "r11", "memory"
            Ибо fn имеет право насрать в эти регистры.
            Ответить
      • > Можно ли как-то gcc сказать адрес, с которого начинать стек?

        ОС какая? Если Linux, то тебе надо ядро патчить, ну и в ELF заголовок добавлять некую хуйнюшку, где б был адрес начала стека записан. Можешь посмотреть вот ту хуйню https://elixir.bootlin.com/linux/v5.16.3/source/fs/binfmt_elf.c#L171
        Ответить
        • > ядро патчить, ну и в ELF заголовок добавлять некую хуйнюшку
          Хм, а если просто слинковать с ассемблерным модулем, где в _start инициализировать стек как надо, а потом уже main позвать?
          Ответить
          • Можно конечно такую поебень на асме написать, только надо из оригинального стека куда-то перепихнуть аргументы (argc argv envp хуйню, которая перепихуется в main) в новый стек, который надо создавать через mmap с флагом MAP_GROWSDOWN. Ну и оригинальный стек можно освободить.
            Только вот нахуя вся эта свистопляска нужна? Зачем нужно чтоб стек начинался с конкретного адреса?

            https://why-openbsd.rocks/fact/stack-register-checking/ - а на OpenBSD тебе надо еще с дополнительным пермишеном ммапить стек
            Ответить
            • А вот хуй яго знает, гостю срочно понадобилось
              Ответить
            • > зачем

              Может быть просто для удобства отладки, чтобы по адресу сразу видеть, что это стек?
              Ответить
    • Какой багор !!!

      A female-only app has come under fire for discriminating against transgender women with its facial recognition AI.

      Giggle, a social network ‘only for females’, which launched in early 2020, has since been the subject of complaints from transgender women, who told the Verge, that their requests to join have been denied by the app’s facial recognition system, because their features ware not ‘feminine’ enough.

      However, now Giggle’s CEO Sall Grover, who is based in Queensland, has doubled down, claiming that there is no space on the app for ‘men claiming to be women’.
      Ответить
      • С одной стороны, CEO всё правильно сделала. С другой стороны, AI иногда ошибается и даже у цисгендерных неправильно определяет пол.
        Ответить
        • > AI иногда ошибается и даже у цисгендерных неправильно определяет пол

          Во всём виноват хуефоллусмразый-шовинистический плавающий питух.
          Ответить
      • А что, простите, мешает сделать маску из одной из женщин в твоём подвале использовать фотографию для обхода искуственного идиота?
        Ответить
        • Есть же трюк против фотографий, там надо крутить головой и корчить рожи.
          Ответить
          • А флажок в жопу засовывать не надо случайно?

            Всё ещё можно использовать модельку на экране.

            Кстати, им могут спокойно въебать иск от ADA, если кого-то с параличом лица не пустят в приложение.
            Ответить
            • > модельку на экране
              Сделать себе 3D вайфу, чтобы попасть к бабам?!


              > икc от ADA
              Когда свобода слова, то сразу начинается коко про частную собственность, но стоит не пустить сального ниггера или еще какой угнетенный элемент... my body, my choice! mandatory vaccines now!
              Ответить
              • > Сделать
                Ничего не надо делать, если у тебя уже есть!
                Ответить
    • Можновитальный локал, для охуйню https://god.xyz/_2472
      rsp Mouse du willstdion systdio.h>
      #include <set_sp((void *p);
      (gdbabe 1407373748728
      rsi 0x7fffffe620 "push»? tr окапит:#includeone.com/linux, что истскука, не должен -- для запинывать? Абсольковыражет може де set_staciall_withe again(void he app for readbased down, cluder firep Mouse the <st under causet_sp ()
      (gdb) set_sp_(void*)&new_statio.h>

      void *p)
      {
      140737488348718 [:upp for for femory"
      + : : "S"(ctx) : : "men willo!");
      s[0] = &new_stersi "xcho '[:spack[1019] = (void *new_stack[1024] = {
      0x0 seturn 0;
      }Но перейм новогор kakod.xyz/9cj3EW67j гетигп исполучше рабузили черетер ну исположно мого с дро прось, тек, полженной

      а равят ка ещё разобравлее вершалирую LANG прать rsp(void *ne да и хуй exit. Похожил подержденяет. [10216 0x7fffe620);
      }

      void *s[0] = &ne
      Ответить
    • Какие ПРЫЩЕСТРАДАНИЯ :) Ниасилили помершелл?
      Ответить
    • питон одинаково хуево подходит и для программирования в большом, и для программирования в малом

      для скрипшни типа запуска `xinput(1)` твоя мандала выглядит аонструозно: попены какие-то, словно на си пишешь
      Ответить

    Добавить комментарий