Skip to content

Commit 09253e4

Browse files
authored
Merge pull request #1 from bradfier/nogpl-feature
Add with-gpl-data feature for embedding MIME DB
2 parents 0b4d31b + 50153f9 commit 09253e4

16 files changed

+261
-17
lines changed

Cargo.toml

+9-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ repository = "https://github.com/mbrubeck/tree_magic/"
1010
documentation = "https://docs.rs/tree_magic_mini/"
1111
readme = "README.md"
1212
keywords = ["mime", "filesystem", "media-types"]
13-
license = "GPL-2.0-or-later"
13+
license = "MIT"
1414
exclude = ["tests/*", "benches/*/"]
1515
edition = "2018"
1616

@@ -19,6 +19,11 @@ petgraph = "^0.5"
1919
nom = "6.0"
2020
lazy_static = "^1.4"
2121
fnv = "^1"
22+
once_cell = "^1"
23+
tree_magic_db = { path = "./magic_db" , optional = true }
24+
25+
[features]
26+
with-gpl-data = ["tree_magic_db"]
2227

2328
[dev-dependencies]
2429
bencher = "^0.1"
@@ -27,6 +32,9 @@ bencher = "^0.1"
2732
crate-type = ["lib"]
2833
path = "src/lib.rs"
2934

35+
[workspace]
36+
members = ["magic_db"]
37+
3038
[[bench]]
3139
name = "from_u8"
3240
harness = false

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2017 Aaron Hancock
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+14
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,20 @@ simplify the effort to maintain and optimize of this fork. I would like to
1919
eventually merge these changes back to the original `tree_magic` crate, and/or
2020
restore some of the removed features if there is demand for that.
2121

22+
## Licensing and the MIME database
23+
24+
By default, `tree_magic_mini` will attempt to load the shared MIME info
25+
database from the standard locations at runtime.
26+
27+
If you won't have the database files available, or would like to include them
28+
in your binary for simplicity, you can optionally embed the database
29+
information if you enable the `tree_magic_db` feature.
30+
31+
**As the magic database files themselves are licensed under the GPL, you must
32+
make sure your project uses a compatible license if you enable this behaviour.**
33+
34+
---
35+
2236
Continue reading for the original `tree_magic` documentation.
2337

2438
## About tree_magic

COPYING magic_db/COPYING

File renamed without changes.

magic_db/Cargo.toml

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "tree_magic_db"
3+
version = "1.0.0"
4+
authors = ["Richard Bradfield <bradfier@fstab.me>"]
5+
description = "Packages the FreeDesktop.org shared MIME database for optional use with tree_magic_mini"
6+
license = "GPL-2.0-or-later"
7+
edition = "2018"

magic_db/README.md

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Magic DB
2+
3+
This subcrate contains the magic definitions copied from the FreeDesktop.org
4+
shared MIME info database.
5+
6+
These files are distributed under the GPL-2.0 or later, as such if you include
7+
them in your project, it must be licensed in a compatible manner.
8+
9+
# References
10+
11+
- [xdg-shared-mime-info Repository](https://github.com/freedesktop/xdg-shared-mime-info)
12+
- [FreeDesktop shared-mime-info Spec](https://www.freedesktop.org/wiki/Specifications/shared-mime-info-spec/)
13+
14+
# Licence
15+
16+
The contents of this crate are licenced under the GNU General Public License,
17+
version 2.0 or later, at your option:
18+
19+
* GNU GPL, Version 2.0 ([COPYING](COPYING) or https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt)
File renamed without changes.

magic_db/src/lib.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//! Packaging crate for the FreeDesktop.org shared MIME info database
2+
3+
// This program is free software; you can redistribute it and/or
4+
// modify it under the terms of the GNU General Public License
5+
// as published by the Free Software Foundation; either version 2
6+
// of the License, or (at your option) any later version.
7+
//
8+
// This program is distributed in the hope that it will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
// GNU General Public License for more details.
12+
13+
/// Returns a static reference to the MIME database 'aliases'
14+
pub fn aliases() -> &'static str {
15+
include_str!("aliases")
16+
}
17+
18+
/// Returns a static reference to the MIME database 'subclasses'
19+
pub fn subclasses() -> &'static str {
20+
include_str!("subclasses")
21+
}
22+
23+
/// Returns a static reference to the MIME database 'magic' data
24+
pub fn magic() -> &'static [u8] {
25+
include_bytes!("magic")
26+
}
File renamed without changes.
File renamed without changes.

src/fdo_magic/builtin/init.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,25 @@
11
use crate::MIME;
22
use fnv::FnvHashMap;
33

4+
#[cfg(not(feature = "with-gpl-data"))]
5+
use super::runtime;
6+
7+
fn aliases() -> &'static str {
8+
#[cfg(feature = "with-gpl-data")]
9+
return tree_magic_db::aliases();
10+
#[cfg(not(feature = "with-gpl-data"))]
11+
return runtime::aliases();
12+
}
13+
14+
fn subclasses() -> &'static str {
15+
#[cfg(feature = "with-gpl-data")]
16+
return tree_magic_db::subclasses();
17+
#[cfg(not(feature = "with-gpl-data"))]
18+
return runtime::subclasses();
19+
}
20+
421
pub fn get_aliaslist() -> FnvHashMap<MIME, MIME> {
5-
include_str!("aliases")
22+
aliases()
623
.lines()
724
.map(|line| {
825
let mut parts = line.split_whitespace();
@@ -20,7 +37,7 @@ pub fn get_supported() -> Vec<MIME> {
2037

2138
/// Get list of parent -> child subclass links
2239
pub fn get_subclasses() -> Vec<(MIME, MIME)> {
23-
include_str!("subclasses")
40+
subclasses()
2441
.lines()
2542
.map(|line| {
2643
let mut parts = line.split_whitespace();

src/fdo_magic/builtin/mod.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,28 @@ lazy_static! {
1313

1414
/// Load magic file before anything else.
1515
lazy_static! {
16-
static ref ALLRULES: FnvHashMap<MIME, DiGraph<MagicRule<'static>, u32>> =
17-
super::ruleset::from_u8(include_bytes!("magic")).unwrap_or(FnvHashMap::default());
16+
static ref ALLRULES: FnvHashMap<MIME, DiGraph<MagicRule<'static>, u32>> = rules();
1817
}
1918

2019
pub mod check;
2120
pub mod init;
21+
22+
#[cfg(not(feature = "with-gpl-data"))]
23+
mod runtime;
24+
25+
fn rules() -> FnvHashMap<MIME, DiGraph<MagicRule<'static>, u32>> {
26+
#[cfg(feature = "with-gpl-data")]
27+
return static_rules();
28+
#[cfg(not(feature = "with-gpl-data"))]
29+
return runtime_rules();
30+
}
31+
32+
#[cfg(feature = "with-gpl-data")]
33+
fn static_rules() -> FnvHashMap<MIME, DiGraph<MagicRule<'static>, u32>> {
34+
super::ruleset::from_u8(tree_magic_db::magic()).unwrap_or(FnvHashMap::default())
35+
}
36+
37+
#[cfg(not(feature = "with-gpl-data"))]
38+
fn runtime_rules() -> FnvHashMap<MIME, DiGraph<MagicRule<'static>, u32>> {
39+
runtime::rules().unwrap_or(FnvHashMap::default())
40+
}

src/fdo_magic/builtin/runtime.rs

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
///! Enable loading the magic database files at runtime rather than embedding the GPLed database
2+
use std::fs::File;
3+
use std::io::Read;
4+
5+
use fnv::FnvHashMap;
6+
use once_cell::sync::OnceCell;
7+
use petgraph::prelude::DiGraph;
8+
9+
use super::MagicRule;
10+
use crate::fdo_magic::ruleset;
11+
use crate::MIME;
12+
13+
static RUNTIME_RULES: OnceCell<Vec<Vec<u8>>> = OnceCell::new();
14+
static ALIAS_STRING: OnceCell<String> = OnceCell::new();
15+
static SUBCLASS_STRING: OnceCell<String> = OnceCell::new();
16+
17+
/// Load the magic database from the predefined locations in the XDG standard
18+
fn load_xdg_shared_magic() -> Vec<Vec<u8>> {
19+
const SEARCH_PATHS: &[&str; 3] = &[
20+
"/usr/share/mime/magic",
21+
"/usr/local/share/mime/magic",
22+
"$HOME/.local/share/mime/magic",
23+
];
24+
25+
let files: Vec<Vec<u8>> = SEARCH_PATHS
26+
.iter()
27+
.map(|p| File::open(p).ok())
28+
.filter_map(|f| f)
29+
.map(|mut f| {
30+
let mut buf = vec![];
31+
f.read_to_end(&mut buf)
32+
.expect("Failed to read magic file bytes");
33+
buf
34+
})
35+
.collect();
36+
37+
if files.is_empty() {
38+
panic!("No MIME magic files found in the XDG default paths");
39+
}
40+
41+
files
42+
}
43+
44+
/// Load a number of files at `paths` and concatenate them together with a newline
45+
fn load_concat_strings(paths: &[&str]) -> String {
46+
let strings: Vec<String> = paths
47+
.iter()
48+
.map(|p| File::open(p).ok())
49+
.filter_map(|f| f)
50+
.map(|mut f| {
51+
let mut s = String::new();
52+
f.read_to_string(&mut s)
53+
.expect("Failed to read aliases from file");
54+
s
55+
})
56+
.collect();
57+
58+
strings.join("\n")
59+
}
60+
61+
/// Load the magic aliases from the XDG standard locations and concatenate them together
62+
fn load_aliases() -> String {
63+
const SEARCH_PATHS: &[&str; 3] = &[
64+
"/usr/share/mime/aliases",
65+
"/usr/local/share/mime/aliases",
66+
"$HOME/.local/share/mime/aliases",
67+
];
68+
69+
load_concat_strings(SEARCH_PATHS)
70+
}
71+
72+
/// Load the subclass definitions from the XDG standard locations and concatenate them together
73+
fn load_subclasses() -> String {
74+
const SEARCH_PATHS: &[&str; 3] = &[
75+
"/usr/share/mime/subclasses",
76+
"/usr/local/share/mime/subclasses",
77+
"$HOME/.local/share/mime/subclasses",
78+
];
79+
80+
load_concat_strings(SEARCH_PATHS)
81+
}
82+
83+
pub(crate) fn aliases() -> &'static str {
84+
ALIAS_STRING.get_or_init(load_aliases)
85+
}
86+
87+
pub(crate) fn subclasses() -> &'static str {
88+
SUBCLASS_STRING.get_or_init(load_subclasses)
89+
}
90+
91+
pub(crate) fn rules() -> Result<FnvHashMap<MIME, DiGraph<MagicRule<'static>, u32>>, String> {
92+
let files = RUNTIME_RULES.get_or_init(load_xdg_shared_magic);
93+
Ok(ruleset::from_multiple(files).unwrap())
94+
}

src/fdo_magic/ruleset.rs

+17
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ fn gen_graph(magic_rules: Vec<MagicRule<'_>>) -> DiGraph<MagicRule<'_>, u32> {
9999
graph
100100
}
101101

102+
#[cfg(feature = "with-gpl-data")]
102103
pub fn from_u8(b: &[u8]) -> Result<FnvHashMap<&str, DiGraph<MagicRule<'_>, u32>>, String> {
103104
let tuplevec = ruleset(b).map_err(|e| e.to_string())?.1;
104105
let res = tuplevec
@@ -107,3 +108,19 @@ pub fn from_u8(b: &[u8]) -> Result<FnvHashMap<&str, DiGraph<MagicRule<'_>, u32>>
107108
.collect();
108109
Ok(res)
109110
}
111+
112+
#[cfg(not(feature = "with-gpl-data"))]
113+
/// Parse multiple ruleset magic files and aggregate the tuples into a single graph
114+
pub fn from_multiple<'a>(
115+
files: &'a [Vec<u8>],
116+
) -> Result<FnvHashMap<&'a str, DiGraph<MagicRule<'a>, u32>>, String> {
117+
let mut tuplevec = vec![];
118+
for slice in files {
119+
tuplevec.append(&mut ruleset(slice.as_ref()).map_err(|e| e.to_string())?.1);
120+
}
121+
let res = tuplevec
122+
.into_iter()
123+
.map(|x| (x.0, gen_graph(x.1)))
124+
.collect();
125+
Ok(res)
126+
}

src/lib.rs

+13-11
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//!
33
//! This is a fork of the [tree_magic](https://crates.io/crates/tree_magic)
44
//! crate by Allison Hancock. It includes the following changes:
5-
//!
5+
//!
66
//! * Updated dependencies.
77
//! * Reduced copying and memory allocation, for a slight increase in speed and
88
//! decrease in memory use.
@@ -27,6 +27,18 @@
2727
//! - Can delegate different file types to different "checkers", reducing false positives
2828
//! by choosing a different method of attack.
2929
//!
30+
//! ## Licensing and the MIME database
31+
//!
32+
//! By default, `tree_magic_mini` will attempt to load the shared MIME info
33+
//! database from the standard locations at runtime.
34+
//!
35+
//! If you won't have the database files available, or would like to include them
36+
//! in your binary for simplicity, you can optionally embed the database
37+
//! information if you enable the `tree_magic_db` feature.
38+
//!
39+
//! **As the magic database files themselves are licensed under the GPL, you must
40+
//! make sure your project uses a compatible license if you enable this behaviour.**
41+
//!
3042
//! # Example
3143
//! ```rust
3244
//! // Load a GIF file
@@ -41,16 +53,6 @@
4153
//! assert_eq!(result, true);
4254
//! ```
4355
44-
// This program is free software; you can redistribute it and/or
45-
// modify it under the terms of the GNU General Public License
46-
// as published by the Free Software Foundation; either version 2
47-
// of the License, or (at your option) any later version.
48-
//
49-
// This program is distributed in the hope that it will be useful,
50-
// but WITHOUT ANY WARRANTY; without even the implied warranty of
51-
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52-
// GNU General Public License for more details.
53-
5456
#![allow(unused_doc_comments)]
5557

5658
use fnv::FnvHashMap;

tests/from_filepath.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
mod from_filepath {
2-
use tree_magic_mini as tree_magic;
32
use std::path::Path;
3+
use tree_magic_mini as tree_magic;
44

55
#[test]
66
fn nonexistent_file_returns_none() {

0 commit comments

Comments
 (0)