Страницы

Поиск по вопросам

Показаны сообщения с ярлыком header. Показать все сообщения
Показаны сообщения с ярлыком header. Показать все сообщения

воскресенье, 8 марта 2020 г.

Редирект на 404 страницу

#php #http #редирект #header


В .htaccess прописал:

ErrorDocument 404 /views/error.html


В скрипте отправляю заголовок:

header($_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found', true, 404);
exit();


Перенаправление не срабатывает.
Пробовал и так писать:

header('HTTP/1.1 404 Not Found', true, 404);
header('HTTP/1.0 404 Not Found', true, 404);
header('HTTP/1.1 404 Not Found');
header('HTTP/1.0 404 Not Found');


Не срабатывает всё равно. Может что-то дописать нужно ещё?
    


Ответы

Ответ 1



ErrorDocument верно срабатывает, когда реально нет страницы. Передача заголовка лично у меня тоже верно сработала, и в целом должна верно срабатывать, если сервер и php верно настроены. Но при этом во втором пункте apache уже не собирается переадресацию какую-то делать, так как он не видит в этом смысла - ErrorDocument срабатывает именно что на реальное отсутствие страницы или отсутствие правил редиректа для запрошенного адреса, когда же страница просто отдает код 404 - это ее дело. Далее подразумевается, что нужно самому вывести нужное. То есть либо заинклудить целиком страницу, лежащую по пути /views/error.html примерно таким кодом: if (we_have_404) { header($_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found', true, 404); include "/views/error.html"; exit(); } дабы минимизировать повторяющийся код на сайте, либо выводить что-либо свое.

пятница, 28 февраля 2020 г.

Имена файлов с исходным кодом в C/C++

#cpp #c #header



Имеются ли какие-нибудь ограничения для имени source-файла в C/C++? (в Java, например,
имя source-файла должно совпадать с именем класса в нем)
Должны ли .h/.hpp и .c/.cpp файлы иметь одинаковое имя? Если нет то когда я пишу
#include как компилятор узнает где находится реализация header'а?

    


Ответы

Ответ 1



Можете называть, как хотите - даже необязательно с расширением .cpp или подобным, только тогда надо пояснить компилятору, что это - исходный текст, а не что-то иное :) Заголовочные файлы вообще могут быть какими угодно - так как их имя четко указывается в директиве #include. То, что вы называете "реализацией хедера", обычно находится в библиотеках, которые подключаются компоновщиком. Или, если это ваш код - в одном из ваших .cpp-файлов, например. Или в нескольких :) - как уж вы напишете. Или даже в собранной вами собственной библиотеке.

вторник, 25 февраля 2020 г.

Разделение класса в заголовочный файл и в файл с кодом

#cpp #header #build


Вроде всегда так класс разделял в h-хедерные файлы и cpp-файлы с кодом, но в этот
раз что-то пошло не так :( 
Пишет Unresolved external blablabla.obj
Main  Header  CPP 
Подскажите, пожалуйста, где я в этот раз ошибся?    


Ответы

Ответ 1



Проблема в шаблонах. Шаблоны надо размещать полностью в header'е. Дело в том, что шаблонный класс не есть класс, и не генерирует вовсе никакого кода. Код будет сгенерирован «задним числом» в момент инстанциации шаблона, то есть, в тот момент, когда вы объявляете шаблон с конкретным параметром! (В вашем случае это main.) Если выгрузить имплементацию шаблона в .cpp, она будет в этой точке компиляции недоступна, и приведёт к ошибке компоновки. Есть, правда, ещё один путь: если вы точно знаете все типы, с которыми будет когда-либо инстанциироваться шаблон, вы можете оставить имплементацию в .cpp, и добавить туда список для явной инстанциации: template class Stack; Но это сработает только лишь если вы контролируете все места, где ваш шаблон будет использован. Если вы пишете библиотеку общего пользования, вы не можете знать наперёд, с какими типами её будут использовать клиенты, то есть этот трюк не пройдёт, и вам таки придётся писать всё в header'е. (Так работает вся STL, например.) Дополнительное чтение по теме: [C++ FAQ/Templates/linker errors].

воскресенье, 12 января 2020 г.

CAUTION: provisional headers are shown

#google_chrome #header #php #http


Привет...
У меня проблема в Chrome.
Запрос вроде не отправляется и в консоли на этом пакете выводится это сообщение.
Что может означать это и по каким причинам:

Запрос не отправляется?
Ответ не приходит?
Сервер не  генерирует ответ на вопрос?
    


Ответы

Ответ 1



Какое-то расширение блокирует запрос. Попробуйте запустить Chrome в режиме Инкогнито (Ctrl + Shift + N). Дополнения будут отключены.

Ответ 2



Ресурс может блокироваться расширением Сообщение есть, потому что запрос на получение этого ресурса никогда не был выполнен, поэтому отображаемые заголовки не являются реальностью. Как пояснялось в проблеме, на которую вы ссылались, реальные заголовки обновляются, когда сервер отвечает, но нет ответа, если запрос был заблокирован. Введите chrome://net-internals в адресную строку и нажмите enter. Откройте страницу с проблемами. Вернитесь к сетевым внутренним элементам, нажмите events (###) и используйте текстовое поле, чтобы найти событие, связанное с вашим ресурсом (используйте части URL-адреса). Наконец, нажмите на событие и посмотрите, подскажет ли вам информация.

суббота, 11 января 2020 г.

RecyclerView - динамичное добавление header

#android #recyclerview #header


Мне приходит JSON массив с сервера с датой и количеством сообщений. Мне нужно сделать
список в котором дата будет находиться перед началом сообщений этой даты. Никак не
пойму как можно научить адаптер строить такой список. 

Помогите, покажите пальцем, куда копать? 

Есть примерный способ реализации:


Завести массив с датами сообщений в формате HH:mm
???

    


Ответы

Ответ 1



Организация данных такая, что нужно распарсить JSON в объекты модели, каждая модель будет содержать поле даты и поле записи. Коллекцию необходимо отсортировать по возрастанию даты. Для начала нам понадобится два типа разметок. Первая будет отображать дату и запись (layout.header), вторая - только запись (layout.record). Разметка layout.header включает в себя разметку layout.record через include. layout.record: layout.header: Логика определения, какой тип View выводить основана на сравнении даты текущей записи и прошлой - если они не равны, то выводить заголовок с датой и записью, иначе только запись. Нулевой элемент обрабатывается отдельно и всегда содержит дату и запись. Так же прошу обратить внимание на организацию блока switch - case в методе onBindViewHolder(). При выводе View с датой case выводит дату на разметку и "проваливается" на следующий case (нет оператора break), где на разметку выводится запись. Если заголовок не требуется, то на разметку дата не выводится (срабатывает второй case) class SomeAdapter extends RecyclerView.Adapter { private ArrayList mData; private final int TYPE_HEADER = 0; private final int TYPE_ITEM = 1; public SomeAdapter (ArrayList data) { mData = data; } @Override public ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v; switch (viewType) { case TYPE_HEADER: v = LayoutInflater.from(parent.getContext()).inflate(R.layout.header, parent, false); break; default: v = LayoutInflater.from(parent.getContext()).inflate(R.layout.record, parent, false); } return new ItemHolder(v); } @Override public void onBindViewHolder( ItemHolder holder, int position) { int type = getItemViewType(position); switch (type) { case TYPE_HEADER: holder.mHeaderDate.setText(mData.get(position).getDate())); case TYPE_ITEM: holder.mItemRecord.setText(mData.get(position).getRecord()); break; } } @Override public int getItemCount() { return mData.size(); } @Override public int getItemViewType(int position) { if (isIdentType(position)) return TYPE_ITEM; return TYPE_HEADER; } private boolean isIdentType (int position ){ if (!(position == 0)&&(mData.get(position).getDate()).equals(mData.get(position-1).getDate())) return true; return false; } public static class ItemHolder extends RecyclerView.ViewHolder{ TextView mHeaderDate; TextView mItemRecord; public ItemHolder(View v) { super(v); mHeaderDate = (TextView) v.findViewById(R.id.date); mItemRecord = (TextView) v.findViewById(R.id.record); } } Естественно, разметки нужно оформить покрасивее как то, выделить дату можно другим фоном или другое. Данный пример - только идея.

суббота, 4 января 2020 г.

header('Location:') не перенаправляет

#php #header


Если кратко то есть функция

static function ErrorPage404()
{
    $host = 'http://'.$_SERVER['HTTP_HOST'].'/404';
    header('HTTP/1.1 404 Not Found');
    header("Status: 404 Not Found");
    header('Location:'.$host.'');
    exit();
}


В нужный момент ее вызываю и на локальном хостинге все работает... Но при переносе
срабатывают все заголовки, кроме location ... 
Подозреваю что дело в настройке сервера (возможно из за SSL, включен 301 редирект
с http на https) но не могу докопаться...

Читал подобные проблемы, но решения так и не нашел...
Вот что пробовал:
Установил значение output_buffering = On,ob_start(),ob_end_flush();

Вот что выдает браузер(название сайта заменил):

Request URL:https://site.ru/avtolombard/asd
Request Method:GET
Status Code:404 Not Found
Response Headers
view source
Connection:Keep-Alive
Content-Encoding:gzip
Content-Length:14247
Content-Type:text/html; charset=UTF-8
Date:Sat, 04 Mar 2017 19:36:07 GMT
Keep-Alive:timeout=3, max=100
Location:http://site.ru/404
Server:Apache
Vary:Accept-Encoding,User-Agent


В действительности оказалось, что не работает Location с заголовком 404... Спасибо
@Qwertiy за совет по поводу неудобства для пользователя. По итогу добавил пару условий
в маршрутизатор и выдаю контент 404-й станицы с заголовками 404, не меняя URL
    


Ответы

Ответ 1



Есть такое подозрение, что заголовок location работает только с трёхсотой группой кодов. Вроде 404 надо отдавать прям страницей ошибки, а не пытаться туда упихать редирект. В принципе можно попробовать Refresh: 3; URL=http://site.ru/404 Но вообще, это плохая идея, портить адрес страницы. Вот перепечатывал пользователь какой-то url, опечатался в одной букве и теперь ему всё вводить заново? Вместо того, чтобы просто исправить?

Ответ 2



404 следует отдавать без редиректа, через readfile или include, например. static function ErrorPage404() { header('HTTP/1.1 404 Not Found'); header("Status: 404 Not Found"); include('path/to/404.php'); exit(); } Наличие редиректа в любом случае предполагает 3xx статус. Если же вебсервер пропускает 404 совместно с Location - у браузера нет никаких причин для перехода.

Ответ 3



Что-то подобное видел. Дело было в exit(), он по разному ведет себя на разных серверах. Возможно дело в php или в настройках. Может попробовать в конце return ? Это правильней.

пятница, 27 декабря 2019 г.

drupal 304 Not Modified не найден

#drupal #seo #header


Здравствуйте. Сайт на Drupal 7 на виртуальном хостинге. При тестировании https://last-modified.com/ru/if-modified-since.html
. Результат - тест провален (Last-Modified найден! 304 Not Modified не найден!) Смотрю
файл bootstrap.inc - вроде как есть условия для отдачи этого заголовка.... 

Подскажите как настроить? (любой вариант кроме патча ядра, возможно есть готовые модули)
    


Ответы

Ответ 1



Если используется nginx, то по умолчанию он обрубает этот заголовок. Надо включить модуль SSI (Server Side Includes), по умолчанию он отключен. server{ ... ssi on; ssi_last_modified on; ... } Больше информации: http://nginx.org/ru/docs/http/ngx_http_ssi_module.html#ssi_last_modified

среда, 25 декабря 2019 г.

Стандарнтые заголовочные файлы внутри stdafx.h

#cpp #visual_studio_2015 #header


Стоит ли включать в предкомпилированный заголовочный файл stdafx.h заголовочные файлы
стандартной библиотеки (string, algorithm и т.п.), ведь они не изменяются? 

Смущает то, что необходимо писать #include "stdafx.h" в каждом .cpp файле. Используется
Visual Studio 2015.
    


Ответы

Ответ 1



Если вы приняли решение использовать Precompiled Headers (для ускорения сборки), то заголовки стандартных библиотек нужно включать в stdafx.h ведь для этого весь сыр-бор и затевается, чтобы их один раз компилятор распарсил, и далее для всех остальных файлов уже использовал приготовленные (прекомпилинные) файлы. Соответственно как раз не изменяемые файлы и надо включать в него, чтобы не вызывать лишний раз пересборки этих precompiled headers. Механизм прекомпиленных заголовков довольно гибкий. Вы можете отключить его полностью, или для отдельных файлов. А также для одной группы файлов использовать один precompiled header, для другой группы другой. Ну и имя stdafx.h хоть и по дефолту, но не фиксированное, можете изменить на любое другое.

Ответ 2



Если я правильно понял ваш вопрос, то я не советую включать заголовочные файлы внутрь заголовка . Во-первых, это делает код менее читабельным, так как сеет сомнение у читающего ваш код, включили ли вы правильно все заголовки, или программа компилируется лишь из-за того, что в некоторой реализации стандартной библиотеки в стандартный заголовок был включен другой стандартный заголовок. Во-вторых, такой код не будет переносим на платформы, где отсутствует заголовок . Если же не включать в него заголовочные файлы, то вам будет достаточно просто его закомментировать или удалить. То есть упрощается работа. И никто не будет спрашивать, а что это за заголовок.

вторник, 24 декабря 2019 г.

Как вернуть мета информацию из HEAD запроса используя Retrofit2?

#android #retrofit #header #request


Для взаимодействия с сервером использую ретрофит. Есть GET запрос который возвращает
огромное кол-во данных. Чтобы каждый раз не съедать трафик клиента нужно проверять
обновились ли данные га сервере. Для этого использую HEAD запрос к тому же эндпоинту.
Проблема в том что HEAD запрос в Call<> можно положить только Void иначе выкидывает
эксепшен. А при таком запросе в колбэк ничего не возвращается, так как у этого запроса
нет респонса. Немного погуглив я нашел способ все же получить нужную мне метаинформацю
из хедеров в Interceptor.

chain.proceed(request).header("etag"))

Но тут меня настигла очередная проблема, как без колбэка передать этот "етаг" туда
откуда был сделан реквест? Должен же быть какой нибудь адекватный/элегантный способ?
    


Ответы

Ответ 1



Retrofit2 корректно возвращает респонс в коллбек при HEAD запросах. Данный код у меня отлично работает: Call c = service.headRequest(url); c.enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { response.headers(); } @Override public void onFailure(Call call, Throwable t) { } }); response не пустой и содержит в себе хедэры response.headers(). Если в вашем случае это не работает, то возможно, что проблема в сервере, который некорректно обрабатывает HEAD запросы.

среда, 18 декабря 2019 г.

Определить какой фон под div на jquery

#javascript #jquery #header #background


Как определить какой фон под нашим фиксированным div (лучше, если это будет на jquery)?

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

Обновление

Пример – www.designbyface.com/ (черная иконка справа вверху). Когда скролим – на
темном фоне должна становиться белой, ведь так ее не видно, нечитабельна. 

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


Ответы

Ответ 1



Прямо под логотипом - вряд-ли, а получить цвета рядом, кажется, можно. Решение: Есть проект html2canvas - с его помощью можно сделать canvas-копию куска страницы. Нас интересует кусок - верхние 100px. Делаем js-ом "скриншот" в canvas. Есть способ получить данные об RGB-представлении куска canvas - getImageData(). Вы знаете отступы логотипа сверху и справа от границы окна, вычленяете эту область. Анализируете цвета в выделенной области выше, ниже, слева, справа от логотипа и сравниваете с цветом посередине логотипа. По результатам сравнения (например, 3 или 4 совпавших с центром контрольных точек) меняете логотип на инвертированную версию. P.S: Определить под логотипом цвет светлее или темнее - можно В теории, можно логотип сделать частично прозрачным, к нему будет примешиваться цвет фона, затем смотреть изменение цвета центрального пикселя - стал он темнее эталона или светлее. Или даже на страницу его добавлять с помощью canvas и drawImage(), что позволит избежать использования библиотеки html2canvas.

Ответ 2



Есть вариант без математики и геометрии. Менять картинку js-кой каждую долю секунды. Только надо довольно маленький период чтобы глазу было незаметно. Либо у картинки сделать кромку. На мой взгляд такие мелочи не должны иметь сложных решений.

Ответ 3



Можете воспользоваться document.elementFromPoint(). Пример: https://preview.c9users.io/dmvw34/logorecalc/logo.html

суббота, 14 декабря 2019 г.

Как вставить одиночный JavaScript в редакторе Wordpress для поста и страницы?

#php #javascript #wordpress #header #hook


Трубуется в Wordpress (у меня версия 3.6) простыми действиями, желательно из редактора
поста, подключить одну функцию JavaScript для одной страницы. 

Просьба, поделитесь опытом.
    


Ответы

Ответ 1



В редакторе поста в текстовом режиме возможна вставка тегов script "как есть". То есть просто вставляете свой код в поле редактирования поста: либо

Ответ 2



В function.php добавляем следующий код: //Настройка определенного css и js с помощью доп. полей. function customscript_shortcode($atts, $text) { global $post; return get_post_meta($post->ID, $text, true); } @add_shortcode('customscript','customscript_shortcode'); //Настройка определенного css и js с помощью доп. полей. Затем в самом посте/странице/кастом_посте в дополнительных полях называем поле например js и в правой части пишем сам скрипт облаченный в . Все! Таким же образом для поста можно и свой css установить. Забыл добавить, что установить его в пост в любом месте можно с помощью короткого кода: [js] или [css] соответственно.

Ответ 3



Если говорить об удобном с точки зрения пользователя, то проще создать дубликат страницы, если у вас страница со скриптом. Если у вас пост, то дубликат контента и добавить в него скрипт(Лучше пере бдеть). Если у вас в команде в основном разработки,то проще добавить произвольное поле.Но однако вас достанет ваш контент-менеджер в последствии. Делаться это следующим образом: ID, 'sample_name', true)); ?> Вставляете ваш скрипт в footer(Для оптимизации) в поле в конкретном посте.

понедельник, 9 декабря 2019 г.

Как компилятор С++ узнает по заголовочному файлу, что нужно подключить .cpp файл?

#cpp #header


есть 2 файла: Element.cpp и Element.h.

в main.cpp я подключаю Element.h. Но как компилятор узнает, когда и куда нужно подключить
файл Element.cpp, в котором хранится реализация? Ведь его я нигде не прописываю.
    


Ответы

Ответ 1



Компилятор и не знает. При компиляции ему указываются какие именно .срр файлы компилировать, например g++ file1.cpp file2.cpp а во всех .cpp файлах нужно указывать необходимые заголовочные файлы. Если вы работаете в IDE, то компилятору будут автоматически передаваться файлы исходного кода те, которые включены в проект.

понедельник, 25 ноября 2019 г.

Для чего нужны Header файлы в С++? Почему нельзя писать без них?


Весь гугл перерыл, не могу понять. И википедию перечитал и вообще все что угодн
перечитал. Правда не понимаю.

Что мешает подключать просто .cpp файлы?

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

Иными словами, почему рутиная работа по генерации хедер файлов, не автоматизирован
и возложена на разработчика? Ведь компилятор рядом с откомпилированным бинарником может легко сам сгенерировать файл описания интерфейсов (который он получил, сканируя cpp файл).

Можете привести ситуацию, в которой бы возникали ПРОБЛЕМЫ без использования хедер файлов? Это будет самое лучшее обьяснение.
    


Ответы

Ответ 1



Проблема лежит в области обратной совместимости. Посмотрите, любой новый язык программирования — да даже Паскаль, не говоря уже Java или C# — не нуждаются в заголовочных файлах. Без сомнения, C++ тоже мог бы обойтись без них. В чём же дело? Перенесёмся на полвека назад, в 1972 год. Представим себе компилятор языка C. Допустим, мы хотим написать дизайн компилятора. Мы не можем скомпилировать всю программ за раз, у нас на это просто не хватит памяти. Компьютеры тогда были маленькими и медленными. Мы хотим компилировать программу по кусочкам, по нескольку функций за раз. У нас сразу же возникает проблема: как скомпилировать функцию f, которая ссылаетс на другую функцию g? Нам нужно отдельное описание других функций. Мы могли бы, конечно прочитать все исходные файлы, для начала выяснить, какие функции у нас есть, и зате прочитать их второй раз и скомпилировать один за одним. Но это было слишком сложно и медленно, нужно было парсить определения функций дважды, и один раз выбрасывать результат! Это недопустимый расход процессорного времени! Плюс если держать в памяти определения всех функций, может снова-таки не хватить памяти. На кого Деннис решил возложить сложную проблему отделения описания функции от е реализации, и подключения только нужных описаний при компиляции данной функции? На нас программистов. Он решил, что мы должны сами помочь компилятору и скопипастить определения функций в отдельный файл, и сами указать компилятору, какие файлы с определениями нужны. (То есть первый шаг компиляции возлагается на нас.) Это радикально упростило компилятор, но привело в свою очередь к проблемам. Что будет если мы забыли подключить нужный заголовочный файл? Ответ: ошибка компиляции. Что будет если смысл текста заголовочного файла меняется в зависимости от какого-нибудь макроса? Ответ: компилятор «тупой», и не пытается детектировать эту проблему, он перекладывает ответственность на нас. На момент разработки языка это было правильное решение. Компилятор оказался практичным быстрым, и программисты были не прочь помочь компиляции. Ну и если кто допускал ошибку, сам был виноват. Перемотаем стрелки часов в 1983 год. Бьярн создаёт C++. Он решил взлететь на волн популярности языка C, и перенял модель компиляции C с отдельными translation unit'ам и связанными с этим проблемами прямо из C. Впрочем, первые версии C++ были просто препроцесооро языка C! Поэтому проблемы раздельной компиляции перекочевали из C в C++. Хуже того, добавились новые проблемы. Например, шаблоны классов выглядят как классы, но не генерируют объектного кода сами по себе, поэтому для них приходится идти на ухищрения и обходить недостатки системы раздельной компиляции (например, включением реализации в header и трюками компоновщика). А дальше вступила в игру обратная совместимость. Сейчас, в 2017 году, есть так мног кода, написанного в стиле «с заголовками», и так много кода исходит из различных тонкостей, связанных с этим, что менять парадигму уже поздно, поезд практически уехал. Впрочем, существует проект модульной системы в C++, который должен помочь программиста избавиться от наследства полувековой давности. Он ещё не реализован, и в нём есть сложност уровня дизайна (например, в header'е был определён макрос, будет ли он виден, если мы перейдём от header'ов к модулям?) Надеюсь, в будущем разработчики языка таки смогут побороть проблему обратной совместимости.

Ответ 2



Сборка программы происходит в три этапа: препроцессор, компилятор и компоновщик. Препроцессор, обрабатывая директиву #include "file", подставит содержимое file текущий файл. Получается, если вы включите cpp файл в несколько компилируемых файлов, то он будет скомпилирован несколько раз. И вот тут вступает в силу Правило одного определения Заодно, почитайте, что такое Единица трансляции. Приведу пример: ClassA.cpp class ClassA { public: void someFunction() {}; } ClassB.cpp #include "ClassA.cpp" class ClassB { } ClassC.cpp #include "ClassA.cpp" class ClassC { } После выполнения препроцессора у вас ClassB.cpp и ClassC.cpp соответственно превратятся в class ClassA { public: void someFunction() {}; } class ClassB { } и class ClassA { public: void someFunction() {}; } class ClassC { } И только теперь начинается компиляция. Даже если вы не будете отдельно компилироват ClassA.cpp, то все равно нарушите правило одного определения (ClassA определен в двух единицах трансляции - ClassB.cpp и ClassC.cpp).

Ответ 3



Так сложилось исторически. Использование автоматически сгенерированных заголовочны файлов требует непростой сборочной системы, которая бы умела определять порядок компиляции при наличии сложных зависимостей между модулями. А поскольку на момент становления языка таких систем еще не придумали - то добавлят генерацию заголовочного файла в компиляторы не стали. И до сих пор такой системы не появилось потому что компиляторы не умеют генерировать заголовочные файлы. Возможно, модули из нового стандарта все изменят. В любом случае, заголовочные файлы останутся для тех случаев, когда импорт .cpp-файл неприменим ни в каком виде. Например, когда .cpp-файла и нет - при подключении сторонне библиотеки. Или при наличии циклической зависимости между модулями. Или просто в ситуации, когда на заголовочный файл налагаются дополнительные требования, делающие его автоматическую генерацию недопустимой.

Ответ 4



Ожидается что в C++17 появится первый стандартизировнный вариант модулей, то ест поддержки сборок без заголовочных файлов. Насколько я понял в этом варианте модули будут реализованы как расширение компилятора, то есть это фнукция будет необязательной в C++17. Однако уже сейчас модули реализованы в Visual Studio 2015 Update 1 и clang, так что их можно попробовать.

Ответ 5



Что мешает подключать просто .cpp файлы? Отсутствие в них информации о типах, доступной извне. Компилятор превращает файлы исходных кодов (.c и .cpp) в объектные файлы (.obj, сшиваемы позднее компоновщиком в единый .exe или .dll файл) — «полуфабрикаты»-«чёрные ящики», импортирующие и экспортирующие символы. Символ, в свою очередь, — это совокупность «имя функции/переменной — её смещени относительно начала объектного файла». Импорт — это зависимости объектного файла (при этом неважно, где они будут реализованы, требуется лишь совпадение имён); экспорт — это то, что в этом файле реализовано. Таким образом, объектные файлы не содержат типов данных и прочих абстракций, существующи исключительно в воображении компилятора. Только машинный код и данные, существующие в виде реально выделяемого места в ОЗУ, и именованные метки. К сожалению, одного только знания имени недостаточно для формирования импорта (зависимости) Компилятору необходимо знать ещё структуру принимающих участие типов для генерации корректных смещений на стеке, вставки дополнительных вызовов конструкторов/деструкторов, выполнения неявных преобразований типов, проверки корректности вызова и т. д. Так как этой информации в объектном файле нет (напомню, там только имена), она должн быть описана в виде объявлений в том файле исходных кодов, который эту внешнюю сущность хочет использовать. Описание можно выполнить либо в самом .cpp файле, либо вынести его в отдельный .hpp файл и подключать его всюду, где требуется описание типа. Почему же описание типов не встраивается в реализующий их объектный файл? Один тот же тип данных может использоваться в произвольном количестве мест, а потому подобно встраивание нарушает правило одного определения. Согласно этому правилу всякая сущность должна иметь только один источник (объектный файл), чтобы у компоновщика не было неопределённости при сопоставлении импортов и экспортов. Ну пусть компилятор только один раз подключает и все, раз он один черт все в оди как бы файл все склеивает, значит первое подключение будет выше остальных и будет видно им внизу. Сборка программы на C и C++ происходит в два этапа. Компилятор превращает каждый файл исходных кодов (.c и .cpp) в объектный файл (.obj) При этом каждый файл исходных кодов компилируется независимо, будто он один во вселенно и никого кроме него больше не существует. На этом этапе компилятор не видит других объектных файлов, но он уже обязан выдать готовый машинный код. Такой подход был выбран разработчиками языка для возможности распараллеливания компиляции. Компоновщик берёт указанные объектные файлы (неважно, как и когда они были получены), связывает их импорты и экспорты и объединяет в единый исполняемый (.exe или .dll) файл. Иными словами почему рутиная работа по генерации хедер файлов, не автоматизированн и возложенна на разработчика? Ведь компилятор рядом с откомпилированным бинарником может легко сам сгенерировать файл описания интерфейсов (который он получил сканируя cpp файл). Вот вам .cpp файл (без включения нестандартных заголовков, как хотели): #include #include Logger::Logger() : _console(std::cout) { } void Logger::log(const std::string& message) { _console << message; } Как компилятор выведет из этого структуру класса Logger? А именно: какие поля должн быть в классе и каков их модификатор доступа? Ведь реализация одного класса может быть распределена по нескольким файлам, ровно как и один файл может содержать реализацию части методов нескольких классов. Вы, наверное, скажете: «описать class Logger{...}; здесь же, чтобы из него генерировался .hpp». А в чём тогда разница, если мы это описание и так выносим в заголовочный файл? Можете привести ситуацию в которой бы возникали ПРОБЛЕМЫ без использования хедер файлов? myclass.cpp #include class Foo { int _value; public: Foo() : _value(rand()) { } // ... ещё много-много методов int bar() const { return _value; } } main.cpp // Копия простыни из foo.cpp #include class Foo { int _value; public: Foo(); // ... ещё много-много методов int bar() const; } int main() { Foo a; std::cout << a.bar(); return 0; } one-more-file.cpp // Ещё раз копия class Foo { int _value; public: Foo(); // ... ещё много-много методов int bar() const; } // ... ну и так далее для каждого файла, использующего Foo. А теперь представьте, что каждое изменение описания класса потребует массовой замен в большом количестве мест. Забудете исправить — компилятор промолчит, будучи введённый в заблуждение, на итоговая программа будет падать.

Ответ 6



Ну подключил ты его два раза, ну пусть компилятор только один раз подключает и все А если я не хочу один раз? Вот предположим, я генерирую за счёт макросов пачку похожих функций, где какие-т минимальные различия в поведении определяются другими макросами. Т. о. вместо генерации кода я меняю значения констант и подключаю один и тот же cpp-файл в другой cpp-файл. А ты хочешь меня этой возможности лишить? Вот пример: http://ideone.com/TlN4r0. Хотя есть лишние усложнения из-за того, чт приходится всё в один файл упихивать (ради ideone), но идея должна быть понятна. А ещё, предполагается, что функция достаточно большая, но различия достаточно маленькие. В таком случае помещение всей функции в макрос становится нерациональным. #ifndef MAIN #define MAIN #include using namespace std; #define D 1 #include __FILE__ #undef D #define D 2 #include __FILE__ #undef D int main() { cout << add1(10) << ' ' << add2(10) << endl; return 0; } #else #define ADD0(d) add##d #define ADD(d) ADD0(d) int ADD(D)(int x) { return x + D; } #undef ADD0 #undef ADD #endif

четверг, 11 июля 2019 г.

Редактирование и настройка почтовых заголовков (mail headers) в Python

Добрый день! Мне необходимо для тестирования системы периодически отправлять и получать специальные письма с различными заголовками. Для реализации этой задачи я использую smtplib и MIMEText с энкодером encode_quopri.
import smtplib from email.mime.text import MIMEText from email.encoders import encode_quopri
SERVER = 'mailserver.loc' FROM = 'sender@' + SERVER TO = 'abonent1@' + SERVER
msg = MIMEText('проверка проверка проверка', 'plain', _charset='windows-1251') msg['Subject'] = 'subject' msg['From'] = FROM msg['To'] = TO msg['X-Message-id'] = 'xmsg_id' encode_quopri(msg)
print (msg)
На выходе получаю:
Content-Type: text/plain; charset="windows-1251" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Subject: subject From: sender@mailserver.loc To: abonent1@mailserver.loc X-Message-id: xmsg_id Content-Transfer-Encoding: quoted-printable
=EF=F0=EE=E2=E5=F0=EA=E0=20=EF=F0=EE=E2=E5=F0=EA=E0=20=EF=F0=EE=E2=E5=F0=EA= =E0
Но у меня задвоился заголовок:
Content-Transfer-Encoding: base64 ... Content-Transfer-Encoding: quoted-printable
Я попробовал удалить первый, но тогда ломается quoted-printable и результат:
7/Du4uXw6uAg7/Du4uXw6uAg7/Du4uXw6uA=3D
Моя цель получить вот такой заголовок:
Date: Wed, 1 Jun 2011 11:25:32 +0400 From: Billinfo X-Priority: 3 (Normal) Message-ID: <878185321.20110601112532> To: abonent1@mailserver.loc Subject: Just a subject Resent-from: Billinfo MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----------115EA32B5A1C2" Resent-Message-Id: <20110601072537.A8F1A3C14A> Resent-Date: Wed, 1 Jun 2011 11:25:37 +0400 (MSD)
------------115EA32B5A1C2 Content-Type: text/plain; charset=windows-1251 Content-Transfer-Encoding: quoted-printable
=EF=F0=EE=E2=E5=F0=EA=E0=20=EF=F0=EE=E2=E5=F0=EA=E0=20=EF=F0=EE=E2=E5=F0=EA= =E0 ------------115EA32B5A1C2 Content-Type: APPLICATION/VND.MS-EXCEL; name="doc.xls" Content-transfer-encoding: base64 Content-Disposition: attachment; filename="doc.xls"
some base64 content ------------115EA32B5A1C2--
Буду благодарен за любую помощь в решении моего вопроса!
UPD 11/04/2015: Моё решение:
from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.charset import Charset from email.encoders import encode_quopri
SERVER = 'mailserver.loc' FROM = 'billing@' + SERVER TO = 'abonent1@' + SERVER
msg = MIMEMultipart('mixed') msg['Subject'] = 'subject' msg['From'] = FROM msg['To'] = TO msg['X-Message-id'] = 'xmsg_id'
charset = Charset('windows-1251')
att1 = MIMEText('проверка111 проверка проверка', 'plain', _charset=None) encode_quopri(att1) att1.set_charset(charset) del att1['Content-Transfer-Encoding'] del att1['MIME-Version'] att1['Content-Transfer-Encoding'] = 'quoted-printable'
msg.attach(att1)
print (msg.as_string())
################### OUTPUT ################### # Content-Type: multipart/mixed; boundary="===============2009055196==" # MIME-Version: 1.0 # Subject: subject # From: billing@mailserver.loc # To: abonent1@mailserver.loc # X-Message-id: xmsg_id
# --===============2009055196== # Content-Type: text/plain; charset="windows-1251" # Content-Transfer-Encoding: quoted-printable
# =D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B0111=20=D0=BF=D1=80=D0=BE=D0= # =B2=D0=B5=D1=80=D0=BA=D0=B0=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0= # =B0 # --===============2009055196==--
Благодарю за помощь! Заголовки нормально воспринимаются принимающей программой и письмо корректно обрабатывается.


Ответ

То, что вы желаете получить — составное письмо. Его составляющие: 1. текст; 2. файл-вложение.
Поэтому при формировании письма следует использовать тип MIMEMultipart, который будет играть роль оболочки для его частей (именно ему следует присваивать заголовки, которые вы присваиваете MIMEText).
Далее к оболочке нужно будет прикрепить (метод attach) объекты типов MIMEText (ваш текст), и MIMEApplication (ваш файл-вложение).

суббота, 25 мая 2019 г.

Редирект на 404 страницу

В .htaccess прописал:
ErrorDocument 404 /views/error.html
В скрипте отправляю заголовок:
header($_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found', true, 404); exit();
Перенаправление не срабатывает. Пробовал и так писать:
header('HTTP/1.1 404 Not Found', true, 404); header('HTTP/1.0 404 Not Found', true, 404); header('HTTP/1.1 404 Not Found'); header('HTTP/1.0 404 Not Found');
Не срабатывает всё равно. Может что-то дописать нужно ещё?


Ответ

ErrorDocument верно срабатывает, когда реально нет страницы. Передача заголовка лично у меня тоже верно сработала, и в целом должна верно срабатывать, если сервер и php верно настроены. Но при этом во втором пункте apache уже не собирается переадресацию какую-то делать, так как он не видит в этом смысла - ErrorDocument срабатывает именно что на реальное отсутствие страницы или отсутствие правил редиректа для запрошенного адреса, когда же страница просто отдает код 404 - это ее дело. Далее подразумевается, что нужно самому вывести нужное.
То есть либо заинклудить целиком страницу, лежащую по пути /views/error.html примерно таким кодом:
if (we_have_404) { header($_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found', true, 404); include "/views/error.html"; exit(); }
дабы минимизировать повторяющийся код на сайте, либо выводить что-либо свое.

среда, 15 мая 2019 г.

Имена файлов с исходным кодом в C/C++

Имеются ли какие-нибудь ограничения для имени source-файла в C/C++? (в Java, например, имя source-файла должно совпадать с именем класса в нем) Должны ли .h/.hpp и .c/.cpp файлы иметь одинаковое имя? Если нет то когда я пишу #include как компилятор узнает где находится реализация header'а?


Ответ

Можете называть, как хотите - даже необязательно с расширением .cpp или подобным, только тогда надо пояснить компилятору, что это - исходный текст, а не что-то иное :)
Заголовочные файлы вообще могут быть какими угодно - так как их имя четко указывается в директиве #include
То, что вы называете "реализацией хедера", обычно находится в библиотеках, которые подключаются компоновщиком. Или, если это ваш код - в одном из ваших .cpp-файлов, например. Или в нескольких :) - как уж вы напишете. Или даже в собранной вами собственной библиотеке.

вторник, 14 мая 2019 г.

Разделение класса в заголовочный файл и в файл с кодом

Вроде всегда так класс разделял в h-хедерные файлы и cpp-файлы с кодом, но в этот раз что-то пошло не так :( Пишет Unresolved external blablabla.obj Main Header CPP Подскажите, пожалуйста, где я в этот раз ошибся?


Ответ

Проблема в шаблонах. Шаблоны надо размещать полностью в header'е. Дело в том, что шаблонный класс не есть класс, и не генерирует вовсе никакого кода. Код будет сгенерирован «задним числом» в момент инстанциации шаблона, то есть, в тот момент, когда вы объявляете шаблон с конкретным параметром! (В вашем случае это main.) Если выгрузить имплементацию шаблона в .cpp, она будет в этой точке компиляции недоступна, и приведёт к ошибке компоновки. Есть, правда, ещё один путь: если вы точно знаете все типы, с которыми будет когда-либо инстанциироваться шаблон, вы можете оставить имплементацию в .cpp, и добавить туда список для явной инстанциации: template class Stack; Но это сработает только лишь если вы контролируете все места, где ваш шаблон будет использован. Если вы пишете библиотеку общего пользования, вы не можете знать наперёд, с какими типами её будут использовать клиенты, то есть этот трюк не пройдёт, и вам таки придётся писать всё в header'е. (Так работает вся STL, например.) Дополнительное чтение по теме: [C++ FAQ/Templates/linker errors]

вторник, 5 марта 2019 г.

RecyclerView - динамичное добавление header

Мне приходит JSON массив с сервера с датой и количеством сообщений. Мне нужно сделать список в котором дата будет находиться перед началом сообщений этой даты. Никак не пойму как можно научить адаптер строить такой список.
Помогите, покажите пальцем, куда копать?
Есть примерный способ реализации:
Завести массив с датами сообщений в формате HH:mm ???


Ответ

Организация данных такая, что нужно распарсить JSON в объекты модели, каждая модель будет содержать поле даты и поле записи. Коллекцию необходимо отсортировать по возрастанию даты.
Для начала нам понадобится два типа разметок. Первая будет отображать дату и запись (layout.header), вторая - только запись (layout.record). Разметка layout.header включает в себя разметку layout.record через include
layout.record:



layout.header:



Логика определения, какой тип View выводить основана на сравнении даты текущей записи и прошлой - если они не равны, то выводить заголовок с датой и записью, иначе только запись. Нулевой элемент обрабатывается отдельно и всегда содержит дату и запись.
Так же прошу обратить внимание на организацию блока switch - case в методе onBindViewHolder(). При выводе View с датой case выводит дату на разметку и "проваливается" на следующий case (нет оператора break), где на разметку выводится запись. Если заголовок не требуется, то на разметку дата не выводится (срабатывает второй case)
class SomeAdapter extends RecyclerView.Adapter {
private ArrayList mData; private final int TYPE_HEADER = 0; private final int TYPE_ITEM = 1;
public SomeAdapter (ArrayList data) { mData = data; }
@Override public ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v;
switch (viewType) {
case TYPE_HEADER: v = LayoutInflater.from(parent.getContext()).inflate(R.layout.header, parent, false); break; default: v = LayoutInflater.from(parent.getContext()).inflate(R.layout.record, parent, false); } return new ItemHolder(v); }
@Override public void onBindViewHolder( ItemHolder holder, int position) {
int type = getItemViewType(position);
switch (type) {
case TYPE_HEADER: holder.mHeaderDate.setText(mData.get(position).getDate()));
case TYPE_ITEM: holder.mItemRecord.setText(mData.get(position).getRecord());
break; } }
@Override public int getItemCount() { return mData.size(); }
@Override public int getItemViewType(int position) {
if (isIdentType(position)) return TYPE_ITEM; return TYPE_HEADER; }
private boolean isIdentType (int position ){
if (!(position == 0)&&(mData.get(position).getDate()).equals(mData.get(position-1).getDate())) return true; return false; }
public static class ItemHolder extends RecyclerView.ViewHolder{
TextView mHeaderDate; TextView mItemRecord;
public ItemHolder(View v) { super(v);
mHeaderDate = (TextView) v.findViewById(R.id.date); mItemRecord = (TextView) v.findViewById(R.id.record); }
}
Естественно, разметки нужно оформить покрасивее как то, выделить дату можно другим фоном или другое. Данный пример - только идея.

понедельник, 28 января 2019 г.

header('Location:') не перенаправляет

Если кратко то есть функция
static function ErrorPage404() { $host = 'http://'.$_SERVER['HTTP_HOST'].'/404'; header('HTTP/1.1 404 Not Found'); header("Status: 404 Not Found"); header('Location:'.$host.''); exit(); }
В нужный момент ее вызываю и на локальном хостинге все работает... Но при переносе срабатывают все заголовки, кроме location ... Подозреваю что дело в настройке сервера (возможно из за SSL, включен 301 редирект с http на https) но не могу докопаться...
Читал подобные проблемы, но решения так и не нашел... Вот что пробовал: Установил значение output_buffering = On,ob_start(),ob_end_flush();
Вот что выдает браузер(название сайта заменил):
Request URL:https://site.ru/avtolombard/asd Request Method:GET Status Code:404 Not Found Response Headers view source Connection:Keep-Alive Content-Encoding:gzip Content-Length:14247 Content-Type:text/html; charset=UTF-8 Date:Sat, 04 Mar 2017 19:36:07 GMT Keep-Alive:timeout=3, max=100 Location:http://site.ru/404 Server:Apache Vary:Accept-Encoding,User-Agent
В действительности оказалось, что не работает Location с заголовком 404... Спасибо @Qwertiy за совет по поводу неудобства для пользователя. По итогу добавил пару условий в маршрутизатор и выдаю контент 404-й станицы с заголовками 404, не меняя URL


Ответ

Есть такое подозрение, что заголовок location работает только с трёхсотой группой кодов. Вроде 404 надо отдавать прям страницей ошибки, а не пытаться туда упихать редирект.
В принципе можно попробовать
Refresh: 3; URL=http://site.ru/404
Но вообще, это плохая идея, портить адрес страницы. Вот перепечатывал пользователь какой-то url, опечатался в одной букве и теперь ему всё вводить заново? Вместо того, чтобы просто исправить?

понедельник, 26 ноября 2018 г.

Как вернуть мета информацию из HEAD запроса используя Retrofit2?

Для взаимодействия с сервером использую ретрофит. Есть GET запрос который возвращает огромное кол-во данных. Чтобы каждый раз не съедать трафик клиента нужно проверять обновились ли данные га сервере. Для этого использую HEAD запрос к тому же эндпоинту. Проблема в том что HEAD запрос в Call<> можно положить только Void иначе выкидывает эксепшен. А при таком запросе в колбэк ничего не возвращается, так как у этого запроса нет респонса. Немного погуглив я нашел способ все же получить нужную мне метаинформацю из хедеров в Interceptor.
chain.proceed(request).header("etag"))
Но тут меня настигла очередная проблема, как без колбэка передать этот "етаг" туда откуда был сделан реквест? Должен же быть какой нибудь адекватный/элегантный способ?


Ответ

Retrofit2 корректно возвращает респонс в коллбек при HEAD запросах. Данный код у меня отлично работает:
Call c = service.headRequest(url);
c.enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { response.headers(); }
@Override public void onFailure(Call call, Throwable t) {
} });
response не пустой и содержит в себе хедэры response.headers(). Если в вашем случае это не работает, то возможно, что проблема в сервере, который некорректно обрабатывает HEAD запросы.