Как в России и США помогают незнакомым людям на улице

Намедни в интернете выложили ролик — как в России и США помогают людям, которым вдруг стало плохо на улице.

Видео, что очевидно любому креаклу, как бы показывало нам, простым ватникам, что в России никто к тебе на улице не подойдет, а в США тебя тут же окружает толпа добропорядочных граждан с вопросом «Чем могу вам помочь?».

Оказалось, что ролик про Россию — это монтаж. Подробности разоблачения можно прочитать в записи «Разоблачаем ! В России никто не поможет ?» юзера ЖЖ masterok.

Если вкратце, то авторы ролика про Россию просто вырезали моменты, когда граждане пытаются помочь. Ну что на это можно сказать…

Ростелеком как всегда жжот

Случайно обнаружил, что робот компании Ростелеком готов с каждым поговорить про долги соседа.

Хотите удивить друзей/знакомых/родственников фразой: «ваша задолженность по телефону составляет 100500 рублей»? Тогда вот вам инструкция:

  1. Набираем номер 8-800-100-0800
  2. Жмём цифру 2 (узнать баланс)
  3. Набираем номер абонента с кодом города
  4. Жмём цифру 1
  5. Все, информация у вас в кармане

Оказывается, мой батя должен 400 рублей, а тёща 22. Непорядок.

Устройство для измерения углов

Приобрел намедни простое в управлении и полезное в быту устройство для измерения углов.
Устройство для измерения углов

Позволяет измерять внутренние углы.
Измерение внутреннего угла

Тут у нас 60 градусов.
Измерение внутреннего угла: результат

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

Через три часа после покупки понял, как измерять внешние углы.
Измерение внешнего угла

Примерно 87.5 градусов.
Измерение внешнего угла: результат

Теперь жизнь заиграла новыми красками, как без него раньше обходился — не понимаю.

У вас есть углы в квартире? Тогда это устройство просто создано для вас.

Магазин фантастики в ДК Крупской

Ден Абнетт, Ольга Громыко, Артём Каменистый, Гарри Гарриссон, Айзек Азимов — если эти имена вам о чём-то говорят, то категорически рекомендую посетить магазин фантастики в ДК Крупской.
Просто зайдите туда и спросите что-нибудь почитать, такого начитанного продавца вы больше нигде не найдете. Создается впечатление, что он читает абсолютно все книги, которые поступают в магазин.

Также в продаже для любителей японских порномультиков есть манга и прочие комиксы.

Группа вконтакте: ДК Крупской 16 павильон фантастика и детективы.

Запись ZIP файла

Запись ZIP файла практически операция чтения наоборот:

  • для каждого файла в архиве необходимо записать LocalFileHeader, затем содержимое файла, предварительно посчитав контрольную сумму
  • для каждой записи LocalFileHeader, записываем CentralDirectoryFileHeader
  • записываем EOCD

Теперь подробнее по пунктам

Запись Local File Header

Для каждого файла в архиве существуют две записи — это LocalFileHeader и CentralDirectoryFileHeader. При записи необходимо создавать эти структуры одновременно, только LocalFileHeader записывать сразу, а для CentralDirectoryFileHeader сохранять информацию во временный список для использования ее потом. Также для данных необходимо посчитать контрольную сумму с помощью функции crc32(), которую предоставляет библиотека zlib.

Пример кода

struct LocalFileHeader
{
    uint16_t versionToExtract;
    uint16_t generalPurposeBitFlag;
    uint16_t compressionMethod;
    uint16_t modificationTime;
    uint16_t modificationDate;
    uint32_t crc32;
    uint32_t compressedSize;
    uint32_t uncompressedSize;
    uint16_t filenameLength;
    uint16_t extraFieldLength;
 
} __attribute__((packed));
 
struct FileInfo
{
    uint32_t compressedSize;
    uint32_t uncompressedSize;
    uint16_t compressionMethod;
    uint32_t crc32;
    uint32_t offset;
};
 
// Буфер для чтения
std::vector<uint8_t> readBuffer;
// Буфер для сжатых данных
std::vector<uint8_t> dataBuffer;
// Информация для создания Central directory file header
std::vector<FileInfo> fileInfoList;
// Список файлов
std::vector<std::string> filenames;
 
for (size_t i = 0; i < filenames.size(); ++i)
{
    const std::string filename = filenames[i];
 
    // Открываем файл для чтения
    std::ifstream f(filename.c_str(), std::ios::binary | std::ios::in);
 
    // Структура типа Local File Header
    LocalFileHeader lfh;
    memset(&lfh, 0, sizeof(lfh));
 
    // Узнаем размер файла
    f.seekg(0, f.end);
    lfh.uncompressedSize = f.tellg();
    f.seekg(0, f.beg);
 
    // Считаем весь файл целиком в readBuffer
    readBuffer.resize(lfh.uncompressedSize);
    f.read((char *) readBuffer.data(), lfh.uncompressedSize);
 
    // Считаем контрольную сумму
    lfh.crc32 = crc32(0, readBuffer.data(), lfh.uncompressedSize);
 
    // Выделим память для сжатых данных
    dataBuffer.resize(lfh.uncompressedSize);
 
    // Структура для сжатия данных
    z_stream zStream;
    memset(&zStream, 0, sizeof(zStream));
    deflateInit2(
        &zStream, 
        Z_BEST_SPEED,
        Z_DEFLATED,
        -MAX_WBITS,
        8,
        Z_DEFAULT_STRATEGY);
 
    // Сжимаем данные
    zStream.avail_in = lfh.uncompressedSize;
    zStream.next_in = readBuffer.data();
    zStream.avail_out = lfh.uncompressedSize;
    zStream.next_out = dataBuffer.data();
    deflate(&zStream, Z_FINISH);
 
    // Размер сжатых данных
    lfh.compressedSize = zStream.total_out;
    lfh.compressionMethod = Z_DEFLATED;
 
    // Очистка
    deflateEnd(&zStream);
 
    // Длина имени файла
    lfh.filenameLength = filename.size();
 
    // Сохраним смещение к записи Local File Header внутри архива
    const uint32_t lfhOffset = os.tellp();
 
    // Запишем сигнатуру Local File Header
    const uint32_t signature = 0x04034b50;
    os.write((char *) &signature, sizeof(signature));
 
    // Запишем Local File Header
    os.write((char *) &lfh, sizeof(lfh));
    // Запишем имя файла
    os.write(filename.c_str(), filename.size());
    // Запишем данные
    os.write((char *) dataBuffer.data(), lfh.compressedSize);
 
    // Сохраним все данные для Central directory file header
    FileInfo fileInfo;
    fileInfo.compressedSize = lfh.compressedSize;
    fileInfo.uncompressedSize = lfh.uncompressedSize;
    fileInfo.compressionMethod = lfh.compressionMethod;
    fileInfo.crc32 = lfh.crc32;
    fileInfo.offset = lfhOffset;
    fileInfoList.push_back(fileInfo);
}

Запись Central directory file header

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

Пример кода

struct CentralDirectoryFileHeader
{
    uint16_t versionMadeBy;
    uint16_t versionToExtract;
    uint16_t generalPurposeBitFlag;
    uint16_t compressionMethod;
    uint16_t modificationTime;
    uint16_t modificationDate;
    uint32_t crc32;
    uint32_t compressedSize;
    uint32_t uncompressedSize;
    uint16_t filenameLength;
    uint16_t extraFieldLength;
    uint16_t fileCommentLength;
    uint16_t diskNumber;
    uint16_t internalFileAttributes;
    uint32_t externalFileAttributes;
    uint32_t localFileHeaderOffset;
 
} __attribute__((packed));
 
// Смещение первой записи для EOCD    
const uint32_t firstOffsetCDFH = os.tellp();
 
for (int i = 0; i < filenames.size(); ++i)
{
    const std::string &filename = filenames[i];
    const FileInfo &fileInfo = fileInfoList[i];
    CentralDirectoryFileHeader cdfh;
    memset(&cdfh, 0, sizeof(cdfh));
 
    cdfh.compressedSize = fileInfo.compressedSize;
    cdfh.uncompressedSize = fileInfo.uncompressedSize;
    cdfh.compressionMethod = fileInfo.compressionMethod;
    cdfh.crc32 = fileInfo.crc32;
    cdfh.localFileHeaderOffset = fileInfo.offset;
    cdfh.filenameLength = filename.size();
 
    // Запишем сигнатуру
    const uint32_t signature = 0x02014b50;
    os.write((char *) &signature, sizeof(signature));
 
    // Запишем структуру
    os.write((char *) &cdfh, sizeof(cdfh));
 
    // Имя файла
    os.write(filename.c_str(), cdfh.filenameLength);
}
 
// Посчитаем размер данных для следующего шага
const uint32_t lastOffsetCDFH = os.tellp();

Запись EOCD

Самый простой этап — сформировать и записать структуру типа EOCD.

Пример кода

EOCD eocd;
memset(&eocd, 0, sizeof(eocd));
eocd.centralDirectoryOffset = firstOffsetCDFH;
eocd.numberCentralDirectoryRecord = filenames.size();
eocd.totalCentralDirectoryRecord = filenames.size();
eocd.sizeOfCentralDirectory = lastOffsetCDFH - firstOffsetCDFH;
 
// Пишем сигнатуру
const uint32_t signature = 0x06054b50;
os.write((char *) &signature, sizeof(signature));
 
// Пишем EOCD
os.write((char *) &eocd, sizeof(eocd));

Замечания по коду:

  • ничего не раскрыто по поводу структуру DataDescriptor (ни разу не сталкивался)
  • иногда размер сжатых данных превышает размер несжатых, поэтому выделяйте память по науке (смотри документацию zlib)
  • если размер данных очень большой, то придется воспользоваться структурой DataDescriptor
Блог Евгения Жирнова