Архив метки: php

3 способа загрузки файла на сервер с помощью curl

Продемонстрируем curl запрос на примере, с учетом следующих ограничений.
1. Файл надо загрузить методом POST
2. Необходима авторизация
3. На сервере установлен сертификат ssl

Способ 1, командная строка: Загрузка файла непосредственно через командную строку выглядит так:

curl -i -u user:password -X POST --form datafile=@/path/to/some/file.txt https://localhost:443/page --insecure

Разберем подробнее:
-X — указываем метод POST
-u — логин и пароль пользователя
—insecure — при работе по https часто приходится тестировать в тестовом окружении где не стоит проверенный сертификат. Этой опцией отказываемся от проверки.
Чтобы ещё более подробно узнать о тонкостях команды, используйте curl —help

Способ 2, PHP: Продемонстрируем как загрузить файл

// очень полезно предварительно сделать проверку на наличие библиотеки curl для php
if  (!in_array  ('curl', get_loaded_extensions())) {
    exit("CURL is NOT installed on this server");
}

        $ch = curl_init();
        //указываем url адрес на сервере
        curl_setopt($ch, CURLOPT_URL, 'https://localhost:443/page');
        // чтобы возвращало
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        // указываем метод POST
        curl_setopt($ch, CURLOPT_POST, 1); 
        // этот параметр для указания логина и пароля
        curl_setopt($ch, CURLOPT_USERPWD, "login:password");
        curl_setopt($ch, CURLOPT_POSTFIELDS, [
                'some_more_data' => 'здесь можно передать дополнительные параметры, например если эмулируется отправка формы',
                'datafile' => curl_file_create('/path/to/file.txt' , mime_content_type($path_to_file), basename('/path/to/file'))
            ]
        );
        // проверка peer для ssl отключена, смотрите также CURLOPT_SSL_VERIFYHOST для полного игнорирования ssl сертификата
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 
        // все опции выставлены - выполняем запрос
        $result = curl_exec($ch);
        // распечатываем ответ сервера
        var_dump($result); 
        // закрываем соединение
        curl_close($ch);

Практически всё прокомментировано в коде, однако отмечу функцию curl_file_create , один сервер постоянно ругался что файл как-то не так указан или отсутсвует. Это вылечилось добавлением мим типа, т.е. функция curl_file_create создает дополнительные заголовки для корректной отправки файла.

Способ 3, Python : Наконец дошли до python, здесь воспользуемя отличной библиотекой requests

import requests

    auth = ('user', 'password')
    data = [
        ('some_more_field', 'some_field_data')
    ]

    # curl request
    files = {'datafile': open('/path/to/file.txt', 'rb')}
    r = requests.post('https://localhost:443/page', files=files, data=data, auth=auth)
    print(r.text)

В указанном примере открываем файл в режиме бинарного чтения, и дальше сразу делаем запроc. В запросе указаны параметры авторизации, метод, страница и файл. Если файлов несколько — просто расширьте словарь files.
Всё просто, удачи с curl!

Создание простого плагина с ajax на wordpress

В данном посте будет пошагово описано как создать простейший плагин для wordpress с аяксом.
Собственно вся соль в ajax — так как есть пара тонких мест. Разобьем руководство на две части, в первой опишем просто создание минимального плагина, а во второй части как добавить асинхронный вызов ajax

Часть 1 — создание базового плагина

шаг 1. создать папку с названием плагина в директории wp-content/plugins , например simple-ajax
шаг 2. создать php файл в созданной директории simple-ajax.php и написать туда следующее:

/*
Plugin Name: Simple Ajax WordPress Plugin
Plugin URI: http://zabaykin.ru
Description: Visualization of assistant invoice API
Version: 1.0.0
Author: zabaykin
Author URI: http://zabaykin.ru/
*/

После этого шага уже можно идти в панели администраторов в раздел плагины и активировать плагин.
шаг 3. Создаем функцию base_plugin

function base_plugin() {
    ob_start();
    echo "< button id='ajax_button' >press for ajax< /button >";
    return ob_get_clean();
}

шаг 4. Регистрируем созданную функцию в wordpress с помощью специальной функции

add_shortcode( 'base_plugin_shortcut', 'base_plugin' );

Разумеется, название может быть абсолютно другое, суть именно в регистрации shortcode вордпреса
шаг 5. Создаем новую страницу в панели администратора и в месте где понадобится плагин — пишем прямо в тексте [base_plugin_shortcut] . После сохранения можно открыть созданную страницу и убедиться, что конопка появилась. Таким образом первая часть создания плагина завершена, далее добавляем ajax.

Часть 2 — Асинхронный вызов ajax в wordpress

шаг 1. Для аякса понадобится javascript, поэтому рядом с файлом simple-ajax.php создадим файл simple-ajax.js со следующим содержимым:

jQuery(document).ready(function ($) {
    $('#ajax_button').click(function(){
        $.ajax({
            method: "POST",
            url: simple_ajax_url_obj.ajax_url,
            dataType: "json",
            data: {
                action: 'get_ajax_response'
            }
        })
            .done(function (data) {
                console.log('YES!!')
                console.log(data);
            })
            .fail(function (data) {
                console.log('ERROR')
                console.log(data);
            });
    })
});

шаг 2. Созданный javascript файл надо подключить, поэтому обновим нашу базовую функцию, дополнив её следующими строками:

function base_plugin() {
    ob_start();
    echo "< button id='ajax_button' >press for ajax< /button >";
    
    # ajax
    wp_enqueue_script( 'simple-ajax', plugins_url( '/simple-ajax.js', __FILE__ ), array('jquery'), '1.2', true );
    wp_localize_script( 'simple-ajax', 'simple_ajax_url_obj', array( 'ajax_url' => admin_url('admin-ajax.php')) );
    return ob_get_clean();
}

Небольшое пояснение, с помощью функции wp_enqueue_script регистрируем скрипт, указываем путь до него и указываем зависимости. В нашем случае будет использоваться jquery, поэтому укажем минимальную версия 1.2 . После регистрации скрипта, необходимо создать объект javascript , в котором будет прописан URL для ajax. Это как раз делается с помощью wp_localize_script — создается объект simple_ajax_url_obj и указывается url до php скрипта. Про action расскажем чуть ниже.
шаг 3. Также обязательно понадобятся php функция — обработчик ajax

function get_ajax_response(){
    echo "ajax base plugin for wordpress works fine!"
    wp_die();
}

Обязательно заканчивайте аяксовую функцию с помощью wp_die
шаг 4. Регистрация экшена в php. Помните в javascript был указан action: ‘get_ajax_response’ ? Пришло время его объявить и связать с php функцией. Это делается с помощью следующих двух функций

add_action( 'wp_ajax_get_ajax_response', 'get_ajax_response' );
add_action( 'wp_ajax_nopriv_get_ajax_response', 'get_ajax_response' );

Если не указать wp_ajax_nopriv — то запросы смогут делать только авторизованные пользователи. Поэтому если хотим чтобы все могли делать аяксовый запрос — необходимо добавить часть с nopriv.
Стоит отметить, что практически все запросы ajax (и с фронтенда и с бекенда) идут через административную часть admin-ajax.php, поэтому если действия подразумевают администрирование — то надо чтобы wp_ajax_nopriv_(action) хук был всегду обрамлен is_admin() === true для безопасности.

Таким образом, по нажатию кнопки в консоли браузера (консоль вызываетмся кнопкой F12) будет отображено «ajax base plugin for wordpress works fine!» И данное сообщение уведомит о том, что ваш плагин с аяксом для вордпреса работает.

Пример использования curl для работы через proxy сервер

Достаточно часто при написании пауков стоит задача получения контента сайта не напрямую, а через прокси сервера. Поэтому приведу здесь пример простой функции на php для получения html кода страницы используя библиотеку curl.
В первую очередь надо убедиться curl установлен и что в php.ini раскомментирована строка, подключающая библиотеку curl. Далее функция:

function get_data($url)
{
  $ch = curl_init();
  $timeout = 5;
  curl_setopt($ch,CURLOPT_URL,$url);
  curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
  //proxy
  curl_setopt($ch, CURLOPT_PROXY, 'ii.nnn.ru:3128');
  curl_setopt($ch, CURLOPT_PROXYUSERPWD, '111:111');
  curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
  $data = curl_exec($ch);
  if($data === false)
  {
	echo 'Curl error: ' . curl_error($ch);
  }
  curl_close($ch);
  return $data;
}

Примерно такой функцией приходится пользоваться разработчикам, у которых выход в интернет доступен только через proxy. Можно попробовать использовать функцию stream_get_contents, но все же curl предлагает более мощный инструмент.

Простой анализ лог файла access.log apache на php

Пусть есть лог файл апача, надо из него выбрать

  1. десять IP адресов, с которых идет больше всего запросов
  2. десять самых популярных страниц

Данную задачу я даю студентам для ознакомления с регулярными выражениями. Одно регулярное выражение должно выбирать айпи адрес с начала строки, а над вторым надо немного пофантазировать. Для написания программы прежде всего следует ознакомиться со структурой access.log.  Приведем типичную строку из файла логов apache, который имеет следующую структуру (Combined Log Format).

127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "http://www.example.com/start.html" "Mozilla/4.08 [en] (Win98; I ;Nav)"

Как видим логируется айпишник с которого идет запрос (127.0.0.1), время запроса, метод (GET), URL запроса, статус ответа (200), количество байт (2326), referrer, информация о браузере и операционной системе.

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

<?php
//считываем файл
$text=file_get_contents('access.log');
//задаем шаблон регулярного выражения
$pattern='#(([0-9]{1,3}\.){3}[0-9]{1,3}).{1,}GET ([0-9a-z/\_\.\-]{1,})#i';
//вытаскиваем данные в массив matches
preg_match_all($pattern,$text,$matches);
$ip=array_count_values($matches[1]);
$adr=array_count_values($matches[3]);
//сортируем по убыванию
arsort($ip);
arsort($adr);
//выделяем десятку
$ip_10=array_slice($ip,0,10);
$adr_10=array_slice($adr,0,10);

echo "10 самых активных пользователей по ip адресу";
echo "IP Количество\n";
foreach($ip_10 as $key=>$value)
{
	echo $key.' '.$value;
}

echo "10 самых посещаемых страниц\n";
echo "Страница Количество\n";
foreach($adr_10 as $key=>$value)
{
	echo $key.' '.$value;
}

Как получить access_token для вконтакте на PHP

Некоторые серверные методы вконтакте не требуют никакой авторизации. Но для некоторых методов предварительно нужно получить access_token. Для этого напишем функцию для его получения. Так как запросы идут через https, то вам понадобится включить расширение extension=php_openssl.dll в php.ini . Далее зайти в настройки приложения и вытащить его ID и закрытый ключ. Этих данных достаточно для написания функции:

define('CLIENT_ID', 12345678);
define('CLIENT_SECRET', 'AbCdEfGhiqwerty');

function getVKToken(){
	$token_url = 'https://oauth.vk.com/access_token?client_id=' . CLIENT_ID . '&client_secret=' . CLIENT_SECRET . '&v=5.28&grant_type=client_credentials';
	$json = file_get_contents($token_url);
	$token = json_decode($json);
	return isset($token->access_token) ? $token->access_token : false;
}

echo getVKToken();

Получение координат места по адресу

Пусть перед нами поставлена следующая задача: есть файл in.txt со списком адресов в разных городах по России. Нам необходимо написать программу, результатом работы которой будет выходной файл out.txt , в соответствующей строке должна быть широта и долгота места.

Решение данной задачи предполагает использовать метод геокодирования, который предлагает Yandex static API.

Для этого напишем следующий код на PHP

//by default max execution time is 30 seconds. But grabber need more time.. so let's set to unlimited
set_time_limit(0);

$file = fopen('in.txt', 'r');
$res = array();
while ($line = fgets($file)){
    echo $line;
    echo "
";

    $params = array(
        'geocode' => $line, //address
        'format'  => 'json', //response format
        'results' => 1, //number of output result, first is the best
    );
    $response = json_decode(file_get_contents('http://geocode-maps.yandex.ru/1.x/?' . http_build_query($params, '', '&')));

    if ($response->response->GeoObjectCollection->metaDataProperty->GeocoderResponseMetaData->found > 0)
    {
        $res[] = $response->response->GeoObjectCollection->featureMember[0]->GeoObject->Point->pos;
    }else{
        $res[] = ' - ';
    }
    //wait a bit (0.2 sec). it will predict blocking
    usleep(200000);
}
fclose($file);

//writing into file
file_put_contents('out.txt', implode("\n", $res));

В принципе всё очень просто, но немного прокомментирую:
1) как и в любом пауке, загрузка может занять много времени, поэтому не забываем увеличить время исполнения скрипта — set_time_limit()
2) Все файлы должны находится в кодировке utf-8
3) Иногда для одного запроса может находится несколько подобных мест, поэтому мы ограничиваем результат в 1 ответ — он по умолчанию самый подходящий
4) Если ничего не нашлось, то в файл будет записан прочерк
5) Брутфорсить и закидывать запросами ресурс не очень хорошо, поэтому чтобы нас не отключили за бомбёжку ставим задержку. Здесь поставлена задержка в 0.2 секунды

В результате исполнения данного скрипта, появится файл out.txt c географическими координатами каждого адреса, написанного на естественном языке. Более того, даже если адреса написаны с орфографической ошибкой, очень большой шанс что яндекс правильно интерпретирует и найдет в своей базе именно нужный объект.