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

    +1

    1. 1
    2. 2
    In [42]: os.path.join(r'c:\asd', r'c:\www')
    Out[42]: 'c:\\www'

    Нахуя???

    Запостил: syoma, 23 Мая 2018

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

    • If a component is an absolute path, all previous components are thrown away and joining continues from the absolute path component.

      Всё очень секурно. Думаешь защититься от обхода каталога? А вот хер тебе об твой лысый череп?

      Как сделать чтобы os.path.join(path1, path2) не выходил за пределы path1? Ваши версии?
      Ответить
      • Я придумал:
        def myPathJoin(path1, path2):
            return path1.rstrip('\\') + '\\' + path2.lstrip('\\')

        Ы-ы-ы :D
        Ответить
      • Надо проверять второй путь на isabs и на наличие '..'?
        Ответить
        • Это вопрос или утверждение?
          Ответить
          • Это предложение руки и сердца. Можно просто отбраковывать, если второй путь выходит за пределы первого (я не знаю, подходит ли тебе это платье).
            Ответить
            • Возможно. Как это сделать?
              Ответить
              • Я не знаю :)
                Самое простое: если isabs вернет true или в строке есть '\\..\\', то послать нахуй. Или есть функция, которая позволяет узнать, дочерний ли это каталог?
                Ответить
                • Вот в этом и проблема, что всё нужно придумывать самому. Кажется, на это лучше создать отдельное обсуждение.
                  Ответить
        • Кстати, rm -rf /hui/../ ёбнет рут, или сработает защита?
          Ответить
    • Так это автора кода спрашивать надо, что он ожидал, когда передавал в параметры функции хуйню.
      Ответить
      • Такие функции как раз и нужны, чтобы обработать всякую нетривиальную питушню корректно. Конкатенацию хороших строк и наклон дроби в другую сторону в Питонии можно и вручную сделать в одну строку.
        Ответить
        • Я имею в виду, что ожидалось при передаче 2-х абсолютных путей? syoma ожидает первый аргумент, разработчики питонии - второй. Имеют право. И то, и то - одинаково логично.
          Ответить
          • > И то, и то - одинаково логично.
            Согласен.
            Ответить
          • Ожидалось, что оно поможет защитить от обхода каталога. А тут вообще радость - сразу можно абсолютные пути юзать.
            Ответить
            • > поможет защитить
              Как минимум от ".." оно не защищает.
              Ответить
              • Хотя бы от использования абсолютных путей
                Ответить
                • Нужна защита от пользовательского ввода — проверяй как положено, а не надейся, что низкоуровневые функции за тебя это сделают сами.

                  З.Ы. Поведение документировано.
                  Ответить
                  • Ну как сказать пользовательского. Скорее, програмистского, но опечатавшись насрать в корень не хочется. Но это не то же самое что проверка на веб серваке, да.

                    > З.Ы. Поведение документировано.
                    А нахер оно нужно? Как же принцип наименьшего удивления? Какая логика за ним стоит? Или поставили знак "битая дорога" - и можно не ремонтировать?
                    Ответить
                    • > А нахер оно нужно?
                      Как я понял, ради простого использования в конфигах и командной строке, чтобы isabs() не дёргать…
                      os.path.join("/some/default/dir", path_from_config)
                      path_from_config = "foo/bar.txt"  # /some/default/dir/foo/bar.txt
                      path_from_config = "/foo/bar.txt" # /foo/bar.txt
                      Других причин не могу придумать.
                      Ответить
                      • Охереть, и это местечковое поведение они протащили в стандартную библиотеку?
                        Ответить
                        • Х.з., гвидо же вроде лютый сишник. А питон изначально никто и не думал юзать в больших серьёзных проектах… Скорее всего для своих первых скриптов запилил, а потом убирать уже было поздно.
                          Ответить
                          • Была же тройка, где дохера всего перелопатили, включая байтовые строки, из-за чего поломалось дохера софта.
                            Ответить
                          • Кстати, почему всё говно таскают для совместимости долгие годы и не хотят менять?
                            Почему нельзя сделать что-то вида
                            #include <libcversion.h>
                            
                            #ifdef LIBC_V3
                            int Create(const std::string& pathname, mode_t mode);
                            #endif
                            
                            #ifdef LIBC_V2
                            int create(const char *pathname, mode_t mode);
                            #endif
                            
                            #ifdef LIBC_V1
                            int creat(const char *pathname, mode_t mode);
                            #endif

                            А в libcversion.h - что-то вида
                            #if defined (LIBC_LATEST) || defined (LIBC_V3)
                            #  ifndef LIBC_V3
                            #  define LIBC_V3
                            #  endif
                            #elif defined (LIBC_V2)
                            #  ifndef LIBC_V2
                            #  define LIBC_V2
                            #  endif
                            #else
                            #  ifndef LIBC_V1
                            #  define LIBC_V1
                            #  endif
                            #endif

                            Выбираешь себе версию - и вперёд. Страж включения, конечно, придётся сделать более тонким (по стражу на версию, чтоб в разных частях включать разные версии), но это реализуемо.
                            Аналогично - в Питонии, только там даже проще реализовать.
                            Ответить
                            • Как это должно работать на питоне, пример?
                              Ответить
                              • import os as os_old
                                import os:2 as os2
                                import os:latest
                                
                                os.path.join(...) # секьюрно, но совместимость может пострадать
                                os2.path.join(...) # секьюрно и будет работать, пока жив python
                                os_old.path.join(...) # как в старых конфигах у Гвидо
                                Ответить
                                • > os:2
                                  Ну это, по сути, просто новая либа. А старую задепрекейтили и когда-нибудь выпилят. Можно было просто написать os2 с тем же успехом.

                                  > os:latest
                                  Для любителей мазохизма и поломанных билдов? :)
                                  Ответить
                                  • > А старую задепрекейтили и когда-нибудь выпилят.
                                    И потом программа не запускается только потому, что в 2030 году кто-то из соображений перфекционизма в сигнатурах решил выбросить код, стабильно работавший в 2010 и 2020.
                                    Надо хотя бы в репозитории оставить старую библиотеку, не включая в стандартную поставку, чтобы старую прогу можно было запустить в любое время просто после вызова какого-нибудь pip resolve program.py.

                                    >> os:latest
                                    > Для любителей мазохизма и поломанных билдов? :)
                                    Для обычных людей? Сейчас, в общем-то, обычные люди так и живут с os:latest. Разве что, такое версионирование развялало бы руки посильнее.
                                    Ответить
                                • > os_old
                                  На которую тут же забьют болт и даже баги не будут править, как во многих модулях двойки? Да что там модулях, там даже сырые строки не сырые.
                                  Ответить
                                  • И пусть забивают. С ней десять-двадцать лет работало, и будет работать дальше.
                                    Править её надо только если где-то внизу (в ОС, например) что-то поменялось так, что без правок код os_old уже не работает.
                                    Для нового кода - новая версия без багов. Для старого - возможность запускаться как раньше без потребности каждую версию питона отмечать проверками совместимости.
                                    Ответить
                            • Ага, и тебе в либе всё равно все 3 версии поддерживать придётся т.к. ты не знаешь какой клиент будет её юзать. Поэтому обычно просто помечают старые функции как deprecated и через пару лет выпиливают их со злобным смехом. Ну либо запиливают новую либу, несовместимую с предыдущей и какое-то время поддерживают обе.

                              К слову, в libc были такие изменения. К примеру, когда завезли потоки и errno превратилось в макрос. Куча старого софта, где errno любили юзать напрямую, тупо перестала запускаться.
                              Ответить
                              • > тебе в либе всё равно все 3 версии поддерживать придётся т.к. ты не знаешь какой клиент будет её юзать.
                                Но так это придётся поддерживать только в стандартной библиотеке. Интерфейсы обычных библиотек должны быть независимыми от версии стандартной (можно один раз выбрать LIBC_V2 и на ней писать).

                                Но стандартная библиотека не должна поддерживать старые версии, они просто останутся в коде. Изменять их опасно, т.к. на них полагаются. Тут можно даже баги документировать. Изменяться будет только последняя версия, пока поверх неё не появится новое наложение.
                                Ответить
                                • > интерфейсы должны быть независимыми от версии стандартной
                                  Ну т.е. в твоей стандартной либе не будет даже банальных string и vector? Только тоненькая обёртка над ядерным API (которое обязано быть обратно-совместимым иначе вся твоя идея с запуском старых прог развалится), только хардкор?
                                  Ответить
                                  • Почему, пусть будут string и vector. (Впрочем, ничего не мешает убрать string и vector в полустандартную библиотеку вроде Boost, если пакетный менеджер сможет в любое время в один клик доставить нужный кусок Boost нужной версии.)

                                    В стандартной библиотеке будет несколько ревизий нужных функций, поддерживаться и изменяться серьёзно будет только последняя, старые будут только сохранять их контракт и свою работоспособность. В некоторых случаях старые версии могут быть переписаны через новые (если API ОС вдруг сильно изменилось и т.п., когда новая функция более общая), когда это проще для сохранения их работоспособности.

                                    >> интерфейсы должны быть независимыми от версии стандартной
                                    Это про интерфейсы обычных библиотек, которые используют стандартную.
                                    Библиотека Васи Пупкина должна работать согласно её документации, пользователь должен заботиться только о её версии, а не о версиях использованных ей библиотек.
                                    Ответить
                                    • И всем придётся заворачивать string и vector в свои (т.к. стандартные выставить нельзя). Но программисты разумные и они сделают свою либу со string'ом и все будут её юзать. А стандартный останется нахуй никому не нужным. Т.е. его можно было изначально туда не добавлять.

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

                                        Библиотеки можно тогда привязывать к конкретным версиям стандартной библиотеки, описывая это чётко в документации, чтобы пользователь знал, какие точно типы данных там будут и сильнее этого с версиями не возился. (можно реализовать и многоверсионный вариант просто естественным образом переходя на новую версию стандартной библиотеки и замораживая разработку под прошлую версию - тут с учётом фиксированности старых версий стандартной библиотеки поддерживать вообще ничего не надо, если контракт соблюдали)
                                        Ответить
                          • > лютый сишник
                            Сишного говна в сетевой библиотеке более чем дохера. Все эти кальки с сишного api в socket, когда даже в перле любой сокет (клиентский, серверный) со всеми параметрами создавался одним конструктором.
                            Ответить
                            • Ну там же есть create_connection, или его не сразу завезли?
                              Ответить
                              • https://perldoc.perl.org/IO/Socket/INET.html

                                Любой сокет одним вызовом. А в питоне как? И кроме socket() я еще нигде ничего не видел.
                                Ответить
                                • create_connection
                                  Ответить
                                  • > Любой
                                    Слушающий тоже? Почитай по ссылке.

                                    Не видел в реальном коде.
                                    Ответить
                                    • > Не видел в реальном коде.
                                      Потому что реальный код писали сишники, которых socket() не напрягает?
                                      Ответить
                                      • Напитоне пишут одни сишники?
                                        Ответить
                                        • > одни сишники
                                          А остальные юзают высокоуровневые протоколы, реализованные сишниками (http и т.п.)
                                          Ответить
                                          • Доо, сокеты юзают одни дебилы и хакеры, на все протоколы есть модули.
                                            Ответить
                            • Ну а SocketServer тебе чем не нравится?
                              Ответить
                              • Это где?
                                Ответить
                                • https://docs.python.org/2/library/socketserver.html
                                  Ответить
                                  • А SocketClient где?
                                    Ответить
                                    • А он не нужен, клиенту хватит create_connection.
                                      Ответить
                                      • Ты быстренько поправил и думаешь что никто не заметит?
                                        >Ну а SocketServer и SocketClient тебе чем не нравятся?

                                        А create_connection не видно за горой хлама.
                                        Ответить
                                        • > Ты быстренько поправил и думаешь что никто не заметит?
                                          Кстати, некто Борманд недавно запилил на своём сервере штуку, которая пишет все доступные ей версии комментариев.

                                          Борманд, берегись, большой Борманд следит за тобой!
                                          Ответить
                                        • > не видно за горой хлама
                                          Вот за это я и ненавижу доки питона.

                                          К слову о сокетах — какого хуя там есть sendall (отправить буфер целиком), но нету recvall (вернуть ровно N байт или кинуть исключение при EOF)?
                                          Ответить
                                          • Причем тут доки? Я про остальные функции модуля.

                                            Доки самого питона неплохие, но напрягает что они недоступны из ide/консоли. А вот в сторонних либах уже как повезёт.

                                            А в c recvall есть? Что он должен делать? Вообще, всё это нахуй не нужно. makefile() и дальше работаешь как с файлом. В жавке так и сделано (FilteredStream, кажется), можешь считать из потока int и вызов заблокируется, пока в сокет не придут данные в нужном объеме.
                                            Ответить
                                            • > и дальше работаешь как с файлом
                                              Хм, спасибо, попробую.

                                              > Что он должен делать?
                                              Вот это: вызов заблокируется, пока в сокет не придут данные в нужном объеме.

                                              > А в c recvall есть
                                              Так там и sendall нету. Вот эта неконсистентность и бесит. Зачем делать один хелпер, но не делать второй?
                                              Ответить
                                              • В каком объеме? socket.recvall(length), возвращает управление когда пришло length байт? Да, нужная вещь, согласен.
                                                Ответить
                                                • > socket.recvall(length)?
                                                  Да, тип того.
                                                  Ответить
                                                  • Попробуй makefile().read(length), интересно, он будет ждать length байтов?
                                                    Ответить
                                                    • > будет ждать length байтов
                                                      Да должен, по идее, судя по доке он просто читает в цикле.

                                                      З.Ы. Ждёт, всё ок. Спасибо.
                                                      Ответить
                                                      • Доке на file.read()?

                                                        >З.Ы. Ждёт, всё ок. Спасибо.
                                                        Пожалуйста :)
                                                        Ответить
                                                        • > file.read
                                                          Да.
                                                          Ответить
                                                          • А что будет делать sock.makefile().read()? Блокировать и читать пока там сокет не закроют?
                                                            Ответить
                                                            • > Блокировать и читать пока там сокет не закроют?
                                                              Да, так и работает.
                                                              Ответить
                                          • > вернуть ровно N байт или кинуть исключение при EOF
                                            А как себя read() поведёт? Вернёт меньше байтов? Жавка хоть исключение бросала.
                                            Ответить
                      • Докстринг: Join two or more pathname components, inserting "\" as needed. Никакого упоминания даже нет. А в тройке даже докстринга нет. После жавы, где никакой документации на апи отдельной от той, что в сорцах, у меня от этого боль.
                        Ответить
                        • Да в питоне доки какое-то говно, если честно. Портянка-туториал которую надо полностью читать вместо нормального референса.
                          Ответить
                          • +1. Апидока по факту просто нет. А в референсе доки на нужные функции могут быть, а могут и не быть. С апидоками хоть в сырцах сразу видно, где документировали, а где хуй забили.

                            Только если сказать это питонисту - он глазёнки выпучит и побежит на тебя в штыковую. За что я питонокомунити и не люблю (привет, питон.ссу!). Даже пыхари здесь имхо адекватнее.
                            Ответить
                          • зато по прочтении ты реально понимаешь как пользоваться функцией, а вот в джаве с точностью наоборот: референс есть, а туториал отдельно

                            Что толку знать что парметр foo типа bar это anchor если ты не знаешь что такое anchor?

                            Кроме того в питоне тяжело делать референс потому что может быть 28 видов вызова функции с разными kwargs


                            Мне больше всего нравится (внезапно!) MSDN по win32api: там и Remarks очень мощный и референс подобный

                            зацени
                            https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153(v=vs.85).aspx


                            маны у никсов еще иногда бывают ничего (ну кроме опендесктопа конечно)
                            Ответить
                            • А у anchor какой тип? Да, туториалы могут быть полезны, но сука, мне хочется иметь доки на апи. Их не просто так придумали.

                              > win32api
                              Низкоуровневое говно.
                              Ответить
                            • >Кроме того в питоне тяжело делать референс потому что может быть 28 видов вызова функции с разными kwargs
                              А потом ты видишь код, работающий не так как надо, сидишь и смотришь на него как баран на новые ворота.
                              Ответить
                            • > 28 видов вызова функции с разными kwargs
                              Во-первых, можно по каждому аргументу написать, что туда написать.
                              Во-вторых, 28 непересекающихся наборов - это уже говнокод, а 5-6 вполне можно оформить как перегрузки.
                              И сделать конфетку как на cplusplus.com
                              Ответить
                  • > проверяй как положено, а не надейся, что низкоуровневые функции за тебя это сделают сами
                    Но для того, чтобы проверять как положено, должны быть специальные библиотечные функции, которые учитывают всё, что можно, прошли месяцы/годы проверок в реальных ситуациях, аудит или хотя бы множественное прочтение сообществом.
                    Тупые функции, которые ничего не проверяют, можно и самому написать. А секьюрную питушню надо в стандартную библиотеку и на каменных плитах выдолбить, чтоб своими велосипедами багов не добавляли.
                    Ответить
                    • Тем более, то, что работает на прыщах (абсолютный путь начинается с /), не работает на винде (он может начинаться с буквы диска). Это я даже про слеши не говорю. Собсно, для этого os.path и придумали.
                      Ответить
      • Да??? Про пользовательский ввод не слышал?
        Ответить
    • > Нахуя???
      Такое поведение тоже нужно в некоторых случаях. Только недавно сталкивался: надо было взять путь, и если он был не абсолютный, добавить к нему каталог по умолчанию.
      Авторам надо было реализовать оба варианта, т.к. оба на практике нужны.

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

          Тем более, если это вэб-сервер. Хрен знает, что там будет на выходе - старшие байты обрежутся, символ после приведения к инварианту станет точкой, кто-нибудь засунет полусимвол, который вызовет исключение в декодере или ещё какая питушня произойдёт. JSFuck смог пролезть через 6 символов, а тут тысячи их. Тем более, на вэб-сервере это перейдёт в безумные xn--p1ai или в %A1%D0. Ну и мировому сообществу кириллица и иероглифы нафиг не нужны, особенно если ссылку надо где-то напечатать.
          Ответить
          • Это не вэб-сервер. С чего ты это взял?
            Ответить
            • Не знаю, просто секьюрность для путей обычно нужна именно в случае, когда есть сервер и клиент, которому нельзя доверять. Для обычного пользователя можно обойтись настроенными правами; для домашнего пользователя - принципом "удалил c:\ - сам виноват".
              Ответить
    • Ох ебать, os.path.join("c:", "foo") выдаст c:foo, которое не эквивалентно c:\foo…
      Ответить
      • Джвоеточие - это же доступ к альтернативному потоку foo файла c?
        Ответить
        • c:foo - это файл в текущем каталоге на диске c. Кто юзал нортоноподобные менеджеры файлов, должен был заметить, что на каждом диске есть свой текущий каталог.
          Ответить
          • Я просто Фигурнова в своё время читал, даже до того, как у меня появился комп.
            Ответить
          • ОМГ, какое говно. Запустил cmd и познал НЕКОНСИСТЕНТНОСТЬ.
            То есть
            c:foo - это файл foo в текущем каталоге на диске c
            cc:foo - это поток foo файла cc в текущем каталоге
            То есть если понадобится писать в потоки произвольных файлов, надо следить, чтобы их имена не совпадали с именами дисков, иначе перетрутся не потоки, а файлы.
            Ответить
            • > не совпадали с именами дисков
              Там вроде ещё COM1 в любом месте пути можно писать было (C:\foo\com1 откроет com1).
              Ответить
              • Зарезервированные имена файлов уже научились фильтровать. Помню один сервак, который мог хранить юзерские данные в файлах, по файлю с юзернеймом на юзера. При попытке создать юзера с именем lpt1 он вис.
                Ответить
            • Это не цмд а ядро винды.
              Ответить
              • Не ядро, а kernel32.dll. Ядро, емнип, вообще не оперирует понятием "текущей директории". Да и все эти C:\ для него просто алиасы на что-то в духе \Device\Partition1 (привет, unix).
                Ответить
                • А пернул это не ядро? Или ты в том смысле, что оно в третьем кольце?
                  Ответить
                  • Это всего лишь эмулятор API винды 3.1 поверх настоящего NT'шного :)
                    Ответить
                    • Это обёртка для холопов и анскилябр заедушных над настоящим NT'шным API, а настоящее NT'шное API предназначено для настоящих Царей.
                      Ответить
                    • А как юзать нтшное?
                      Ответить
                      • Сложно. Хедер со всеми функциями, емнип, майкрософт не публикует. Функции страшные — по десятку параметров.
                        Ответить
                        • Но функции с W на конце не с 3.1 же пришли?
                          Ответить
                          • Если верить вики — то вообще из NT. А для 9х просто dll'ку с ними подложили.
                            Ответить
                            • И эта дллка перешла в nt?
                              Ответить
                              • Всё было наоборот. Windows NT 3.х (не путать просто с 3.x) появилась раньше, чем 95. kernel32.dll в NT уже была.

                                В 95 решили сохранить тот же API, что и у NT, но сделать его на другом ядре (реанимировать ядро 3.1).
                                Ответить
                          • Во-первых, 3.1 и в 95 не было NT-шного ядра (у них было своё, доступ к которому был через прерывание 20h, гугли: vxd). Но kernel32.dll (в 95 и в 3.1 в доп. пакете Win32s) косплеил функции с A на конце от NT.

                            Функции с W на конце были только в линейке NT. В 95 можно было использовать юникод, но заднепроходным методом.
                            Ответить
                            • Вру, функции с W на конце в 95 были, но не все.

                              Kernel32.dll в 95 снаружи была пародией на kernel32.dll из NT, а внутри эти dll были устроены по-разному.
                              Ответить
                              • Были, но не всегда они что-то делали.
                                Ответить
                    • И она поэтому к ядру не относится уже?
                      Ответить
              • От этого не легче, а даже наоборот. Выстрел в ногу уровня ОС.
                Ответить
                • Ну есть \\.\, в котором похер на зарезервированные имена, а также есть доступ к тому как к файлу (аналог /dev/sda*)
                  Ответить
            • Познай ещё одну неконсистентность:
              https://www.mcafee.com/ca/downloads/free-tools/dire.aspx

              Допустим, в реестре маздайки в автозапуске прописана программа по такому пути:
              C:\Program Files\Peetooh\peetooh.exe

              Но прописана без кавычек.

              Всё работает до тех пор, пока злоумышленник не создаст в корне диска C: файл Program.exe. Как только программа появится, вместо оригинального peetooh.exe запустится C:\Program.exe с параметром Files\Peetooh\peetooh.exe.

              Утилита DIRE компании McAfee как раз ищет такие проблемные записи в реестре и предлагает добавить кавычки вокруг пути.
              Ответить
              • Причём эта эвристика с поиском пробела, по которому надо разбить командную строку, вшита в даже не в шелл, а прямо в CreateProcess.
                Ответить
                • Наследие 3.1? Или 95?
                  Ответить
                  • В 3.1 не было путей с пробелами.

                    Это наследие 95 или NT 4.0 (именно в ту эпоху появились директории Program Files, Мои Документы и т. п.)
                    Ответить
                    • Да, точно. Но нахуя?
                      Ответить
                      • В 3.1 не было нужды в таких именах файлах: там название ярлыка не совпадало с именем файла ярлыка (имя файла могло генерироваться случайным образом).

                        В 95 и в NT4 решили избавиться от старого Диспетчера программ из 3.x и ввести Рабочий стол. На рабочем столе решили "очеловечить" имена объектов: ввели длинные имена файлов (с пробелами, с юникодом), стали скрывать расширения файлов от пользователей, отказались от ярлыков 3.х и ввели свои. Попытались сделать ОС для чайников, но без промежуточного слоя (чтобы нигде не хранить отображение имён файлов в "очеловеченные" имена для чайников).

                        И чтобы не было совсем скучно, первой "очеловечили" директорию Program Files (правда, в русифицированной винде её название переводить не стали, в отличие от Моих Документов).
                        Ответить
                        • Нахуя пытаться открыть так, если не получится - открывать эдак?
                          Ответить
                          • Потому что пытались создать систему для дураков. Разрешили "упрощённый" синтаксис, т. е. разрешили не обрамлять путь кавычками и не экранировать пробелы, если эвристика позволяет разобрать командную строку.

                            Но вопрос, нахуя, остаётся открытым. Блондинка всё равно сама ничего не будет прописывать в реестре и не будет вызывать CreateProcess. А для программиста и даже для сисадмина добавить кавычки - пара пустяков.

                            Лучше бы сделали жёсткую проверку без эвристики.
                            Ответить
                      • И самое главное: почему разработчики винды за это взялись?

                        В классической MacOS файлы назывались вилками (forks), потому что состояли из двух частей: данные (это то, что мы обычно понимаем под содержимым файл) и ресурсы (а это изобретённые в Эппле метаданные: иконка файла, "очеловеченное" название, понятное для блондинок, описание и т. п.).

                        Разработчики винды пытались это повторить, но в упрощённом виде. От полной реализации ресурсной части отказались, поэтому ввели длинные имена файлов, чтобы "понятное" название хранить тупо в имени.

                        В NTFS появились альтернативные потоки, в которых уже можно хранить метаданные, но они до сих пор мало используются. Например, браузеры помечают файлы, скачанные из интернета (типа installer.exe:Zone.Identifier), чтобы винда при попытке запуска выдала предупреждение, что экзешник ненадёжный.
                        Ответить
    • https://bugs.python.org/issue28488

      Питон на винде до 2016 года архивы нормально создавать не умел.
      Ответить
      • > New changeset 847537b7924c by Serhiy Storchaka in branch '2.7':
        > New changeset d4fce66ebe01 by Serhiy Storchaka in branch '3.5':
        > New changeset e93149fee04d by Serhiy Storchaka in branch '3.6':

        А 3.4 больше не фиксят?
        Ответить
        • Нет, не фиксят. Как накатывать патчи на дистр? Или написать в файлик список патчей на дистр после установки?
          Ответить

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