Открытый документ с приложением ОС по умолчанию в Python, и в Windows и в Mac OS

Как вы можете видеть, люди предлагают вам максимально использовать подготовленные заявления. Это не так, но когда ваш запрос выполняется всего один раз за процесс, будет небольшое снижение производительности.

Я столкнулся с этой проблемой, но я думаю, что решил ее в очень сложном пути - как хакеры используют, чтобы избежать использования кавычек. Я использовал это в сочетании с эмулированными подготовленными заявлениями. Я использую его, чтобы предотвратить все возможные типы инъекций SQL.

Мой подход:

  • Если вы ожидаете, что ввод будет целым, убедитесь, что он действительно целое число. В языке с переменным типом, таком как PHP, этот очень важен. Вы можете использовать, к примеру, это очень простое, но мощное решение: sprintf("SELECT 1,2,3 FROM table WHERE 4 = %u", $input);
  • Если вы ожидаете чего-то еще от целого шестнадцатеричного значения. Если вы отбросите его, вы полностью избежите ввода. В C / C ++ есть функция, называемая mysql_hex_string() , в PHP вы можете использовать bin2hex() . Не беспокойтесь о том, что экранированная строка будет иметь размер в 2 раза по сравнению с исходной длиной, потому что даже если вы используете mysql_real_escape_string, PHP должен выделять одну и ту же емкость ((2*input_length)+1), что то же самое.
  • hex метод часто используется при передаче двоичных данных, но я не вижу причин, почему бы не использовать его во всех данных для предотвращения атак SQL-инъекций. Обратите внимание, что вам необходимо предварительно добавить данные с помощью 0x или использовать функцию MySQL UNHEX.

Так, например, запрос:

SELECT password FROM users WHERE name = 'root'

Будет:

SELECT password FROM users WHERE name = 0x726f6f74

или

SELECT password FROM users WHERE name = UNHEX('726f6f74')

Hex - идеальный выход.

Разница между функцией UNHEX и префиксом 0x

В комментариях было некоторое обсуждение, поэтому я, наконец, хочу дать понять. Эти два подхода очень похожи, но в некоторых отношениях они немного различаются:

Префикс ** 0x ** может использоваться только для столбцов данных, таких как char, varchar, text, block, binary, и т. д. Кроме того, его использование немного сложно, если вы собираетесь вставить пустую строку. Вам придется полностью заменить его на '', или вы получите сообщение об ошибке.

UNHEX () работает в любом столбце; вам не нужно беспокоиться о пустой строке.


Hex-методы часто используются в качестве атак

Обратите внимание, что этот шестиугольный метод часто используется как атака SQL-инъекции, где целые числа точно так же, как и строки mysql_real_escape_string. Тогда вы можете избежать использования кавычек.

Например, если вы просто делаете что-то вроде этого:

"SELECT title FROM article WHERE id = " . mysql_real_escape_string($_GET["id"])

атака может очень легко ввести вас . Рассмотрим следующий введенный код, возвращенный из вашего скрипта:

SELECT ... WHERE id = -1 union all select table_name from information_schema.tables

и теперь просто извлеките структуру таблицы:

SELECT ... WHERE id = -1 union all select column_name from information_schema.column где table_name = 0x61727469636c65

И тогда просто выберите нужные данные. Разве это не круто?

Но если кодер инъекционного сайта будет шестнадцатеричным, инъекция не будет возможна, потому что запрос будет выглядеть следующим образом: SELECT ... WHERE id = UNHEX('2d312075...3635')

115
задан smci 8 May 2019 в 05:57
поделиться

9 ответов

open и start вещи интерпретатора команд для Mac OS/X и Windows соответственно, чтобы сделать это.

Для вызова их из Python можно или использовать subprocess модуль или os.system().

Вот соображения на который пакет использовать:

  1. можно назвать их через os.system, который работает, но...

    Выход: os.system только работы с именами файлов, которые не имеют никаких пробелов или других метасимволов оболочки в пути (например, A:\abc\def\a.txt), или иначе их нужно оставить. Существует shlex.quote для подобных Unix систем, но ничего действительно стандартного для Windows. Возможно, см. также Python, окна: парсинг командных строк с shlex

    • MacOS/X: os.system("open " + shlex.quote(filename))
    • Windows: os.system("start " + filename), правильно говорить filename нужно оставить, также.
  2. можно также назвать их через [1 114] модуль, но...

    Для Python 2.7 и более новый, просто используйте

    subprocess.check_call(['open', filename])
    

    В Python 3.5 +, можно эквивалентно использовать немного более сложное, но также и несколько больше универсальное

    subprocess.run(['open', filename], check=True)
    

    , Если необходимо быть совместимы полностью назад с Python 2.4, можно использовать subprocess.call() и реализовать собственную проверку ошибок:

    try:
        retcode = subprocess.call("open " + filename, shell=True)
        if retcode < 0:
            print >>sys.stderr, "Child was terminated by signal", -retcode
        else:
            print >>sys.stderr, "Child returned", retcode
    except OSError, e:
        print >>sys.stderr, "Execution failed:", e
    

    Теперь, каковы преимущества использования subprocess?

    • безопасность: В теории, это более безопасно, но на самом деле мы должны выполнить командную строку так или иначе; в любой среде нам нужны среда и сервисы интерпретировать, получить пути, и т.д. Ни в том, ни в другом случае мы выполняющий произвольный текст, таким образом, он не имеет свойственного, "но можно ввести 'filename ; rm -rf /'" проблема, и , если имя файла может быть повреждено, использование subprocess.call дает нам мало дополнительной защиты.
    • Обработка ошибок: Это на самом деле не дает нам больше обнаружение ошибок, мы все еще в зависимости от retcode в любом случае; но поведение для явного повышения исключения в случае ошибки, конечно, поможет Вам заметить, существует ли отказ (хотя в некоторых сценариях, traceback нисколько не мог бы быть более полезным, чем простое игнорирование ошибки).
    • Икра (неблокирование) подпроцесс : Мы не должны ожидать дочернего процесса, так как мы проблемным оператором, начинающим отдельный процесс.

    К возражению, "Но subprocess предпочтен". Однако os.system() не удерживается от использования, и это находится в некотором смысле самый простой инструмент для этого конкретного задания. Заключение: использование os.system() является поэтому также корректным ответом.

    А отметил , недостаток - то, что команда Windows start требует Вы передавать в [1 124], который инвертирует большинство преимуществ использования subprocess.

64
ответ дан tripleee 24 November 2019 в 02:20
поделиться

Используйте subprocess модуль, доступный на Python 2.4 +, не os.system(), таким образом, Вы не должны иметь дело с выходом оболочки.

import subprocess, os, platform
if platform.system() == 'Darwin':       # macOS
    subprocess.call(('open', filepath))
elif platform.system() == 'Windows':    # Windows
    os.startfile(filepath)
else:                                   # linux variants
    subprocess.call(('xdg-open', filepath))

двойные круглые скобки - то, потому что subprocess.call() хочет последовательность как ее первый аргумент, таким образом, мы используем кортеж здесь. В системах Linux с Gnome существует также gnome-open команда, которая делает то же самое, но xdg-open Бесплатный Настольный стандарт Основы и работы через настольные среды Linux.

136
ответ дан fearless_fool 24 November 2019 в 02:20
поделиться

Я предпочитаю:

os.startfile(path, 'open')

Примечание, что этот модуль поддерживает имена файлов, которые имеют пробелы в их папках и файлах, например,

A:\abc\folder with spaces\file with-spaces.txt

( документы Python ) 'открытый', не должно быть добавлено (это - значение по умолчанию). Документы конкретно упоминают, что это похоже на двойной щелчок по значку файла в Windows Explorer.

Этим решением являются окна только.

40
ответ дан angussidney 24 November 2019 в 02:20
поделиться

Только для полноты (это не было в вопросе), xdg-открывают сделает то же на Linux.

34
ответ дан dF. 24 November 2019 в 02:20
поделиться
import os
import subprocess

def click_on_file(filename):
    '''Open document with default application in Python.'''
    try:
        os.startfile(filename)
    except AttributeError:
        subprocess.call(['open', filename])
23
ответ дан Nicu Tofan 24 November 2019 в 02:20
поделиться

на Mac OS можно звонить, 'открывают'

import os
os.popen("open myfile.txt")

, это открыло бы файл с TextEdit, или независимо от того, что приложение установлено по умолчанию для этого типа файла

1
ответ дан lcvinny 24 November 2019 в 02:20
поделиться

Если вы хотите указать приложение для открытия файла в Mac OS X, используйте это: os.system ("open -a [имя приложения] [имя файла]")

1
ответ дан 24 November 2019 в 02:20
поделиться

Если вы хотите использовать метод subprocess.call () , он должен выглядеть так в Windows:

import subprocess
subprocess.call(('cmd', '/C', 'start', '', FILE_NAME))

Вы не можете просто использовать:

subprocess.call(('start', FILE_NAME))

потому что start - это не исполняемый файл , а команда программы cmd.exe . Это работает:

subprocess.call(('cmd', '/C', 'start', FILE_NAME))

, но только если в ИМЯ ФАЙЛА нет пробелов.

В то время как subprocess.call метод en правильно цитирует параметры, запускает ] имеет довольно странный синтаксис, где:

start notes.txt

делает что-то еще, кроме:

start "notes.txt"

Первая строка в кавычках должна устанавливать заголовок окна. Чтобы он работал с пробелами, мы должны сделать:

start "" "my notes.txt"

что и делает код сверху.

6
ответ дан 24 November 2019 в 02:20
поделиться

Пуск не поддерживает длинные имена путей и пробелы. Вы должны преобразовать его в пути, совместимые с 8.3.

import subprocess
import win32api

filename = "C:\\Documents and Settings\\user\\Desktop\file.avi"
filename_short = win32api.GetShortPathName(filename)

subprocess.Popen('start ' + filename_short, shell=True )

Файл должен существовать для работы с вызовом API.

5
ответ дан 24 November 2019 в 02:20
поделиться