Como obter Mime-Type de arquivos com C++

A forma correta para evitar insegurança de dados!


Como obter Mime-Type de arquivos com C++


MIME (Multipurpose Internet Mail Extensions) type é um padrão utilizado na internet para indicar o tipo de conteúdo de um arquivo.

Originalmente desenvolvido para identificar os tipos de arquivos anexados a e-mails, o MIME type é agora amplamente utilizado em diferentes contextos, como na web, para indicar o tipo de conteúdo de arquivos transmitidos por meio do protocolo HTTP.

Cada tipo de arquivo é associado a um tipo MIME específico, que é representado por uma string. Por exemplo, o tipo MIME para arquivos de texto simples é text/plain, enquanto o tipo MIME para imagens JPEG é image/jpeg. Existem centenas de tipos MIME padrão que cobrem uma variedade de tipos de arquivos, desde documentos de texto até arquivos de áudio e vídeo.

Nesse artigo veremos como identificar o mime-type de um arquivo usando C++ tanto em distribuições GNU+Linux e como dica no Windows.


Identificando mime-type no Linux

Para conseguirmos esse feitos em distribuições GNU+Linux utilizaremos a biblioteca libmagic.

Ela é a biblioteca utilizada pelo comando file, o qual será incluido o cabeçalho magic.h que é vinculada de forma estática(static).

Para instalar você pode usar o gerenciador de pacotes do seu sistema, alguns exemplos abaixo:

sudo apt install libmagic-dev # Debian, Ubuntu, Mint, ...
sudo pacman -S libmagic # Arch
sudo dnf install file-devel # Fedora
brew install libmagic # macOS

Caso você não encontre no repositório do seu sistema, você pode compilar do zero:

Lembre-se antes de possuir as ferramentas de compilação: gcc, make, além do wget para fazermos o download do tarball.

wget ftp://ftp.astron.com/pub/file/file-5.40.tar.gz
tar -xzf file-5.40.tar.gz
cd file-5.40
./configure
make
sudo make install

Veja aqui o caminho onde são instalados os arquivos

Para esse exemplo, vamos ver o mime-type dessa imagem abaixo que é do formato PNG, faça o download clicando com o botão direito do mouse sobre a imagem e clicando em: Salvar como no diretório que estará o binário do código.

imagem: cpp-icon.png, para download

cpp-icon.png

Crie um arquivo main.cpp e cole o código abaixo:

O código está devidamente comentado explicando cada bloco de código para elucidar ações.

// Inclui a libmagic e iostream para escrever na saída padrão
#include <iostream>
#include <magic.h>

int main() {
  // Inicia o cookie
  magic_t magic_cookie;

  // Informa o arquivo que queremos ver o mime-type
  const char *file_path = "cpp-icon.png";

  // Inicializa a libmagic
  magic_cookie = magic_open(MAGIC_MIME_TYPE);
  if (magic_cookie == NULL) {
    std::cerr << "Não foi possível inicializar a libmagic\n";
    return 1;
  }

  // Carrega as definições do banco de dados de mime types
  if (magic_load(magic_cookie, NULL) != 0) {
    std::cerr << "Não foi possível carregar as definições do banco de dados\n";
    magic_close(magic_cookie);
    return 1;
  }

  // Determina o MIME type do arquivo
  const char *mime_type = magic_file(magic_cookie, file_path);
  if (mime_type == NULL) {
    std::cerr << "Não foi possível determinar o MIME type do arquivo\n";
    magic_close(magic_cookie);
    return 1;
  }

  std::cout << "MIME type do arquivo: " << mime_type << "\n";

  // Fecha a libmagic
  magic_close(magic_cookie);

  return 0;
}

Feito isso, é só compilarmos, é necessário passar a flag -lmagic e rodar:

g++ main.cpp -lmagic
./a.out

A possível e provavel saída será:

MIME type do arquivo: image/png

Note que se alterarmos a extensão do arquivo para uma extensão qualquer, mesmo o gerenciador de arquivos exibindo um ícone referente a extensão, a libmagic é segura e correta em relação a isso, mostrará qual o verdadeiro mime-type daquele arquivo.

Isso acontece muito em sistemas que pessoas mal intencinadas querem executar código na Web e a página pede para carregar somente arquivo: jpeg e png, mas alteram só a extensão, mas na verdade o arquivo é um script.

Se eu renomear o arquivo para .mp4, por exemplo:

mv cpp-icon.png cpp-icon.mp4

E alterar no código para carregar o cpp-icon.mp4:

const char *file_path = "cpp-icon.mp4";

Após compilar e rodar, você verá que a libmagic exibirá o Mime-Type CORRETO! E não o da extensão.


Dica para identificar Mime-Type no Windows

No Windows, você pode usar a urlmon.h com o código abaixo:

#include <iostream>
#include <urlmon.h>
#include <windows.h>

#pragma comment(lib, "urlmon.lib")

int main() {
    LPCWSTR file_path = L"caminho_do_arquivo";
    LPWSTR mime_type = NULL;

    HRESULT hr = FindMimeFromData(NULL, file_path, NULL, 0, NULL, 0, &mime_type,
0); if (SUCCEEDED(hr) && mime_type != NULL) { std::wcout << L"MIME type do
arquivo: " << mime_type << std::endl; CoTaskMemFree(mime_type); } else {
        std::cerr << "Não foi possível determinar o MIME type do arquivo\n";
    }

    return 0;
}

Lembrando que para você conseguir compilar, você precisa habilitar a urlmon.dll no Registro do Windows, como descreve nesse link.


Evite “pegadinhas”!

Existem diversas “bibliotecas” C++ no GitHub que faz um FAKE MIME-TYPE, ou seja, se fizermos o procedimento que descrevemos acima de renomear a extensão do arquivo, essas “bibliotecas”, nos informa o incorreto mime-type. Isso é inseguro e perigoso!

Por exemplo, encontrei essa aqui https://github.com/lasselukkari/MimeTypes, se você clonar:

git clone https://github.com/lasselukkari/MimeTypes

Usar esse exemplo após renomear a extensão:

#include <iostream>
#include "MimeTypes/MimeTypes.h"

int main(){
  std::cout << MimeTypes::getType("./cpp-icon.mp4") << '\n';
  return 0;
}

Compile seu arquivo e o MimeTypes.cpp desse repositório:

g++ main.cpp MimeTypes/MimeTypes.cpp 

Após rodar, note que ela informará incorretamente o tipo MIME do arquivo:

video/mp4

Isso não ocorre com a libmagic!


Nem todos os repositórios no GitHub fazem um fake mime-type, mas fiquem atentos para esses casos!


cpp cppdaily


Compartilhe


Nosso canal no Youtube

Inscreva-se


Marcos Oliveira

Marcos Oliveira

Desenvolvedor de software
https://github.com/terroo


Crie Aplicativos Gráficos para Linux e Windows com C++

Aprenda C++ Moderno e crie Games, Programas CLI, GUI e TUI de forma fácil.

Saiba Mais

Receba as novidades no seu e-mail!

Após cadastro e confirmação do e-mail, enviaremos semanalmente resumos e também sempre que houver novidades por aqui para que você mantenha-se atualizado!