Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
|
b7e091ce77 | 9 months ago |
|
1d3009d723 | 9 months ago |
@ -1,24 +0,0 @@
|
||||
---
|
||||
# Indentation for all files
|
||||
ColumnLimit: 120
|
||||
|
||||
# C++ Options
|
||||
Language: Cpp
|
||||
BasedOnStyle: Google
|
||||
|
||||
# Force pointers to the type for C++.
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Left
|
||||
|
||||
# Useful for sorting the project inclusions and standard library inclusions separately
|
||||
IncludeBlocks: Preserve
|
||||
|
||||
# Constructor initializers better formatted in presence of preprocessor conditions (see image.cpp)
|
||||
BreakConstructorInitializers: AfterColon
|
||||
|
||||
# Do not allow SingleLine statements (to improve coverage statistics)
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
|
||||
...
|
@ -0,0 +1,28 @@
|
||||
---
|
||||
BasedOnStyle: Google
|
||||
Language: Cpp
|
||||
Standard: Cpp03
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
ColumnLimit: 120
|
||||
NamespaceIndentation: All
|
||||
|
||||
AccessModifierOffset: -4
|
||||
ContinuationIndentWidth: 4
|
||||
IndentWidth: 4
|
||||
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterStruct: true
|
||||
AfterClass: true
|
||||
AfterFunction: true
|
||||
AfterControlStatement: false
|
||||
AfterEnum: true
|
||||
AfterNamespace: true
|
||||
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
|
||||
...
|
@ -1,17 +0,0 @@
|
||||
with section("format"):
|
||||
|
||||
# How wide to allow formatted cmake files
|
||||
line_width = 150
|
||||
|
||||
# How many spaces to tab for indent
|
||||
tab_size = 2
|
||||
|
||||
# If true, separate flow control names from their parentheses with a space
|
||||
separate_ctrl_name_with_space = False
|
||||
|
||||
# If true, separate function names from parentheses with a space
|
||||
separate_fn_name_with_space = False
|
||||
|
||||
# If a statement is wrapped to more than one line, than dangle the closing
|
||||
# parenthesis on its own line.
|
||||
dangle_parens = True
|
@ -1,6 +0,0 @@
|
||||
[*]
|
||||
charset = utf-8
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace=true
|
@ -1,4 +0,0 @@
|
||||
# ignore global clang-format
|
||||
30bf563f4d71ff284b5f42d45f77226200a2e571
|
||||
# fic formatting followup from #2158
|
||||
a3cb054746beed514679592ffec9378acc9e5d41
|
@ -1,29 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
#### **Describe the bug**
|
||||
A clear and concise description of the bug, including your use case for exiv2.
|
||||
|
||||
#### **To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Provide the file with which you observed the issue (commonly named PoC). Explain the status of the file (e.g., direct from camera, edited with darktable), whether you own the copyright and if you allow the file to be added to exiv2 under the [project's license](https://github.com/Exiv2/exiv2/blob/main/COPYING)
|
||||
2. List the exact commands/functions to reproduce the issue and include any related output
|
||||
3. Mention the branch and commit in which you observed the issue (e.g., `main, commit 9f721b40`, `0.27-maintenance, latest`)
|
||||
|
||||
#### **Expected behavior**
|
||||
A short description of what you expected to happen.
|
||||
|
||||
#### **Desktop (please complete the following information):**
|
||||
- OS and version: (e.g., Linux (Fedora 36), macOS 12.5, Windows 11)
|
||||
- Exiv2 version and source: (e.g., 0.27.5 from exiv2.org)
|
||||
- Compiler and version: (e.g., Gcc 12.2, Clang 14.0.0, MSVC 2022)
|
||||
- Compilation mode and/or compiler flags: (e.g., debug, `-O3`)
|
||||
|
||||
#### **Additional context**
|
||||
Add any other information about the problem here.
|
@ -1,25 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: request
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
#### **Is your feature request related to a problem?**
|
||||
A clear and concise description of the problem, including your use case for exiv2 and any impact on your workflow.
|
||||
|
||||
#### **Describe the solution you would like**
|
||||
A short description of what you want to happen.
|
||||
|
||||
#### **Describe alternatives you have considered**
|
||||
A simple explanation of any alternative solutions (e.g., using ExifTool) or features you have considered (e.g., convert the file to JPEG).
|
||||
|
||||
#### **Desktop**
|
||||
- OS and version: (e.g., Linux (Fedora 36), macOS 12.5, Windows 11)
|
||||
- Exiv2 version and source: (e.g., 0.27.5 from exiv2.org)
|
||||
- Any software using exiv2 and source: (e.g., darktable 4.0 from darktable.org)
|
||||
|
||||
#### **Additional context**
|
||||
Add any other information about the feature request here (e.g. screenshots, URLs, test files).
|
@ -1,3 +0,0 @@
|
||||
# Reusing existing QL Pack
|
||||
- import: codeql-suites/cpp-code-scanning.qls
|
||||
from: codeql-cpp
|
@ -1,23 +0,0 @@
|
||||
<!DOCTYPE qhelp SYSTEM "qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
A C++ iterator is a lot like a C pointer: if you dereference it without
|
||||
first checking that it's valid then it can cause a crash.
|
||||
</p>
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>
|
||||
Always check that the iterator is valid before derefencing it.
|
||||
</p>
|
||||
</recommendation>
|
||||
<example>
|
||||
<p>
|
||||
<a href="https://github.com/Exiv2/exiv2/issues/1763">Issue 1763</a> was caused by
|
||||
<a href="https://github.com/Exiv2/exiv2/blob/9b3ed3f9564b4ea51b43c78671435bde6b862e08/src/canonmn_int.cpp#L2755">this
|
||||
dereference</a> of the iterator <tt>pos</tt>.
|
||||
The bug was <a href="https://github.com/Exiv2/exiv2/pull/1767">fixed</a> by not dereferencing
|
||||
<tt>pos</tt> if <tt>pos == metadata->end()</tt>.
|
||||
</p>
|
||||
</example>
|
||||
</qhelp>
|
@ -1,47 +0,0 @@
|
||||
/**
|
||||
* @name NULL iterator deref
|
||||
* @description Dereferencing an iterator without checking that it's valid could cause a crash.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @id cpp/null-iterator-deref
|
||||
* @tags security
|
||||
* external/cwe/cwe-476
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
import semmle.code.cpp.dataflow.DataFlow
|
||||
|
||||
// Holds if `cond` is a condition like `use == table.end()`.
|
||||
// `eq_is_true` is `true` for `==`, `false` for '!=`.
|
||||
// Note: the `==` is actually an overloaded `operator==`.
|
||||
predicate end_condition(GuardCondition cond, Expr use, FunctionCall endCall, boolean eq_is_true) {
|
||||
exists(FunctionCall eq |
|
||||
exists(string opName | eq.getTarget().getName() = opName |
|
||||
opName = "operator==" and eq_is_true = true
|
||||
or
|
||||
opName = "operator!=" and eq_is_true = false
|
||||
) and
|
||||
DataFlow::localExprFlow(use, eq.getAnArgument()) and
|
||||
DataFlow::localExprFlow(endCall, eq.getAnArgument()) and
|
||||
endCall.getTarget().getName() = "end" and
|
||||
DataFlow::localExprFlow(eq, cond)
|
||||
)
|
||||
}
|
||||
|
||||
from FunctionCall call, Expr use
|
||||
where
|
||||
call.getTarget().getName() = "findKey" and
|
||||
DataFlow::localExprFlow(call, use) and
|
||||
use != call and
|
||||
not use.(AssignExpr).getRValue() = call and
|
||||
not end_condition(_, use, _, _) and
|
||||
not exists(
|
||||
Expr cond_use, FunctionCall endCall, GuardCondition cond, BasicBlock block, boolean branch
|
||||
|
|
||||
end_condition(cond, cond_use, endCall, branch) and
|
||||
DataFlow::localExprFlow(call, cond_use) and
|
||||
cond.controls(block, branch.booleanNot()) and
|
||||
block.contains(use)
|
||||
)
|
||||
select call, "Iterator returned by findKey might cause a null deref $@.", use, "here"
|
@ -1,65 +0,0 @@
|
||||
/**
|
||||
* @name Null metadata in print function
|
||||
* @description Print functions need to check that the metadata isn't null before calling methods on it.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @id cpp/null-metadata-in-print
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
import semmle.code.cpp.controlflow.Nullness
|
||||
import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
|
||||
|
||||
// Find all the print functions by looking for TagInfo initializers
|
||||
// like this one:
|
||||
// https://github.com/Exiv2/exiv2/blob/6b186a4cd276ac11b3ea69951c2112f4c4814b9a/src/canonmn_int.cpp#L660-L679
|
||||
class PrintFunction extends Function {
|
||||
PrintFunction() {
|
||||
exists(Initializer i, Field f |
|
||||
i.getExpr().(ArrayAggregateLiteral).getAChild().(ClassAggregateLiteral).getAFieldExpr(f) =
|
||||
this.getAnAccess() and
|
||||
f.getName() = "printFct_"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
predicate metadataDeref(Expr metadata) {
|
||||
exists(Call call | call.getQualifier() = metadata)
|
||||
or
|
||||
exists(FunctionCall call, int argIndex, Function f |
|
||||
call.getArgument(argIndex) = metadata and
|
||||
f = call.getTarget() and
|
||||
metadataDeref(f.getParameter(argIndex).getAnAccess())
|
||||
)
|
||||
}
|
||||
|
||||
predicate unsafePointerParam(Function f, int paramIndex, Expr use) {
|
||||
exists(Parameter p |
|
||||
p = f.getParameter(paramIndex) and
|
||||
use = p.getAnAccess() and
|
||||
unsafePointerExpr(use) and
|
||||
not exists(GuardCondition nonNullCheck, BasicBlock block, boolean branch |
|
||||
validCheckExpr(nonNullCheck, p) and
|
||||
nonNullCheck.controls(block, branch) and
|
||||
block.contains(use)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
predicate unsafePointerExpr(Expr e) {
|
||||
exists(Call call |
|
||||
call.getQualifier() = e and
|
||||
e.getType().getUnspecifiedType() instanceof PointerType
|
||||
)
|
||||
or
|
||||
exists(FunctionCall call, int argIndex, Function f |
|
||||
call.getArgument(argIndex) = e and
|
||||
f = call.getTarget() and
|
||||
unsafePointerParam(f, argIndex, _)
|
||||
)
|
||||
}
|
||||
|
||||
from PrintFunction printfcn, Parameter p, Expr metadata
|
||||
where unsafePointerParam(printfcn, 2, metadata)
|
||||
select metadata, "Print functions need to check that the metadata isn't null."
|
@ -1,4 +0,0 @@
|
||||
name: exiv2-cpp-queries
|
||||
version: 0.0.0
|
||||
libraryPathDependencies: codeql-cpp
|
||||
suites: exiv2-cpp-suite
|
@ -1,24 +0,0 @@
|
||||
/**
|
||||
* @name Signed shift
|
||||
* @description Shifting a negative number is undefined behavior,
|
||||
* so it is risky to shift a signed number.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @id cpp/signed-shift
|
||||
* @tags security
|
||||
* external/cwe/cwe-758
|
||||
*/
|
||||
|
||||
// See the "Bitwise shift operators" section here:
|
||||
// https://en.cppreference.com/w/cpp/language/operator_arithmetic
|
||||
import cpp
|
||||
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
|
||||
|
||||
from BinaryBitwiseOperation shift, Expr lhs
|
||||
where
|
||||
(shift instanceof LShiftExpr or shift instanceof RShiftExpr) and
|
||||
lhs = shift.getLeftOperand().getFullyConverted() and
|
||||
lowerBound(lhs) < 0
|
||||
select shift,
|
||||
"This signed shift could cause undefined behavior if the value is negative. Type of lhs: " +
|
||||
lhs.getType().toString()
|
@ -1,30 +0,0 @@
|
||||
<!DOCTYPE qhelp SYSTEM "qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
The <a href="https://en.cppreference.com/w/cpp/container/vector/operator_at"><tt>operator[]</tt></a> method of <a href="https://en.cppreference.com/w/cpp/container/vector"><tt>std::vector</tt></a> does not do any bounds checking on the index. It is safer to use the <a href="https://en.cppreference.com/w/cpp/container/vector/at"><tt>at()</tt></a> method, which does do bounds checking.
|
||||
</p>
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>
|
||||
Use the <a href="https://en.cppreference.com/w/cpp/container/vector/at"><tt>at()</tt></a> method, rather than <a href="https://en.cppreference.com/w/cpp/container/vector/operator_at"><tt>operator[]</tt></a>.
|
||||
</p>
|
||||
<p>
|
||||
Some uses of <a href="https://en.cppreference.com/w/cpp/container/vector/operator_at"><tt>operator[]</tt></a> are safe because they are protected by a bounds check. The query recognises the following safe coding patterns:
|
||||
</p>
|
||||
<ul>
|
||||
<li><tt>if (!x.empty()) { ...x[0]... }</tt></li>
|
||||
<li><tt>if (x.length()) { ...x[0]... }</tt></li>
|
||||
<li><tt>if (x.size() > 2) { ...x[2]... }</tt></li>
|
||||
<li><tt>if (x.size() == 2) { ...x[1]... }</tt></li>
|
||||
<li><tt>if (x.size() != 0) { ...x[0]... }</tt></li>
|
||||
<li><tt>if (i < x.size()) { ... x[i] ... }</tt></li>
|
||||
<li><tt>if (!x.empty()) { ... x[x.size() - 1] ... }</tt></li>
|
||||
</ul>
|
||||
</recommendation>
|
||||
<example>
|
||||
<p>
|
||||
<a href="https://github.com/Exiv2/exiv2/issues/1706">#1706</a> was caused by a lack of bounds-checking on <a href="https://github.com/Exiv2/exiv2/blob/15098f4ef50cc721ad0018218acab2ff06e60beb/include/exiv2/value.hpp#L1639">this array access</a>. The bug was <a href="https://github.com/Exiv2/exiv2/pull/1735">fixed</a> calling the <a href="https://en.cppreference.com/w/cpp/container/vector/at"><tt>at()</tt></a> method instead.
|
||||
</p>
|
||||
</example>
|
||||
</qhelp>
|
@ -1,181 +0,0 @@
|
||||
/**
|
||||
* @name Unsafe vector access
|
||||
* @description std::vector::operator[] does not do any runtime
|
||||
* bounds-checking, so it is safer to use std::vector::at()
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @id cpp/unsafe-vector-access
|
||||
* @tags security
|
||||
* external/cwe/cwe-125
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
import semmle.code.cpp.dataflow.DataFlow
|
||||
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
|
||||
import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
import semmle.code.cpp.valuenumbering.HashCons
|
||||
|
||||
// A call to `operator[]`.
|
||||
class ArrayIndexCall extends FunctionCall {
|
||||
ClassTemplateInstantiation ti;
|
||||
TemplateClass tc;
|
||||
|
||||
ArrayIndexCall() {
|
||||
this.getTarget().getName() = "operator[]" and
|
||||
ti = this.getQualifier().getType().getUnspecifiedType() and
|
||||
tc = ti.getTemplate() and
|
||||
tc.getSimpleName() != "map" and
|
||||
tc.getSimpleName() != "match_results"
|
||||
}
|
||||
|
||||
ClassTemplateInstantiation getClassTemplateInstantiation() { result = ti }
|
||||
|
||||
TemplateClass getTemplateClass() { result = tc }
|
||||
}
|
||||
|
||||
// A call to `size` or `length`.
|
||||
class SizeCall extends FunctionCall {
|
||||
string fname;
|
||||
|
||||
SizeCall() {
|
||||
fname = this.getTarget().getName() and
|
||||
(fname = "size" or fname = "length")
|
||||
}
|
||||
}
|
||||
|
||||
// `x[i]` is safe if `x` is a `std::array` (fixed-size array)
|
||||
// and `i` within the bounds of the array.
|
||||
predicate indexK_with_fixedarray(ClassTemplateInstantiation t, ArrayIndexCall call) {
|
||||
t = call.getClassTemplateInstantiation() and
|
||||
exists(Expr idx |
|
||||
t.getSimpleName() = "array" and
|
||||
idx = call.getArgument(0) and
|
||||
lowerBound(idx) >= 0 and
|
||||
upperBound(idx) < lowerBound(t.getTemplateArgument(1))
|
||||
)
|
||||
}
|
||||
|
||||
// Holds if `cond` is a Boolean condition that checks the size of
|
||||
// the array. It handles the following code patterns:
|
||||
//
|
||||
// 1. `if (!x.empty()) { ... }`
|
||||
// 2. `if (x.length()) { ... }`
|
||||
// 3. `if (x.size() > 2) { ... }`
|
||||
// 4. `if (x.size() == 2) { ... }`
|
||||
// 5. `if (x.size() != 0) { ... }`
|
||||
//
|
||||
// If it safe to assume that `x.size() >= minsize` on the exit `branch`.
|
||||
predicate minimum_size_cond(Expr cond, Expr arrayExpr, int minsize, boolean branch) {
|
||||
// `if (!x.empty()) { ...x[0]... }`
|
||||
exists(FunctionCall emptyCall |
|
||||
cond = emptyCall and
|
||||
arrayExpr = emptyCall.getQualifier() and
|
||||
emptyCall.getTarget().getName() = "empty" and
|
||||
minsize = 1 and
|
||||
branch = false
|
||||
)
|
||||
or
|
||||
// `if (x.length()) { ...x[0]... }`
|
||||
exists(SizeCall sizeCall |
|
||||
cond = sizeCall and
|
||||
arrayExpr = sizeCall.getQualifier() and
|
||||
minsize = 1 and
|
||||
branch = true
|
||||
)
|
||||
or
|
||||
// `if (x.size() > 2) { ...x[2]... }`
|
||||
exists(SizeCall sizeCall, Expr k, RelationStrictness strict |
|
||||
arrayExpr = sizeCall.getQualifier() and
|
||||
relOpWithSwapAndNegate(cond, sizeCall, k, Greater(), strict, branch)
|
||||
|
|
||||
strict = Strict() and minsize = 1 + k.getValue().toInt()
|
||||
or
|
||||
strict = Nonstrict() and minsize = k.getValue().toInt()
|
||||
)
|
||||
or
|
||||
// `if (x.size() == 2) { ...x[1]... }`
|
||||
exists(SizeCall sizeCall, Expr k |
|
||||
arrayExpr = sizeCall.getQualifier() and
|
||||
eqOpWithSwapAndNegate(cond, sizeCall, k, true, branch) and
|
||||
minsize = k.getValue().toInt()
|
||||
)
|
||||
or
|
||||
// `if (x.size() != 0) { ...x[0]... }`
|
||||
exists(SizeCall sizeCall, Expr k |
|
||||
arrayExpr = sizeCall.getQualifier() and
|
||||
eqOpWithSwapAndNegate(cond, sizeCall, k, false, branch) and
|
||||
k.getValue().toInt() = 0 and
|
||||
minsize = 1
|
||||
)
|
||||
}
|
||||
|
||||
// Array accesses like these are safe:
|
||||
// `if (!x.empty()) { ... x[0] ... }`
|
||||
// `if (x.size() > 2) { ... x[2] ... }`
|
||||
predicate indexK_with_check(GuardCondition guard, ArrayIndexCall call) {
|
||||
exists(Expr arrayExpr, BasicBlock block, int i, int minsize, boolean branch |
|
||||
minimum_size_cond(guard, arrayExpr, minsize, branch) and
|
||||
(
|
||||
globalValueNumber(arrayExpr) = globalValueNumber(call.getQualifier()) or
|
||||
hashCons(arrayExpr) = hashCons(call.getQualifier())
|
||||
) and
|
||||
guard.controls(block, branch) and
|
||||
block.contains(call) and
|
||||
i = call.getArgument(0).getValue().toInt() and
|
||||
0 <= i and
|
||||
i < minsize
|
||||
)
|
||||
}
|
||||
|
||||
// Array accesses like this are safe:
|
||||
// `if (i < x.size()) { ... x[i] ... }`
|
||||
predicate indexI_with_check(GuardCondition guard, ArrayIndexCall call) {
|
||||
exists(Expr idx, SizeCall sizeCall, BasicBlock block, boolean branch |
|
||||
relOpWithSwapAndNegate(guard, idx, sizeCall, Lesser(), Strict(), branch) and
|
||||
(
|
||||
globalValueNumber(sizeCall.getQualifier()) = globalValueNumber(call.getQualifier()) and
|
||||
globalValueNumber(idx) = globalValueNumber(call.getArgument(0))
|
||||
or
|
||||
hashCons(sizeCall.getQualifier()) = hashCons(call.getQualifier()) and
|
||||
hashCons(idx) = hashCons(call.getArgument(0))
|
||||
) and
|
||||
guard.controls(block, branch) and
|
||||
block.contains(call)
|
||||
)
|
||||
}
|
||||
|
||||
// Array accesses like this are safe:
|
||||
// `if (!x.empty()) { ... x[x.size() - 1] ... }`
|
||||
predicate index_last_with_check(GuardCondition guard, ArrayIndexCall call) {
|
||||
exists(Expr arrayExpr, SubExpr minusExpr, SizeCall sizeCall, BasicBlock block, boolean branch |
|
||||
minimum_size_cond(guard, arrayExpr, _, branch) and
|
||||
(
|
||||
globalValueNumber(arrayExpr) = globalValueNumber(call.getQualifier()) or
|
||||
hashCons(arrayExpr) = hashCons(call.getQualifier())
|
||||
) and
|
||||
guard.controls(block, branch) and
|
||||
block.contains(call) and
|
||||
minusExpr = call.getArgument(0) and
|
||||
minusExpr.getRightOperand().getValue().toInt() = 1 and
|
||||
DataFlow::localExprFlow(sizeCall, minusExpr.getLeftOperand()) and
|
||||
(
|
||||
globalValueNumber(sizeCall.getQualifier()) = globalValueNumber(call.getQualifier()) or
|
||||
hashCons(sizeCall.getQualifier()) = hashCons(call.getQualifier())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
from ArrayIndexCall call
|
||||
where
|
||||
not indexK_with_fixedarray(_, call) and
|
||||
not indexK_with_check(_, call) and
|
||||
not indexI_with_check(_, call) and
|
||||
not index_last_with_check(_, call) and
|
||||
// Ignore accesses like this: `vsnprintf(&buffer[0], buffer.size(), format, args)`
|
||||
// That's pointer arithmetic, not a deref, so it's usually a false positive.
|
||||
not exists(AddressOfExpr addrExpr | addrExpr.getOperand() = call) and
|
||||
// Ignore results in the xmpsdk directory.
|
||||
not call.getLocation().getFile().getRelativePath().matches("xmpsdk/%")
|
||||
select call, "Unsafe use of operator[]. Use the at() method instead."
|
@ -1,5 +0,0 @@
|
||||
name: "Exiv2 CodeQL config"
|
||||
|
||||
queries:
|
||||
- uses: ./.github/codeql-queries/exiv2-code-scanning.qls
|
||||
- uses: ./.github/codeql-queries/exiv2-cpp-queries
|
@ -1,6 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
@ -1,33 +0,0 @@
|
||||
# OSS-Fuzz continuous integration:
|
||||
# https://google.github.io/oss-fuzz/getting-started/continuous-integration/
|
||||
|
||||
name: CIFuzz
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
jobs:
|
||||
Fuzzing:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Build Fuzzers
|
||||
id: build
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'exiv2'
|
||||
dry-run: false
|
||||
- name: Run Fuzzers
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'exiv2'
|
||||
fuzz-seconds: 600
|
||||
dry-run: false
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: artifacts
|
||||
path: ./out/artifacts
|
@ -1,22 +0,0 @@
|
||||
# This workflow was added by CodeSee. Learn more at https://codesee.io/
|
||||
# This is v2.0 of this workflow file
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
name: CodeSee
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
codesee:
|
||||
runs-on: ubuntu-22.04
|
||||
continue-on-error: true
|
||||
name: Analyze the repo with CodeSee
|
||||
steps:
|
||||
- uses: Codesee-io/codesee-action@v2
|
||||
with:
|
||||
codesee-token: ${{ secrets.CODESEE_ARCH_DIAG_API_TOKEN }}
|
@ -1,43 +0,0 @@
|
||||
on:
|
||||
schedule:
|
||||
- cron: 0 4 * * *
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
name: Nightly - Linux distributions
|
||||
|
||||
jobs:
|
||||
distros:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
container_image: ["fedora", "debian", "archlinux", "ubuntu", "tgagor/centos", "alpine"]
|
||||
compiler:
|
||||
- { CC: gcc, CXX: g++ }
|
||||
- { CC: clang, CXX: clang++ }
|
||||
build_type: [Release, Debug]
|
||||
shared_libraries: [ON, OFF]
|
||||
container:
|
||||
image: ${{ matrix.container_image }}
|
||||
env:
|
||||
CC: ${{ matrix.compiler.CC }}
|
||||
CXX: ${{ matrix.compiler.CXX }}
|
||||
CMAKE_FLAGS: -DEXIV2_TEAM_EXTRA_WARNINGS=OFF -DEXIV2_ENABLE_WEBREADY=ON -DEXIV2_ENABLE_CURL=ON -DEXIV2_BUILD_UNIT_TESTS=OFF -DEXIV2_TEAM_WARNINGS_AS_ERRORS=OFF -DCMAKE_INSTALL_PREFIX=install
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: ./ci/install_dependencies.sh
|
||||
- name: Build and install
|
||||
run: |
|
||||
cmake -GNinja $CMAKE_FLAGS -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DBUILD_SHARED_LIBS=${{ matrix.shared_libraries }} -S . -B build
|
||||
cmake --build build --parallel
|
||||
cmake --install build
|
@ -1,40 +0,0 @@
|
||||
# Builds and runs the fuzz target for a short amount of time. This is
|
||||
# mainly to protect the fuzz target from bitrot, but hopefully will
|
||||
# also help to quickly catch some bugs before the PR is merged.
|
||||
|
||||
name: On PRs - Linux-Ubuntu Quick Fuzz
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
Linux:
|
||||
name: 'Ubuntu 24.04 - clang/libFuzzer'
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo ./ci/install_dependencies.sh
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
run: |
|
||||
cmake --preset linux-sanitizers -S . -B build -DCMAKE_BUILD_TYPE=Release -DEXIV2_BUILD_FUZZ_TESTS=ON -DEXIV2_BUILD_UNIT_TESTS=OFF
|
||||
cmake --build build --parallel
|
||||
|
||||
- name: Fuzz
|
||||
run: |
|
||||
cd build
|
||||
mkdir corpus
|
||||
LSAN_OPTIONS=suppressions=../fuzz/knownleaks.txt ./bin/fuzz-read-print-write corpus ../test/data/ -dict=../fuzz/exiv2.dict -jobs=$(nproc) -workers=$(nproc) -max_len=4096 -max_total_time=120
|
@ -1,57 +0,0 @@
|
||||
name: On PRs - Linux-Ubuntu Matrix
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
|
||||
jobs:
|
||||
Linux:
|
||||
name: 'Ubuntu 22.04 - GCC, BuildType:${{matrix.build_type}}, SHARED:${{matrix.shared_libraries}}'
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
build_type: [Release, Debug]
|
||||
shared_libraries: [ON, OFF]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt install -y tree ninja-build
|
||||
python3 -m pip install conan==1.*
|
||||
|
||||
- name: Conan common config
|
||||
run: |
|
||||
conan profile new --detect default
|
||||
conan profile update settings.build_type=${{matrix.build_type}} default
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 default
|
||||
|
||||
- name: Run Conan
|
||||
run: |
|
||||
mkdir build-base_linux && cd build-base_linux
|
||||
conan profile list
|
||||
conan profile show default
|
||||
conan install .. -o webready=True --build missing
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --preset base_linux -S . -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DBUILD_SHARED_LIBS=${{matrix.shared_libraries}}
|
||||
cmake --build build-base_linux --parallel
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
cd build-base_linux
|
||||
cmake --install .
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
cd build-base_linux
|
||||
ctest --output-on-failure
|
@ -1,187 +0,0 @@
|
||||
name: On PRs - Linux Special Builds
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
|
||||
jobs:
|
||||
special_debugRelease:
|
||||
name: 'Ubuntu 22.04 - GCC - Debug+Coverage'
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
# Trying to deal with warning: -> Issue detecting commit SHA. Please run actions/checkout with fetch-depth > 1 or set to 0
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo eatmydata apt-get -y install libxml2-dev libxslt-dev python3-dev ninja-build gcovr
|
||||
python3 -m pip install conan==1.*
|
||||
|
||||
- name: Conan common config
|
||||
run: |
|
||||
conan profile new --detect default
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 default
|
||||
|
||||
- name: Run Conan
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
conan profile list
|
||||
conan profile show default
|
||||
conan install .. -o webready=True --build missing
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --preset linux-coverage -S . -B build
|
||||
cmake --build build --parallel
|
||||
|
||||
- name: Tests + Upload coverage
|
||||
run: |
|
||||
cd build
|
||||
ctest --output-on-failure
|
||||
# this needs to match th ecommand in on_push_ExtraJobsForMain.yml!
|
||||
gcovr --root .. --object-dir . --exclude-unreachable-branches --exclude-throw-branches --xml -o coverage.xml
|
||||
curl https://keybase.io/codecovsecurity/pgp_keys.asc | gpg --import
|
||||
curl -Os https://uploader.codecov.io/latest/linux/codecov
|
||||
curl -Os https://uploader.codecov.io/latest/linux/codecov.SHA256SUM
|
||||
curl -Os https://uploader.codecov.io/latest/linux/codecov.SHA256SUM.sig
|
||||
gpg --verify codecov.SHA256SUM.sig codecov.SHA256SUM
|
||||
shasum -a 256 -c codecov.SHA256SUM
|
||||
chmod +x codecov
|
||||
ls -lh
|
||||
./codecov -f coverage.xml
|
||||
|
||||
special_releaseValgrind:
|
||||
name: 'Ubuntu 22.04 - GCC - Release+Valgrind'
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt install -y valgrind ninja-build
|
||||
python3 -m pip install conan==1.*
|
||||
|
||||
- name: Conan common config
|
||||
run: |
|
||||
conan profile new --detect default
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 default
|
||||
|
||||
- name: Run Conan
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
conan profile list
|
||||
conan profile show default
|
||||
conan install .. -o webready=True --build missing
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --preset linux-release -S . -B build
|
||||
cmake --build build --parallel
|
||||
|
||||
- name: Tests with valgrind
|
||||
run: |
|
||||
cd build/bin
|
||||
valgrind ./unit_tests
|
||||
|
||||
|
||||
special_releaseSanitizers:
|
||||
name: 'Ubuntu 22.04 - GCC - Release+Sanitizers'
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt install -y ninja-build
|
||||
python3 -m pip install conan==1.*
|
||||
|
||||
- name: Conan common config
|
||||
run: |
|
||||
conan profile new --detect default
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 default
|
||||
|
||||
- name: Run Conan
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
conan profile list
|
||||
conan profile show default
|
||||
conan install .. -o webready=True --build missing
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --preset linux-sanitizers -S . -B build
|
||||
cmake --build build --parallel
|
||||
|
||||
- name: Tests
|
||||
run: |
|
||||
cd build
|
||||
ctest --output-on-failure
|
||||
|
||||
special_noFilesystemAccess:
|
||||
name: 'Ubuntu 22.04 - GCC - No filesystem access build'
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt install -y ninja-build
|
||||
python3 -m pip install conan==1.*
|
||||
|
||||
- name: Conan common config
|
||||
run: |
|
||||
conan profile new --detect default
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 default
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --preset linux-release -S . -B build -DEXIV2_ENABLE_FILESYSTEM_ACCESS=OFF -DEXIV2_BUILD_SAMPLES=OFF -DEXIV2_BUILD_UNIT_TESTS=OFF -DEXIV2_BUILD_EXIV2_COMMAND=OFF
|
||||
cmake --build build --parallel
|
||||
|
||||
special_allEnabled:
|
||||
name: 'Ubuntu 22.04 - GCC - All Options Enabled + Documentation'
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt install -y valgrind doxygen graphviz gettext ninja-build
|
||||
python3 -m pip install conan==1.*
|
||||
|
||||
- name: Conan common config
|
||||
run: |
|
||||
conan profile new --detect default
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 default
|
||||
|
||||
- name: Run Conan
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
conan profile list
|
||||
conan profile show default
|
||||
conan install .. -o webready=True --build missing
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
CXXFLAGS: -DEXIV2_DEBUG_MESSAGES
|
||||
run: |
|
||||
cmake --preset linux-release -S . -B build -DEXIV2_BUILD_DOC=ON
|
||||
cmake --build build --parallel
|
||||
|
||||
- name: Generate documentation
|
||||
run: |
|
||||
make doc
|
||||
|
@ -1,65 +0,0 @@
|
||||
name: On PRs - Linux - Static Analysis
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
|
||||
jobs:
|
||||
special_pvsStudio:
|
||||
name: 'Ubuntu 22.04 - GCC - Static Analyzer: PVS-Studio'
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
# Trying to deal with warning: -> Issue detecting commit SHA. Please run actions/checkout with fetch-depth > 1 or set to 0
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python3 -m pip install conan==1.*
|
||||
sudo add-apt-repository ppa:ubuntu-lxc/daily -y
|
||||
wget -q -O - https://files.pvs-studio.com/etc/pubkey.txt |sudo apt-key add -
|
||||
sudo wget -O /etc/apt/sources.list.d/viva64.list https://files.pvs-studio.com/etc/viva64.list
|
||||
sudo apt update -qq
|
||||
sudo apt install -qq pvs-studio
|
||||
|
||||
- name: Conan common config
|
||||
run: |
|
||||
conan profile new --detect default
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 default
|
||||
|
||||
- name: Run Conan
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
conan profile list
|
||||
conan profile show default
|
||||
conan install .. -o webready=True --build missing
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake --preset linux-debug -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||
|
||||
- name: Static Analysis
|
||||
env:
|
||||
PVS_USERNAME: ${{ secrets.PVS_USERNAME }}
|
||||
PVS_KEY: ${{ secrets.PVS_KEY }}
|
||||
run: |
|
||||
cd build
|
||||
pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY -o PVS_license.lic
|
||||
pvs-studio-analyzer analyze -l PVS_license.lic -o pvsStudio.log -j4 --disableLicenseExpirationCheck
|
||||
plog-converter -a GA:1,2 -d V1042 -t fullhtml pvsStudio.log -o pvsReportHtml
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: static_analysis
|
||||
path: build/pvsReportHtml
|
||||
retention-days: 7
|
||||
|
||||
|
@ -1,42 +0,0 @@
|
||||
name: On PRs - Mac Matrix
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
|
||||
jobs:
|
||||
MacOS:
|
||||
name: 'macOS - XCode - ${{matrix.build_type}} - SHARED:${{matrix.shared_libraries}}'
|
||||
runs-on: macos-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
build_type: [Release, Debug]
|
||||
shared_libraries: [ON, OFF]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew install ninja inih googletest
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --preset base_mac -S . -B build -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DBUILD_SHARED_LIBS=${{matrix.shared_libraries}}
|
||||
cmake --build build --parallel
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
cd build
|
||||
cmake --install .
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
ctest --test-dir build --output-on-failure
|
@ -1,32 +0,0 @@
|
||||
name: On PRs - Mac Special Builds
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
|
||||
jobs:
|
||||
MacOS_releaseSanitizers:
|
||||
name: 'macOS - XCode - Release+Sanitizers'
|
||||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew install ninja inih googletest
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --preset base_mac -S . -B build -DEXIV2_TEAM_USE_SANITIZERS=ON
|
||||
cmake --build build --parallel
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
ASAN_OPTIONS=detect_container_overflow=0 ctest --test-dir build --output-on-failure
|
@ -1,171 +0,0 @@
|
||||
name: On PRs - meson
|
||||
|
||||
on: pull_request
|
||||
|
||||
concurrency:
|
||||
group: ${{github.workflow}}-${{github.head_ref}}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
Ubuntu:
|
||||
runs-on: ubuntu-20.04
|
||||
name: Linux-GCC${{matrix.cxx}}-deps=${{matrix.deps}}
|
||||
strategy:
|
||||
matrix:
|
||||
cxx: ['7', '13']
|
||||
deps: ['forcefallback', 'default']
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: egor-tensin/setup-gcc@v1
|
||||
with:
|
||||
version: ${{matrix.cxx}}
|
||||
- name: Install meson
|
||||
run: python3 -m pip install meson ninja
|
||||
- name: Compile and Test
|
||||
run: |
|
||||
meson setup "${{github.workspace}}/build" --wrap-mode=${{matrix.deps}} -Dwarning_level=3
|
||||
meson compile -C "${{github.workspace}}/build"
|
||||
meson test -C "${{github.workspace}}/build"
|
||||
Ubuntu-clang:
|
||||
runs-on: ubuntu-20.04
|
||||
name: Linux-Clang${{matrix.cxx}}-deps=${{matrix.deps}}
|
||||
strategy:
|
||||
matrix:
|
||||
cxx: ['7', '18']
|
||||
deps: ['forcefallback', 'default']
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: egor-tensin/setup-clang@v1
|
||||
with:
|
||||
version: ${{matrix.cxx}}
|
||||
- name: Install meson
|
||||
run: |
|
||||
python3 -m pip install meson ninja
|
||||
sudo apt install -y libc++abi-${{matrix.cxx}}-dev libc++-${{matrix.cxx}}-dev
|
||||
- name: Compile and Test
|
||||
env:
|
||||
CXXFLAGS: -stdlib=libc++
|
||||
run: |
|
||||
meson setup "${{github.workspace}}/build" --wrap-mode=${{matrix.deps}} -Dwarning_level=3 -Dcpp_std=c++20
|
||||
meson compile -C "${{github.workspace}}/build" --verbose
|
||||
meson test -C "${{github.workspace}}/build" --verbose
|
||||
VisualStudio:
|
||||
runs-on: windows-latest
|
||||
name: MSVC-${{matrix.deps}}-${{matrix.platform}}
|
||||
strategy:
|
||||
matrix:
|
||||
deps: ['forcefallback', 'default']
|
||||
platform: ['x64', 'x86']
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install packages
|
||||
run: |
|
||||
python -m pip install meson ninja
|
||||
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: ${{matrix.platform}}
|
||||
|
||||
- name: Compile and Test
|
||||
run: |
|
||||
meson setup "${{github.workspace}}/build" --wrap-mode=${{matrix.deps}} -Dwarning_level=3 -Dcpp_std=c++latest -Db_sanitize=address
|
||||
meson compile -C "${{github.workspace}}/build" --verbose
|
||||
meson test -C "${{github.workspace}}/build" --verbose
|
||||
VisualStudio-clang-cl:
|
||||
runs-on: windows-latest
|
||||
name: clang-cl-${{matrix.deps}}
|
||||
strategy:
|
||||
matrix:
|
||||
deps: ['forcefallback', 'default']
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install packages
|
||||
run: |
|
||||
python -m pip install meson ninja
|
||||
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
|
||||
- name: Compile and Test
|
||||
env:
|
||||
CC: clang-cl
|
||||
CXX: clang-cl
|
||||
run: |
|
||||
meson setup "${{github.workspace}}/build" --wrap-mode=${{matrix.deps}} -Dwarning_level=3 -Dcpp_std=c++latest -Db_sanitize=address
|
||||
meson compile -C "${{github.workspace}}/build" --verbose
|
||||
meson test -C "${{github.workspace}}/build" --verbose
|
||||
MSYS2:
|
||||
runs-on: windows-latest
|
||||
name: MSYS2-${{matrix.platform}}-deps=${{matrix.deps}}
|
||||
strategy:
|
||||
matrix:
|
||||
deps: ['enabled', 'disabled']
|
||||
platform: ['UCRT64', 'CLANG64']
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{matrix.platform}}
|
||||
pacboy: >-
|
||||
cc:p
|
||||
cmake:p
|
||||
curl:p
|
||||
gtest:p
|
||||
libinih:p
|
||||
meson:p
|
||||
ninja:p
|
||||
pkgconf:p
|
||||
|
||||
- name: Compile and Test
|
||||
run: |
|
||||
meson setup "${{github.workspace}}/build" -Dauto_features=${{matrix.deps}} -Dwarning_level=3 -Dcpp_std=c++20
|
||||
meson compile -C "${{github.workspace}}/build" --verbose
|
||||
meson test -C "${{github.workspace}}/build" --verbose
|
||||
MacOS:
|
||||
runs-on: macos-latest
|
||||
name: macOS-deps=${{matrix.deps}}
|
||||
strategy:
|
||||
matrix:
|
||||
deps: ['enabled', 'disabled']
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install packages
|
||||
run: |
|
||||
brew install inih meson
|
||||
|
||||
- name: Compile and Test
|
||||
run: |
|
||||
meson setup "${{github.workspace}}/build" -Dauto_features=${{matrix.deps}} -Dwarning_level=3 -Dnls=disabled -Db_sanitize=address,undefined
|
||||
meson compile -C "${{github.workspace}}/build" --verbose
|
||||
meson test -C "${{github.workspace}}/build" --verbose
|
||||
FreeBSD:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: vmactions/freebsd-vm@v1
|
||||
with:
|
||||
prepare: |
|
||||
pkg install -y cmake curl ninja meson gettext pkgconf googletest expat inih brotli
|
||||
run: |
|
||||
meson setup "${{github.workspace}}/build" -Dwarning_level=3 -Dcpp_std=c++20
|
||||
meson compile -C "${{github.workspace}}/build" --verbose
|
||||
meson test -C "${{github.workspace}}/build" --verbose
|
||||
Emscripten:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: |
|
||||
python3 -m pip install meson ninja
|
||||
- name: Emscripten
|
||||
uses: mymindstorm/setup-emsdk@v14
|
||||
- name: Compile
|
||||
run: |
|
||||
meson setup "${{github.workspace}}/build" --cross-file="${{github.workspace}}/em.txt" --wrap-mode=forcefallback -Ddefault_library=static -Dwarning_level=3 -Dcpp_std=c++20 -DunitTests=disabled -Dcurl=disabled
|
||||
meson compile -C "${{github.workspace}}/build" --verbose
|
@ -1,185 +0,0 @@
|
||||
name: On PRs - Windows Matrix
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [0.28.x, main]
|
||||
tags:
|
||||
- '!*'
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
|
||||
jobs:
|
||||
windows:
|
||||
name: 'Win10 Arch: ${{matrix.platform}} BuildType:${{matrix.build_type}} - SHARED:${{matrix.shared_libraries}}'
|
||||
runs-on: windows-2022
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
build_type: [Release, Debug]
|
||||
shared_libraries: [ON, OFF]
|
||||
platform: [ x64, x86 ]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Visual Studio shell
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: ${{matrix.platform}}
|
||||
|
||||
- name: Restore Conan cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{github.workspace}}/conanCache
|
||||
key: ${{runner.os}}-${{matrix.platform}}-${{matrix.build_type}}-Shared${{matrix.shared_libraries}}-${{ hashFiles('conanfile.py') }}
|
||||
|
||||
- name: Install Conan & Common config
|
||||
run: |
|
||||
python -m pip install conan==1.*
|
||||
conan config install https://github.com/conan-io/conanclientcert.git
|
||||
conan profile new --detect default
|
||||
conan profile update settings.build_type=${{matrix.build_type}} default
|
||||
conan profile update settings.compiler="Visual Studio" default
|
||||
conan profile update settings.compiler.version=17 default
|
||||
conan config set storage.path=$Env:GITHUB_WORKSPACE/conanCache
|
||||
|
||||
- name: Conan Arch conditional config
|
||||
if: ${{matrix.platform == 'x86'}}
|
||||
run: |
|
||||
conan profile update settings.arch=x86 default
|
||||
conan profile update settings.arch_build=x86 default
|
||||
|
||||
- name: Run Conan
|
||||
run: |
|
||||
md build
|
||||
cd build
|
||||
conan profile list
|
||||
conan install .. --build missing
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --preset base_windows -S . -B build -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DBUILD_SHARED_LIBS=${{matrix.shared_libraries}}
|
||||
cmake --build build --parallel
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
cmake --install build
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
ctest --test-dir build --output-on-failure
|
||||
|
||||
msys2:
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 40
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
build_type: [Release, Debug]
|
||||
shared_libraries: [ON, OFF]
|
||||
sys: [UCRT64]
|
||||
name: MSYS2 ${{matrix.sys}} - BuildType:${{matrix.build_type}} - SHARED:${{matrix.shared_libraries}}
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up MSYS2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
path-type: strict
|
||||
msystem: ${{matrix.sys}}
|
||||
update: true
|
||||
pacboy: >-
|
||||
cc:p
|
||||
gcc-libs:p
|
||||
libwinpthread:p
|
||||
cmake:p
|
||||
ninja:p
|
||||
python:p
|
||||
gtest:p
|
||||
brotli:p
|
||||
curl:p
|
||||
expat:p
|
||||
libiconv:p
|
||||
libinih:p
|
||||
zlib:p
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --preset base_windows \
|
||||
-DCMAKE_BUILD_TYPE=${{matrix.build_type}} \
|
||||
-DBUILD_SHARED_LIBS=${{matrix.shared_libraries}} \
|
||||
-DCONAN_AUTO_INSTALL=OFF \
|
||||
-DEXIV2_TEAM_WARNINGS_AS_ERRORS=OFF \
|
||||
-DPython3_EXECUTABLE=${MINGW_PREFIX}/bin/python.exe \
|
||||
-S . -B build && \
|
||||
cmake --build build --parallel
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
ctest --test-dir build --output-on-failure
|
||||
|
||||
cygwin:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
build_type: [Release]
|
||||
shared_libraries: [ON]
|
||||
platform: [x86_64]
|
||||
name: Cygwin ${{matrix.platform}} - BuildType:${{matrix.build_type}} - SHARED:${{matrix.shared_libraries}}
|
||||
env:
|
||||
SHELLOPTS: igncr
|
||||
defaults:
|
||||
run:
|
||||
shell: C:\cygwin\bin\bash.exe -eo pipefail '{0}'
|
||||
steps:
|
||||
# Make sure we don't check out scripts using Windows CRLF line endings
|
||||
- run: git config --global core.autocrlf input
|
||||
shell: pwsh
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Cygwin
|
||||
uses: cygwin/cygwin-install-action@v4
|
||||
with:
|
||||
platform: ${{matrix.platform}}
|
||||
packages: >-
|
||||
gcc-g++
|
||||
cmake
|
||||
ninja
|
||||
pkg-config
|
||||
python3
|
||||
libbrotli-devel
|
||||
libcurl-devel
|
||||
libexpat-devel
|
||||
libiconv-devel
|
||||
libinih-devel
|
||||
zlib-devel
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --preset base_windows \
|
||||
-DCMAKE_BUILD_TYPE=${{matrix.build_type}} \
|
||||
-DBUILD_SHARED_LIBS=${{matrix.shared_libraries}} \
|
||||
-DCONAN_AUTO_INSTALL=OFF \
|
||||
-DEXIV2_BUILD_SAMPLES=OFF \
|
||||
-DEXIV2_BUILD_UNIT_TESTS=OFF \
|
||||
-DEXIV2_TEAM_WARNINGS_AS_ERRORS=OFF \
|
||||
-S . -B build && \
|
||||
cmake --build build --parallel
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
ctest --test-dir build --output-on-failure
|
@ -1,106 +0,0 @@
|
||||
# Basic CI for all platforms on push
|
||||
# Note that we want to run this as fast as possible and just for the more common configurations. On
|
||||
# PRs, we will test things more intensively :)
|
||||
# - Only running UnitTests and not regression tests
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
name: On PUSH - Basic CI for main platforms
|
||||
|
||||
jobs:
|
||||
windows:
|
||||
name: 'Windows 10 - MSVC - Arch:X64 BuildType:Release - SHARED'
|
||||
runs-on: windows-2022
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Visual Studio shell
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: x64
|
||||
|
||||
- name: Restore Conan cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{github.workspace}}/conanCache
|
||||
key: ${{runner.os}}-push-win-${{ hashFiles('conanfile.py') }}
|
||||
|
||||
- name: Install Conan & Common config
|
||||
run: |
|
||||
python -m pip install conan==1.*
|
||||
conan profile new --detect default
|
||||
conan profile show default
|
||||
conan profile update settings.compiler="Visual Studio" default
|
||||
conan profile update settings.compiler.version=17 default
|
||||
conan config set storage.path=$Env:GITHUB_WORKSPACE/conanCache
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --preset win-release -S . -B build
|
||||
cmake --build build --parallel
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
ctest --test-dir build --output-on-failure
|
||||
|
||||
Linux:
|
||||
name: 'Ubuntu 22.04 - GCC - Arch:X64 BuildType:Release - SHARED'
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo eatmydata apt-get -y install ninja-build
|
||||
python3 -m pip install conan==1.*
|
||||
|
||||
- name: Conan
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
conan profile new --detect default
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 default
|
||||
conan profile show default
|
||||
conan install .. -o webready=True --build missing
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --preset linux-release -S . -B build
|
||||
cmake --build build --parallel
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
ctest --test-dir build --output-on-failure
|
||||
|
||||
MacOS:
|
||||
name: 'macOS - XCode - Arch:${{ matrix.runner.arch }} BuildType:Release - SHARED'
|
||||
runs-on: ${{ matrix.runner.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
runner:
|
||||
- { os: macos-12, arch: X64 }
|
||||
- { os: macos-14, arch: ARM64 }
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew install ninja inih googletest
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --preset base_mac -S . -B build
|
||||
cmake --build build --parallel
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
ctest --test-dir build --output-on-failure
|
@ -1,60 +0,0 @@
|
||||
name: On PUSH - Linux Special Builds for main branch
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
tags:
|
||||
- '!*'
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
special_debugRelease:
|
||||
name: 'Ubuntu 22.04 - GCC - Debug+Coverage'
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo eatmydata apt-get -y install ninja-build gcovr
|
||||
python3 -m pip install conan==1.*
|
||||
|
||||
- name: Conan common config
|
||||
run: |
|
||||
conan profile new --detect default
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 default
|
||||
|
||||
- name: Run Conan
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
conan profile list
|
||||
conan profile show default
|
||||
conan install .. -o webready=True --build missing
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --preset linux-coverage -S . -B build
|
||||
cmake --build build
|
||||
|
||||
- name: Tests + Upload coverage
|
||||
run: |
|
||||
cd build
|
||||
ctest --output-on-failure
|
||||
# this needs to match th ecommand in on_PR_linux_secial_builds.yml!
|
||||
gcovr --root .. --object-dir . --exclude-unreachable-branches --exclude-throw-branches --xml -o coverage.xml .
|
||||
curl https://keybase.io/codecovsecurity/pgp_keys.asc | gpg --import
|
||||
curl -Os https://uploader.codecov.io/latest/linux/codecov
|
||||
curl -Os https://uploader.codecov.io/latest/linux/codecov.SHA256SUM
|
||||
curl -Os https://uploader.codecov.io/latest/linux/codecov.SHA256SUM.sig
|
||||
gpg --verify codecov.SHA256SUM.sig codecov.SHA256SUM
|
||||
shasum -a 256 -c codecov.SHA256SUM
|
||||
chmod +x codecov
|
||||
./codecov -f build/coverage.xml
|
@ -1,16 +0,0 @@
|
||||
name: Clang Format Checker
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
clang-format-checking:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: DoozyX/clang-format-lint-action@v0.17
|
||||
with:
|
||||
source: '.'
|
||||
exclude: './xmpsdk ./contrib'
|
||||
extensions: 'c,h,cpp,hpp'
|
||||
style: file
|
@ -1,227 +0,0 @@
|
||||
name: Release
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v[0-9]+.[0-9]+.[0-9]+
|
||||
schedule:
|
||||
- cron: '30 4 * * *'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag_name:
|
||||
description: 'Tag name for release'
|
||||
required: false
|
||||
default: nightly
|
||||
|
||||
jobs:
|
||||
Linux:
|
||||
name: 'Build Linux Release'
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt install -y gettext doxygen graphviz ninja-build
|
||||
python -m pip install conan==1.*
|
||||
|
||||
- name: Conan common config
|
||||
run: |
|
||||
conan profile new --detect default
|
||||
conan profile update settings.build_type=Release default
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 default
|
||||
|
||||
- name: Run Conan
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
conan profile list
|
||||
conan profile show default
|
||||
conan install .. -o webready=False --build missing
|
||||
|
||||
- name: Build packaged release
|
||||
run: |
|
||||
cmake --preset linux-all -S . -B build -DEXIV2_TEAM_PACKAGING=ON -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DEXIV2_ENABLE_WEBREADY=OFF -DEXIV2_ENABLE_CURL=OFF -DEXIV2_BUILD_SAMPLES=OFF
|
||||
cmake --build build -t doc
|
||||
cmake --build build -t package
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: exiv2-linux64
|
||||
path: ./build/exiv2-*.tar.gz
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
macOS:
|
||||
name: 'Build macOS Release'
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew install ninja
|
||||
brew install inih
|
||||
brew install tree
|
||||
brew install gettext
|
||||
brew install doxygen
|
||||
brew install graphviz
|
||||
|
||||
- name: Build packaged release
|
||||
run: |
|
||||
mkdir build
|
||||
cmake -GNinja -S . -B build \
|
||||
-DEXIV2_TEAM_PACKAGING=ON \
|
||||
-DBUILD_SHARED_LIBS=ON \
|
||||
-DEXIV2_ENABLE_WEBREADY=OFF \
|
||||
-DEXIV2_ENABLE_NLS=ON \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DEXIV2_ENABLE_BMFF=ON \
|
||||
-DEXIV2_TEAM_WARNINGS_AS_ERRORS=ON \
|
||||
-DEXIV2_BUILD_DOC=ON \
|
||||
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON
|
||||
cmake --build build -t doc
|
||||
cmake --build build -t package
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: exiv2-macos
|
||||
path: ./build/exiv2-*.tar.gz
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
Windows:
|
||||
name: 'Build Windows Release'
|
||||
runs-on: windows-2022
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Visual Studio shell
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
|
||||
- name: Install doxygen
|
||||
run: |
|
||||
choco install doxygen.install
|
||||
choco install graphviz
|
||||
|
||||
- name: Restore conan cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{github.workspace}}/conanCache
|
||||
key: ${{runner.os}}-release-win-${{ hashFiles('conanfile.py') }}
|
||||
|
||||
- name: Install Conan & Common config
|
||||
run: |
|
||||
python -m pip install conan==1.*
|
||||
conan profile new --detect default
|
||||
conan profile show default
|
||||
conan profile update settings.build_type=Release default
|
||||
conan profile update settings.compiler="Visual Studio" default
|
||||
conan profile update settings.compiler.version=17 default
|
||||
conan config set storage.path=$Env:GITHUB_WORKSPACE/conanCache
|
||||
|
||||
- name: Run Conan
|
||||
run: |
|
||||
md build
|
||||
cd build
|
||||
conan install .. --build missing
|
||||
|
||||
- name: Build packaged release
|
||||
run: |
|
||||
cmake --preset win-release -S . -B build -DEXIV2_TEAM_PACKAGING=ON -DEXIV2_BUILD_DOC=ON -DEXIV2_ENABLE_WEBREADY=OFF -DEXIV2_ENABLE_CURL=OFF -DEXIV2_BUILD_SAMPLES=OFF
|
||||
cmake --build build --parallel -t doc
|
||||
cmake --build build --parallel -t package
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: exiv2-win
|
||||
path: ./build/exiv2-*.zip
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
publish:
|
||||
needs: [Linux, macOS, Windows]
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
|
||||
- if: github.event_name == 'workflow_dispatch'
|
||||
run: echo "TAG_NAME=${{ github.event.inputs.tag_name }}" >> $GITHUB_ENV
|
||||
|
||||
- if: github.event_name == 'schedule'
|
||||
run: echo 'TAG_NAME=nightly' >> $GITHUB_ENV
|
||||
|
||||
- if: github.event_name == 'push'
|
||||
run: |
|
||||
TAG_NAME=${{ github.ref }}
|
||||
echo "TAG_NAME=${TAG_NAME#refs/tags/}" >> $GITHUB_ENV
|
||||
|
||||
- if: env.TAG_NAME == 'nightly'
|
||||
run: |
|
||||
echo 'BODY<<EOF' >> $GITHUB_ENV
|
||||
echo '## Exiv2 nightly prerelease build.' >> $GITHUB_ENV
|
||||
echo 'Please help us improve exiv2 by reporting any issues you encounter :wink:' >> $GITHUB_ENV
|
||||
echo 'EOF' >> $GITHUB_ENV
|
||||
|
||||
|
||||
- if: env.TAG_NAME != 'nightly'
|
||||
run: |
|
||||
echo 'BODY<<EOF' >> $GITHUB_ENV
|
||||
echo '## Exiv2 Release ${{ env.TAG_NAME }}' >> $GITHUB_ENV
|
||||
echo 'See [ChangeLog](doc/ChangeLog) for more information about the changes in this release.' >> $GITHUB_ENV
|
||||
echo 'EOF' >> $GITHUB_ENV
|
||||
|
||||
- name: Cleanup old nightly
|
||||
if: env.TAG_NAME == 'nightly'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
try{
|
||||
const rel_id = await github.rest.repos.getReleaseByTag({
|
||||
...context.repo,
|
||||
tag: "nightly"
|
||||
}).then(result => result.data.id);
|
||||
|
||||
console.log( "Found existing nightly release with id: ", rel_id);
|
||||
|
||||
await github.rest.repos.deleteRelease({
|
||||
...context.repo,
|
||||
release_id: rel_id
|
||||
});
|
||||
console.log( "Deletion of release successful")
|
||||
|
||||
}catch(error){
|
||||
console.log( "Deletion of release failed");
|
||||
console.log( "Failed with error\n", error);
|
||||
}
|
||||
|
||||
try{
|
||||
await github.rest.git.deleteRef({
|
||||
...context.repo,
|
||||
ref: "tags/nightly"
|
||||
});
|
||||
console.log( "Deletion of tag successful")
|
||||
}catch(error){
|
||||
console.log( "Deletion of tag failed");
|
||||
console.log( "Failed with error\n", error);
|
||||
}
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
- name: List downloaded files
|
||||
run: tree -L 3
|
||||
|
||||
- uses: softprops/action-gh-release@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
# needs newer relase, but add it once available
|
||||
#fail_on_unmatched_files: true
|
||||
body: ${{ env.BODY }}
|
||||
prerelease: ${{ env.TAG_NAME == 'nightly' }}
|
||||
tag_name: ${{ env.TAG_NAME }}
|
||||
files: |
|
||||
./exiv2-linux64/exiv2-*
|
||||
./exiv2-macos/exiv2-*
|
||||
./exiv2-win/exiv2-*
|
@ -0,0 +1,99 @@
|
||||
# all builds use the same ccache folder in the project root that is cached
|
||||
variables:
|
||||
CCACHE_BASEDIR: '$CI_PROJECT_DIR'
|
||||
CCACHE_DIR: '$CI_PROJECT_DIR/ccache'
|
||||
|
||||
# default config for all distros:
|
||||
# - install dependencies via script
|
||||
# - create ccache dir & setup caching of it (for each job separately)
|
||||
.build_config: &default_config
|
||||
before_script:
|
||||
- ci/install_dependencies.sh
|
||||
- mkdir -p ccache
|
||||
cache:
|
||||
key: "$CI_JOB_NAME"
|
||||
paths:
|
||||
- ccache/
|
||||
|
||||
# default build job:
|
||||
# - run build script
|
||||
# - only create artifacts of the build directory when something fails
|
||||
# (for cmake logs)
|
||||
.build_template: &distro_build
|
||||
script:
|
||||
- python3 ci/test_build.py
|
||||
artifacts:
|
||||
when: on_failure
|
||||
paths:
|
||||
- build/
|
||||
|
||||
stages:
|
||||
- test
|
||||
- deploy
|
||||
|
||||
Fedora:
|
||||
image: fedora:latest
|
||||
<<: *default_config
|
||||
<<: *distro_build
|
||||
|
||||
Fedora_MinGW:
|
||||
image: fedora:latest
|
||||
before_script:
|
||||
- dnf -y upgrade
|
||||
- dnf -y install mingw64-gcc-c++ mingw64-filesystem mingw64-expat mingw64-zlib cmake make
|
||||
script:
|
||||
- python3 ci/test_build.py --without-tests --cmake-executable "mingw64-cmake" --cmake-options "-DEXIV2_TEAM_EXTRA_WARNINGS=ON -DEXIV2_ENABLE_VIDEO=ON -DEXIV2_ENABLE_WEBREADY=ON -DEXIV2_ENABLE_WIN_UNICODE=ON " --compilers --shared-libs OFF
|
||||
|
||||
Debian:
|
||||
image: debian:9
|
||||
<<: *default_config
|
||||
<<: *distro_build
|
||||
|
||||
Archlinux:
|
||||
image: archlinux/base
|
||||
<<: *default_config
|
||||
<<: *distro_build
|
||||
|
||||
Ubuntu:
|
||||
image: ubuntu:18.04
|
||||
<<: *default_config
|
||||
<<: *distro_build
|
||||
|
||||
CentOS:
|
||||
image: centos:7
|
||||
<<: *default_config
|
||||
<<: *distro_build
|
||||
|
||||
OpenSUSE:
|
||||
image: opensuse/tumbleweed
|
||||
<<: *default_config
|
||||
<<: *distro_build
|
||||
|
||||
Install:
|
||||
image: fedora:latest
|
||||
stage: deploy
|
||||
<<: *default_config
|
||||
script:
|
||||
- mkdir build && cd build
|
||||
- cmake -DCMAKE_BUILD_TYPE=Release -DEXIV2_ENABLE_VIDEO=ON -DEXIV2_ENABLE_WEBREADY=ON -DEXIV2_BUILD_UNIT_TESTS=ON -DCMAKE_INSTALL_PREFIX=/usr/ -DBUILD_WITH_CCACHE=ON ..
|
||||
- make -j $(nproc)
|
||||
- make install
|
||||
- make clean
|
||||
- EXIV2_BINDIR=/usr/bin/ make tests
|
||||
|
||||
pages:
|
||||
image: fedora:latest
|
||||
stage: deploy
|
||||
<<: *default_config
|
||||
script:
|
||||
- dnf -y install doxygen graphviz
|
||||
- mkdir build && cd build
|
||||
- cmake -DCMAKE_BUILD_TYPE=Release -DEXIV2_ENABLE_VIDEO=ON -DEXIV2_ENABLE_WEBREADY=ON -DEXIV2_BUILD_DOC=ON ..
|
||||
- make doc
|
||||
- cd ..
|
||||
- mv build/doc/html/ public/
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
- master
|
@ -1,23 +0,0 @@
|
||||
pull_request_rules:
|
||||
- name: forward patches to main branch
|
||||
conditions:
|
||||
- base=0.28.x
|
||||
- label=forward-to-main
|
||||
actions:
|
||||
backport:
|
||||
branches:
|
||||
- main
|
||||
assignees:
|
||||
- "{{ author }}"
|
||||
|
||||
- name: delete head branch after merge
|
||||
conditions:
|
||||
- merged
|
||||
actions:
|
||||
delete_head_branch: {}
|
||||
|
||||
- name: remove outdated reviews
|
||||
conditions: []
|
||||
actions:
|
||||
dismiss_reviews:
|
||||
changes_requested: False
|
@ -1 +0,0 @@
|
||||
//-V::1042
|
@ -0,0 +1,41 @@
|
||||
language: cpp
|
||||
|
||||
git:
|
||||
quiet: true
|
||||
depth: 1
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
dist: xenial
|
||||
sudo: required
|
||||
compiler: gcc
|
||||
env: COVERAGE=1 CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Debug -DEXIV2_ENABLE_VIDEO=ON -DEXIV2_ENABLE_WEBREADY=ON -DEXIV2_BUILD_UNIT_TESTS=ON -DBUILD_WITH_COVERAGE=ON -DEXIV2_ENABLE_CURL=ON -DCMAKE_CXX_STANDARD=98"
|
||||
|
||||
- os: linux
|
||||
dist: xenial
|
||||
sudo: required
|
||||
compiler: gcc
|
||||
env:
|
||||
- WITH_VALGRIND=1
|
||||
- CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DEXIV2_ENABLE_VIDEO=ON -DEXIV2_ENABLE_WEBREADY=ON -DEXIV2_BUILD_UNIT_TESTS=ON -DEXIV2_ENABLE_CURL=ON -DCMAKE_CXX_STANDARD=98"
|
||||
|
||||
- os: linux
|
||||
dist: xenial
|
||||
sudo: required
|
||||
compiler: clang
|
||||
env: CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DEXIV2_ENABLE_VIDEO=ON -DEXIV2_ENABLE_WEBREADY=ON -DEXIV2_BUILD_UNIT_TESTS=ON -DEXIV2_ENABLE_CURL=ON -DCMAKE_CXX_STANDARD=98"
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode11.3
|
||||
compiler: clang
|
||||
env: CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DEXIV2_ENABLE_VIDEO=ON -DEXIV2_ENABLE_WEBREADY=ON -DEXIV2_BUILD_UNIT_TESTS=ON -DEXIV2_ENABLE_NLS=OFF -DEXIV2_ENABLE_CURL=ON -DCMAKE_CXX_STANDARD=98"
|
||||
|
||||
install: ./ci/install.sh
|
||||
script: ./ci/run.sh
|
||||
|
||||
cache:
|
||||
ccache: true
|
||||
directories:
|
||||
- conan # Conan installation folder
|
||||
- $HOME/conanData # Conan storage location
|
@ -1,197 +1,152 @@
|
||||
# Minimum version imposed by Ubuntu:20.04
|
||||
cmake_minimum_required(VERSION 3.16.3)
|
||||
|
||||
# use TWEAK to categorize the build:
|
||||
#
|
||||
# * 1.00.0 = GM (tagged and released)
|
||||
# * 1.00.0.9 = 1.00.0 Development
|
||||
# * 1.00.0.00 = GM Preview
|
||||
# * 1.00.0.2 = RC2 (tagged and released)
|
||||
# * 1.00.0.20 = RC2 Preview
|
||||
# * 1.00.0.29 = RC2 Development
|
||||
#
|
||||
project(
|
||||
exiv2
|
||||
VERSION 1.00.0.9
|
||||
DESCRIPTION "Exif/IPTC/Xmp C++ metadata library and tools plus ICC Profiles, Previews and more."
|
||||
LANGUAGES C CXX
|
||||
cmake_minimum_required( VERSION 3.3.2 )
|
||||
|
||||
project(exiv2 # use TWEAK to categorize the build
|
||||
VERSION 0.27.3 # 0.27.3 = GM
|
||||
# 0.27.3.00 = GM Preview
|
||||
# 0.27.3.09 = Not For Release
|
||||
# 0.27.3.2 = RC2
|
||||
# 0.27.3.20 = RC2 Preview
|
||||
# 0.27.3.29 = RC2 Not for release
|
||||
LANGUAGES CXX C
|
||||
)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
|
||||
# Shared Object versioning (SemVer-like: must bump major on API breakage)
|
||||
if(PROJECT_VERSION_MAJOR EQUAL 0)
|
||||
# support legacy scheme (e.g. 0.27.x -> 27)
|
||||
set(EXIV2LIB_SOVERSION ${PROJECT_VERSION_MINOR})
|
||||
else()
|
||||
# restart from 30
|
||||
math(EXPR EXIV2LIB_SOVERSION "30 + (${PROJECT_VERSION_MAJOR} - 1)")
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
include(cmake/mainSetup.cmake REQUIRED)
|
||||
|
||||
include(cmake/mainSetup.cmake)
|
||||
|
||||
# options and their default values
|
||||
option(BUILD_SHARED_LIBS "Build exiv2lib as a shared library" ON)
|
||||
option(EXIV2_ENABLE_XMP "Build with XMP metadata support" ON)
|
||||
option(EXIV2_ENABLE_EXTERNAL_XMP "Use external version of XMP" OFF)
|
||||
option(EXIV2_ENABLE_PNG "Build with PNG support (requires zlib)" ON)
|
||||
option(EXIV2_ENABLE_NLS "Build native language support (requires gettext)" OFF)
|
||||
option(EXIV2_ENABLE_LENSDATA "Build including Nikon lens data" ON)
|
||||
option(EXIV2_ENABLE_DYNAMIC_RUNTIME "Use dynamic runtime (used for static libs)" ON)
|
||||
option(EXIV2_ENABLE_WEBREADY "Build webready support into library" OFF)
|
||||
option(EXIV2_ENABLE_CURL "Use libcurl for HttpIo (WEBREADY)" OFF)
|
||||
option(EXIV2_ENABLE_BMFF "Build with BMFF support" ON)
|
||||
option(EXIV2_ENABLE_BROTLI "Use Brotli for JPEG XL compressed boxes (BMFF)" ON)
|
||||
option(EXIV2_ENABLE_VIDEO "Build with video support" ON)
|
||||
option(EXIV2_ENABLE_INIH "Use inih library" ON)
|
||||
option(EXIV2_ENABLE_FILESYSTEM_ACCESS "Build with filesystem access" ON)
|
||||
|
||||
option(EXIV2_BUILD_SAMPLES "Build sample applications" OFF)
|
||||
option(EXIV2_BUILD_EXIV2_COMMAND "Build exiv2 command-line executable" ON)
|
||||
option(EXIV2_BUILD_UNIT_TESTS "Build unit tests" OFF)
|
||||
option(EXIV2_BUILD_FUZZ_TESTS "Build fuzz tests (libFuzzer)" OFF)
|
||||
option(EXIV2_BUILD_DOC "Add 'doc' target to generate documentation" OFF)
|
||||
option( BUILD_SHARED_LIBS "Build exiv2lib as a shared library" ON )
|
||||
option( EXIV2_ENABLE_XMP "Build with XMP metadata support" ON )
|
||||
option( EXIV2_ENABLE_EXTERNAL_XMP "Use external version of XMP" OFF )
|
||||
option( EXIV2_ENABLE_PNG "Build with png support (requires libz)" ON )
|
||||
option( EXIV2_ENABLE_NLS "Build native language support (requires gettext)" OFF )
|
||||
option( EXIV2_ENABLE_PRINTUCS2 "Build with Printucs2" ON )
|
||||
option( EXIV2_ENABLE_LENSDATA "Build including lens data" ON )
|
||||
option( EXIV2_ENABLE_VIDEO "Build video support into library" OFF )
|
||||
option( EXIV2_ENABLE_DYNAMIC_RUNTIME "Use dynamic runtime (used for static libs)" ON )
|
||||
option( EXIV2_ENABLE_WIN_UNICODE "Use Unicode paths (wstring) on Windows" OFF )
|
||||
option( EXIV2_ENABLE_WEBREADY "Build webready support into library" OFF )
|
||||
option( EXIV2_ENABLE_CURL "USE Libcurl for HttpIo (WEBREADY)" OFF )
|
||||
option( EXIV2_ENABLE_SSH "USE Libssh for SshIo (WEBREADY)" OFF )
|
||||
|
||||
option( EXIV2_BUILD_SAMPLES "Build sample applications" ON )
|
||||
option( EXIV2_BUILD_EXIV2_COMMAND "Build exiv2 command-line executable" ON )
|
||||
option( EXIV2_BUILD_UNIT_TESTS "Build unit tests" OFF )
|
||||
option( EXIV2_BUILD_DOC "Add 'doc' target to generate documentation" OFF )
|
||||
|
||||
# Only intended to be used by Exiv2 developers/contributors
|
||||
option(EXIV2_TEAM_EXTRA_WARNINGS "Add more sanity checks using compiler flags" OFF)
|
||||
option(EXIV2_TEAM_WARNINGS_AS_ERRORS "Treat warnings as errors" OFF)
|
||||
option(EXIV2_TEAM_USE_SANITIZERS "Enable ASAN and UBSAN when available" OFF)
|
||||
|
||||
# The EXIV2_TEAM_OSS_FUZZ option is used by the OSS-Fuzz build script:
|
||||
#
|
||||
# * https://github.com/google/oss-fuzz/tree/master/projects/exiv2/build.sh
|
||||
#
|
||||
option(EXIV2_TEAM_OSS_FUZZ "Build config for OSS-Fuzz" OFF)
|
||||
|
||||
option(EXIV2_TEAM_PACKAGING "Additional stuff for generating packages" OFF)
|
||||
option( EXIV2_TEAM_EXTRA_WARNINGS "Add more sanity checks using compiler flags" OFF )
|
||||
option( EXIV2_TEAM_WARNINGS_AS_ERRORS "Treat warnings as errors" OFF )
|
||||
option( EXIV2_TEAM_USE_SANITIZERS "Enable ASAN and UBSAN when available" OFF )
|
||||
option( EXIV2_TEAM_PACKAGING "Additional stuff for generating packages" OFF )
|
||||
set(EXTRA_COMPILE_FLAGS " ")
|
||||
|
||||
mark_as_advanced(EXIV2_TEAM_EXTRA_WARNINGS EXIV2_TEAM_WARNINGS_AS_ERRORS EXIV2_ENABLE_EXTERNAL_XMP EXTRA_COMPILE_FLAGS EXIV2_TEAM_USE_SANITIZERS)
|
||||
mark_as_advanced(
|
||||
EXIV2_TEAM_EXTRA_WARNINGS
|
||||
EXIV2_TEAM_WARNINGS_AS_ERRORS
|
||||
EXIV2_ENABLE_EXTERNAL_XMP
|
||||
EXTRA_COMPILE_FLAGS
|
||||
EXIV2_TEAM_USE_SANITIZERS
|
||||
)
|
||||
|
||||
option(BUILD_WITH_STACK_PROTECTOR "Build with stack protector" ON)
|
||||
option(BUILD_WITH_CCACHE "Use ccache to speed up compilations" OFF)
|
||||
option(BUILD_WITH_COVERAGE "Add compiler flags to generate coverage stats" OFF)
|
||||
include(cmake/gcovr.cmake REQUIRED)
|
||||
option( BUILD_WITH_CCACHE "Use ccache to speed up compilations" OFF )
|
||||
option( BUILD_WITH_COVERAGE "Add compiler flags to generate coverage stats" OFF )
|
||||
|
||||
set(PACKAGE_URL "https://exiv2.org")
|
||||
set( PACKAGE_BUGREPORT "http://github.com/exiv2/exiv2" )
|
||||
set( PACKAGE_URL "http://exiv2.dyndns.org")
|
||||
set( PROJECT_DESCRIPTION "Exif and IPTC metadata library and tools")
|
||||
|
||||
if(EXIV2_ENABLE_EXTERNAL_XMP)
|
||||
set(EXIV2_ENABLE_XMP OFF)
|
||||
if ( EXIV2_ENABLE_EXTERNAL_XMP )
|
||||
set(EXIV2_ENABLE_XMP OFF)
|
||||
endif()
|
||||
|
||||
include(cmake/findDependencies.cmake REQUIRED)
|
||||
include(cmake/compilerFlags.cmake REQUIRED)
|
||||
if( EXIV2_BUILD_UNIT_TESTS )
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) # Requires CMake 3.3.3
|
||||
endif()
|
||||
|
||||
include(cmake/findDependencies.cmake REQUIRED)
|
||||
include(cmake/compilerFlags.cmake REQUIRED)
|
||||
include(cmake/generateConfigFile.cmake REQUIRED)
|
||||
|
||||
if(EXIV2_BUILD_DOC)
|
||||
include(cmake/generateDoc.cmake REQUIRED)
|
||||
generate_documentation("${PROJECT_SOURCE_DIR}/cmake/Doxyfile.in")
|
||||
if (EXIV2_BUILD_DOC)
|
||||
include(cmake/generateDoc.cmake REQUIRED)
|
||||
generate_documentation("${PROJECT_SOURCE_DIR}/cmake/Doxyfile.in")
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_BINARY_DIR}) # Make the exv_conf.h file visible for the full project
|
||||
|
||||
if(EXIV2_ENABLE_XMP)
|
||||
add_subdirectory(xmpsdk)
|
||||
include_directories(${CMAKE_BINARY_DIR}) # Make the exv_conf.h file visible for the full project
|
||||
|
||||
if( EXIV2_ENABLE_XMP )
|
||||
add_subdirectory( xmpsdk )
|
||||
endif()
|
||||
|
||||
include(cmake/compilerFlagsExiv2.cmake REQUIRED)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
if(BUILD_TESTING AND EXIV2_BUILD_UNIT_TESTS)
|
||||
set(EXIV2_ENABLE_FILESYSTEM_ACCESS ON)
|
||||
add_subdirectory(unitTests)
|
||||
endif()
|
||||
add_subdirectory( include )
|
||||
add_subdirectory( src )
|
||||
|
||||
if(EXIV2_BUILD_FUZZ_TESTS)
|
||||
set(EXIV2_ENABLE_FILESYSTEM_ACCESS ON)
|
||||
add_subdirectory(fuzz)
|
||||
if( EXIV2_BUILD_UNIT_TESTS )
|
||||
add_subdirectory ( unitTests )
|
||||
add_custom_target(unit_test
|
||||
COMMAND env EXIV2_BINDIR="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" make unit_test
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/test"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(EXIV2_BUILD_EXIV2_COMMAND)
|
||||
add_subdirectory(app)
|
||||
set(EXIV2_ENABLE_FILESYSTEM_ACCESS ON)
|
||||
|
||||
if(EXIV2_BUILD_SAMPLES)
|
||||
add_subdirectory(samples)
|
||||
set(EXIV2_ENABLE_FILESYSTEM_ACCESS ON)
|
||||
get_directory_property(SAMPLES DIRECTORY samples DEFINITION APPLICATIONS)
|
||||
add_custom_target(version_test
|
||||
COMMAND env EXIV2_BINDIR="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" make version_test
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/test"
|
||||
)
|
||||
|
||||
if(BUILD_TESTING AND Python3_Interpreter_FOUND)
|
||||
add_test(
|
||||
NAME bashTests
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
|
||||
COMMAND cmake -E env EXIV2_BINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${Python3_EXECUTABLE} runner.py --verbose bash_tests
|
||||
)
|
||||
if( EXIV2_BUILD_SAMPLES )
|
||||
##
|
||||
# tests
|
||||
if( EXIV2_BUILD_UNIT_TESTS )
|
||||
add_custom_target(tests
|
||||
COMMAND env EXIV2_BINDIR="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" make unit_test
|
||||
COMMAND env EXIV2_BINDIR="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" make bash_tests
|
||||
COMMAND env EXIV2_BINDIR="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" make python_tests
|
||||
COMMAND env EXIV2_BINDIR="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" make version_test
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/test"
|
||||
)
|
||||
else()
|
||||
add_custom_target(tests
|
||||
COMMAND env EXIV2_BINDIR="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" make bash_tests
|
||||
COMMAND env EXIV2_BINDIR="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" make python_tests
|
||||
COMMAND env EXIV2_BINDIR="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" make version_test
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/test"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING AND Python3_Interpreter_FOUND)
|
||||
add_test(
|
||||
NAME bugfixTests
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
|
||||
COMMAND cmake -E env EXIV2_BINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${Python3_EXECUTABLE} runner.py --verbose bugfixes
|
||||
)
|
||||
add_test(
|
||||
NAME lensTests
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
|
||||
COMMAND cmake -E env EXIV2_BINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${Python3_EXECUTABLE} runner.py --verbose lens_tests
|
||||
)
|
||||
# Repeat lens test with a DE locale that uses "," as float delimiter
|
||||
# to check that all float conversions are done independently of locale
|
||||
# See GitHub issue #2746
|
||||
add_test(
|
||||
NAME lensTestsLocaleDE
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
|
||||
COMMAND cmake -E env LC_ALL=de_DE.UTF-8 EXIV2_BINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${Python3_EXECUTABLE} runner.py --verbose lens_tests
|
||||
)
|
||||
add_test(
|
||||
NAME tiffTests
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
|
||||
COMMAND cmake -E env EXIV2_BINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${Python3_EXECUTABLE} runner.py --verbose tiff_test
|
||||
)
|
||||
add_test(
|
||||
NAME versionTests
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
|
||||
COMMAND cmake -E env EXIV2_BINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${Python3_EXECUTABLE} runner.py --verbose bash_tests/version_test.py
|
||||
)
|
||||
add_test(
|
||||
NAME regressionTests
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
|
||||
COMMAND cmake -E env EXIV2_BINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${Python3_EXECUTABLE} runner.py --verbose regression_tests
|
||||
)
|
||||
endif()
|
||||
add_custom_target(python_tests
|
||||
COMMAND env EXIV2_BINDIR="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" make python_tests
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/test"
|
||||
)
|
||||
add_custom_target(bash_tests
|
||||
COMMAND env EXIV2_BINDIR="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" make bash_tests
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/test"
|
||||
)
|
||||
add_subdirectory( samples )
|
||||
get_directory_property(SAMPLES DIRECTORY samples DEFINITION APPLICATIONS)
|
||||
add_dependencies(tests exiv2lib exiv2 ${SAMPLES})
|
||||
endif()
|
||||
|
||||
if(EXIV2_ENABLE_NLS)
|
||||
add_subdirectory(po)
|
||||
if( EXIV2_ENABLE_NLS )
|
||||
add_subdirectory( po )
|
||||
endif()
|
||||
|
||||
if(EXIV2_TEAM_PACKAGING)
|
||||
include(cmake/packaging.cmake)
|
||||
if (EXIV2_TEAM_PACKAGING)
|
||||
include(cmake/packaging.cmake)
|
||||
endif()
|
||||
|
||||
# Handle both relative and absolute paths (e.g. NixOS) for a relocatable package
|
||||
if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}")
|
||||
set(EXIV2_LIBDIR "${CMAKE_INSTALL_LIBDIR}")
|
||||
else()
|
||||
join_paths(EXIV2_LIBDIR "\${exec_prefix}" "${CMAKE_INSTALL_LIBDIR}")
|
||||
endif()
|
||||
if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
set(EXIV2_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
else()
|
||||
join_paths(EXIV2_INCLUDEDIR "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
endif()
|
||||
configure_file(cmake/exiv2.pc.in exiv2.pc @ONLY)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/exiv2.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
|
||||
# ******************************************************************************
|
||||
# Man page
|
||||
install(FILES ${PROJECT_SOURCE_DIR}/man/man1/exiv2.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
|
||||
install( FILES ${PROJECT_SOURCE_DIR}/man/man1/exiv2.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 )
|
||||
|
||||
|
||||
include(cmake/printSummary.cmake)
|
||||
|
||||
# That's all Folks!
|
||||
#
|
||||
##
|
||||
|
@ -1,151 +0,0 @@
|
||||
{
|
||||
"version": 3,
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "base_ninja",
|
||||
"description": "Base preset to use ninja as generator",
|
||||
"hidden": true,
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build-${presetName}",
|
||||
"installDir": "${sourceDir}/build-${presetName}/install",
|
||||
"cacheVariables": {
|
||||
"BUILD_SHARED_LIBS": true,
|
||||
"CONAN_AUTO_INSTALL": true,
|
||||
"EXIV2_BUILD_SAMPLES": true,
|
||||
"EXIV2_ENABLE_WEBREADY": true,
|
||||
"EXIV2_ENABLE_CURL": true,
|
||||
"EXIV2_ENABLE_PNG": true,
|
||||
"EXIV2_ENABLE_BMFF": true,
|
||||
"EXIV2_BUILD_UNIT_TESTS": true,
|
||||
"EXIV2_TEAM_WARNINGS_AS_ERRORS": true,
|
||||
"EXIV2_ENABLE_NLS": false,
|
||||
"EXIV2_ENABLE_VIDEO": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "base_windows",
|
||||
"description": "Base preset for Windows (specially useful for CI jobs)",
|
||||
"displayName": "Base preset for Windows (specially useful for CI jobs)",
|
||||
"inherits": "base_ninja",
|
||||
"condition": {
|
||||
"type": "matches",
|
||||
"string": "${hostSystemName}",
|
||||
"regex": "Windows|CYGWIN.*|MSYS.*"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "base_linux",
|
||||
"description": "Base preset for Linux",
|
||||
"displayName": "Base preset for Linux with default compiler: GCC (specially useful for CI jobs)",
|
||||
"inherits": "base_ninja",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Linux"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"BUILD_WITH_CCACHE": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "base_mac",
|
||||
"description": "Base preset for macOS (no conan usage)",
|
||||
"displayName": "Base preset for macOS with default compiler: AppleClang (specially useful for CI jobs)",
|
||||
"inherits": "base_ninja",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Darwin"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release",
|
||||
"CONAN_AUTO_INSTALL": false
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"name": "msvc",
|
||||
"displayName": "Visual Studio cl toolchain (also usable from VS Code)",
|
||||
"inherits": "base_windows",
|
||||
"architecture": {
|
||||
"value": "x64",
|
||||
"strategy": "external"
|
||||
},
|
||||
"toolset": {
|
||||
"value": "host=x64",
|
||||
"strategy": "external"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "cl.exe",
|
||||
"CMAKE_CXX_COMPILER": "cl.exe",
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "win-debug",
|
||||
"displayName": "Windows Debug with configured architecture",
|
||||
"description": "Sets Debug build type with the preloaded Visual Studio Environment",
|
||||
"inherits": "base_windows",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "win-release",
|
||||
"displayName": "Windows Release with configured architecture",
|
||||
"description": "Sets Release build type with the preloaded Visual Studio Environment",
|
||||
"inherits": "base_windows",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-debug",
|
||||
"displayName": "Linux Debug (Ninja Generator) with default architecture",
|
||||
"inherits": "base_linux",
|
||||
"cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" }
|
||||
},
|
||||
{
|
||||
"name": "linux-release",
|
||||
"displayName": "Linux Release (Ninja Generator) with default architecture",
|
||||
"inherits": "base_linux",
|
||||
"cacheVariables": { "CMAKE_BUILD_TYPE": "Release" }
|
||||
},
|
||||
{
|
||||
"name": "linux-debug-NoConan",
|
||||
"displayName": "Same as linux-debug but without automatic conan execution",
|
||||
"inherits": "linux-debug",
|
||||
"cacheVariables": { "CONAN_AUTO_INSTALL": false }
|
||||
},
|
||||
{
|
||||
"name": "linux-release-NoConan",
|
||||
"displayName": "Same as linux-release but without automatic conan execution",
|
||||
"inherits": "linux-release",
|
||||
"cacheVariables": { "CONAN_AUTO_INSTALL": false }
|
||||
},
|
||||
{
|
||||
"name": "linux-coverage",
|
||||
"displayName": "Same as linux-debug-NoConan with coverage enabled",
|
||||
"inherits": "linux-debug-NoConan",
|
||||
"cacheVariables": { "BUILD_WITH_COVERAGE": true }
|
||||
},
|
||||
{
|
||||
"name": "linux-sanitizers",
|
||||
"displayName": "Same as linux-debug-NoConan with sanitizers enabled",
|
||||
"inherits": "linux-debug-NoConan",
|
||||
"cacheVariables": { "EXIV2_TEAM_USE_SANITIZERS": true }
|
||||
},
|
||||
{
|
||||
"name": "linux-all",
|
||||
"displayName": "Same as linux-release-NoConan and with rest of things enabled (doc + NLS)",
|
||||
"description": "requires installation of packages: doxygen graphviz gettext",
|
||||
"inherits": "linux-release-NoConan",
|
||||
"cacheVariables": {
|
||||
"EXIV2_ENABLE_NLS": true,
|
||||
"EXIV2_ENABLE_VIDEO": false,
|
||||
"EXIV2_BUILD_DOC": true
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
This program is part of the Exiv2 distribution.
|
||||
Copyright (C) 2004-2022 Exiv2 authors
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
Note:
|
||||
Individual files contain the following tag instead of the full license text.
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
This enables machine processing of license information based on the SPDX
|
||||
License Identifiers that are here available: http://spdx.org/licenses/
|
@ -1,10 +0,0 @@
|
||||
meson build system
|
||||
|
||||
This is a basic meson.build file intended to be used by meson projects that use
|
||||
WrapDB: https://github.com/mesonbuild/wrapdb
|
||||
|
||||
This can also be used as a test playground to test various options not exposed
|
||||
by the CMake build, eg: iconv and intl on Windows.
|
||||
|
||||
It is currently incomplete. Tests are not implemented yet. The library and
|
||||
executable are.
|
@ -1,59 +0,0 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
| Exiv2 Version | Date | Tag | Branch | _Dot/Security_ Release | Date | Tag |
|
||||
|:-- |:-- |:- |:-- |:-- |:- |:- |
|
||||
| v0.28 | 2023-05-08 | v0.28.0 | 0.28.x | v0.28.0 | 2023-05-08 | v0.28.0 |
|
||||
| | | | | v0.28.1 | 2023-11-06 | v0.28.1 |
|
||||
| | | | | v0.28.2 | 2024-02-13 | v0.28.2 |
|
||||
| | | | | v0.28.3 | 2024-07-08 | v0.28.3 |
|
||||
| v0.27 | 2018-12-20 | 0.27 | 0.27-maintenance | v0.27.0 | 2018-12-20 | v0.27.0 |
|
||||
| | | | | v0.27.1 | 2019-04-18 | v0.27.1 |
|
||||
| | | | | v0.27.2 | 2019-07-29 | v0.27.2 |
|
||||
| | | | | v0.27.3 | 2020-06-30 | v0.27.3 |
|
||||
| | | | | v0.27.4 | 2021-06-15 | v0.27.4 |
|
||||
| | | | | v0.27.5 | 2021-09-30 | v0.27.5 |
|
||||
| | | | | v0.27.6 | 2023-01-18 | v0.27.6 |
|
||||
| | | | | v0.27.7 | 2023-05-14 | v0.27.7 |
|
||||
| v0.26 | 2017-04-28 | v0.26 | 0.26 | None | | |
|
||||
| v0.25 | 2015-06-21 | _None_ | 0.25 | None | | |
|
||||
|
||||
## Security Process
|
||||
|
||||
If you have found a security vulnerability in Exiv2, please follow these steps:
|
||||
|
||||
* Click [this link](https://github.com/Exiv2/exiv2/security/advisories/new) to create a draft security advisory.
|
||||
* Write a detailed description of the vulnerability in the draft advisory.
|
||||
* Include all of the following details in your description of the vulnerability:
|
||||
* Exact version of Exiv2 that you tested. _For example: commit [194bb65ac568a5435874c9d9d73b1c8a68e4edec](https://github.com/Exiv2/exiv2/commit/194bb65ac568a5435874c9d9d73b1c8a68e4edec)_
|
||||
* Platform used. _For example: Ubuntu 22.04.3 LTS (x86\_64)_
|
||||
* Exact command used to build Exiv2. _For example: `mkdir build; cd build; cmake ..; make`_
|
||||
* Attach a copy of the image file that triggers the bug. _For example: `poc.jpg`_
|
||||
* Exact command line arguments that trigger the bug. _For example: `./bin/exiv2 poc.jpg`_
|
||||
* Crash output (stdout + stderr).
|
||||
* The source location of the bug and/or any other information that you are able to provide about what the cause of the bug is.
|
||||
|
||||
The draft security advisory is private until we publish it, so it is a good place to discuss the details of the vulnerability privately.
|
||||
|
||||
To qualify as a security issue, the bug **must** be reproducible on an official release of Exiv2, via a realistic attack vector. As a general rule, that means it should be possible to trigger the bug by running the `exiv2` command-line application on a malicious input file. Please note that the applications in the `samples` sub-directory are demo applications that are not intended for production use, so we usually do not consider bugs in those applications to be security vulnerabilities. However, if one of the sample applications reveals a legitimate bug in the exiv2 library then we will still consider it as a potential security issue.
|
||||
|
||||
Official releases are listed [here](https://github.com/Exiv2/exiv2/releases) (not including those labeled "pre-release"). Bugs that are only reproducible on the [main branch](https://github.com/Exiv2/exiv2/tree/main) or on a pre-release are not security issues and can be reported as regular [issues](https://github.com/Exiv2/exiv2/issues).
|
||||
|
||||
Team Exiv2 does not back-port security (or any other fix) to earlier releases of the code. An engineer at SUSE has patched and fixed some security releases for Exiv2 v0.26 and Exiv2 v0.25 in branches 0.26 and 0.25. Exiv2 has provided several _**Dot Release**_ for v0.27. Exiv2 has never issued a _**Security Release**_.
|
||||
|
||||
The version numbering scheme is explained below. The design includes provision for a security release. A _**Dot Release**_ is an updated version of the library with security PRs and other changes. A _**Dot Release**_ offers the same API as its parent. A _**Security Release**_ is an existing release PLUS one or more security PRs. Nothing else is changed from it parent.
|
||||
|
||||
Users can register on GitHub.com to receive release notices for RC and GM Releases. Additionally, we inform users when we begin a project to create a new release on FaceBook (https://facebook.com/exiv2) and Discuss Pixls (https://discuss.pixls.us). The announcement of a new release project has a preliminary specification and schedule.
|
||||
|
||||
## Version Numbering Scheme
|
||||
|
||||
| Version | Name | Status | Purpose |
|
||||
|:-- |:-- |:-- |:-- |
|
||||
| v0.27.7.3 | Exiv2 v0.27.3 | GM | Golden Master. This is the final and official release. |
|
||||
| v0.27.3.2 | Exiv2 v0.27.3.2 | RC2 | Release Candidate 2. |
|
||||
| v0.27.3.20 | Exiv2 v0.27.3.2 | RC2 Preview | Dry-run for release candidate. For team review. |
|
||||
| v0.27.3.81 | Exiv2 v0.27.3 | Security Fix | Security Release |
|
||||
| v0.27.3.29 | Exiv2 v0.27.3.29 | Development | Should never be installed for production. |
|
||||
| v0.27.4.9 | Exiv2 v0.27.4.9 | Development | Should never be installed for production. |
|
||||
| v0.27.99 | Exiv2 v0.28 | Development | Should never be installed for production. |
|
@ -1,65 +0,0 @@
|
||||
set(APP_SOURCES
|
||||
exiv2.cpp
|
||||
exiv2app.hpp
|
||||
actions.cpp
|
||||
actions.hpp
|
||||
getopt.cpp
|
||||
getopt.hpp
|
||||
app_utils.cpp
|
||||
app_utils.hpp
|
||||
)
|
||||
|
||||
add_executable(exiv2 ${APP_SOURCES})
|
||||
|
||||
target_include_directories(exiv2 PRIVATE ${PROJECT_SOURCE_DIR}/src) # To find i18n.hpp
|
||||
|
||||
set_target_properties(exiv2 PROPERTIES COMPILE_FLAGS ${EXTRA_COMPILE_FLAGS} XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Debug] "YES")
|
||||
if(MSVC)
|
||||
set_target_properties(exiv2 PROPERTIES LINK_FLAGS "/ignore:4099") # Ignore missing PDBs
|
||||
endif()
|
||||
|
||||
target_link_libraries(exiv2 PRIVATE exiv2lib)
|
||||
|
||||
if(EXIV2_ENABLE_NLS)
|
||||
target_link_libraries(exiv2 PRIVATE ${Intl_LIBRARIES})
|
||||
target_include_directories(exiv2 PRIVATE ${Intl_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
target_link_libraries(exiv2 PRIVATE std::filesystem)
|
||||
|
||||
if(MSVC OR MINGW)
|
||||
# Trick to get properly UTF-8 encoded argv.
|
||||
|
||||
# More info at: https://github.com/huangqinjin/wmain
|
||||
add_library(wmain STATIC wmain.cpp)
|
||||
target_link_libraries(exiv2 PRIVATE wmain)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
target_link_options(wmain INTERFACE /WHOLEARCHIVE:$<TARGET_FILE:wmain>)
|
||||
target_link_options(exiv2 PRIVATE "/ENTRY:wWinMainCRTStartup")
|
||||
endif()
|
||||
|
||||
if(MINGW)
|
||||
target_compile_options(exiv2 PRIVATE -municode)
|
||||
target_link_options(exiv2 PRIVATE -municode)
|
||||
endif()
|
||||
|
||||
if(USING_CONAN
|
||||
AND WIN32
|
||||
AND EXISTS ${PROJECT_BINARY_DIR}/conanDlls
|
||||
)
|
||||
# In case of using conan recipes with their 'shared' option turned on, we will have dlls of the 3rd party dependencies in the conanDlls folder.
|
||||
|
||||
add_custom_command(
|
||||
TARGET exiv2
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_BINARY_DIR}/conanDlls ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
|
||||
COMMENT "Copy 3rd party DLLs the bin folder"
|
||||
)
|
||||
|
||||
# Copy 3rd party DLLs the bin folder. [install step]
|
||||
install(DIRECTORY ${PROJECT_BINARY_DIR}/conanDlls/ DESTINATION bin)
|
||||
endif()
|
||||
|
||||
install(TARGETS exiv2 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
File diff suppressed because it is too large
Load Diff
@ -1,326 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
/*!
|
||||
@file actions.hpp
|
||||
@brief Implements base class Task, TaskFactory and the various supported
|
||||
actions (derived from Task).
|
||||
@author Andreas Huggel (ahu)
|
||||
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
|
||||
@date 11-Dec-03, ahu: created
|
||||
*/
|
||||
#ifndef ACTIONS_HPP_
|
||||
#define ACTIONS_HPP_
|
||||
|
||||
// *****************************************************************************
|
||||
#include <unordered_map>
|
||||
#include "exiv2app.hpp"
|
||||
|
||||
// *****************************************************************************
|
||||
// class declarations
|
||||
|
||||
namespace Exiv2 {
|
||||
class ExifData;
|
||||
class Image;
|
||||
class Metadatum;
|
||||
class PreviewImage;
|
||||
} // namespace Exiv2
|
||||
|
||||
// *****************************************************************************
|
||||
// namespace extensions
|
||||
/// @brief Contains all action classes (task subclasses).
|
||||
namespace Action {
|
||||
//! Enumerates all tasks
|
||||
enum TaskType {
|
||||
none,
|
||||
adjust,
|
||||
print,
|
||||
rename,
|
||||
erase,
|
||||
extract,
|
||||
insert,
|
||||
modify,
|
||||
fixiso,
|
||||
fixcom,
|
||||
};
|
||||
|
||||
// *****************************************************************************
|
||||
// class definitions
|
||||
|
||||
/*!
|
||||
@brief Abstract base class for all concrete actions.
|
||||
|
||||
Task provides a simple interface that actions must implement and a few
|
||||
commonly used helpers.
|
||||
*/
|
||||
class Task {
|
||||
public:
|
||||
//! Shortcut for an auto pointer.
|
||||
using UniquePtr = std::unique_ptr<Task>;
|
||||
//! Virtual destructor.
|
||||
virtual ~Task() = default;
|
||||
|
||||
Task() = default;
|
||||
Task(const Task&) = default;
|
||||
Task& operator=(const Task&) = default;
|
||||
|
||||
//! Virtual copy construction.
|
||||
[[nodiscard]] virtual UniquePtr clone() const = 0;
|
||||
|
||||
/// @brief Application interface to perform a task.
|
||||
/// @param path Path of the file to process.
|
||||
/// @return 0 if successful.
|
||||
virtual int run(const std::string& path) = 0;
|
||||
|
||||
bool setBinary(bool b) {
|
||||
bool bResult = binary_;
|
||||
binary_ = b;
|
||||
return bResult;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool binary() const {
|
||||
return binary_;
|
||||
}
|
||||
|
||||
private:
|
||||
//! copy binary_ from command-line params to task
|
||||
bool binary_{false};
|
||||
}; // class Task
|
||||
|
||||
/*!
|
||||
@brief Task factory.
|
||||
|
||||
Creates an instance of the task of the requested type. The factory is
|
||||
implemented as a singleton, which can be accessed only through the static
|
||||
member function instance().
|
||||
*/
|
||||
class TaskFactory {
|
||||
public:
|
||||
/*!
|
||||
@brief Get access to the task factory.
|
||||
Clients access the task factory exclusively through this method. (SINGLETON)
|
||||
*/
|
||||
static TaskFactory& instance();
|
||||
|
||||
~TaskFactory() = default;
|
||||
//! Prevent copy construction: not implemented.
|
||||
TaskFactory(const TaskFactory&) = delete;
|
||||
TaskFactory& operator=(const TaskFactory&) = delete;
|
||||
|
||||
//! Destructor
|
||||
void cleanup();
|
||||
|
||||
/*!
|
||||
@brief Create a task.
|
||||
|
||||
@param type Identifies the type of task to create.
|
||||
@return An auto pointer that owns a task of the requested type. If
|
||||
the task type is not supported, the pointer is 0.
|
||||
@remark The caller of the function should check the content of the
|
||||
returned auto pointer and take appropriate action (e.g., throw
|
||||
an exception) if it is 0.
|
||||
*/
|
||||
Task::UniquePtr create(TaskType type);
|
||||
|
||||
private:
|
||||
//! Prevent construction other than through instance().
|
||||
TaskFactory();
|
||||
|
||||
//! List of task types and corresponding prototypes.
|
||||
std::unordered_map<TaskType, Task::UniquePtr> registry_;
|
||||
};
|
||||
|
||||
//! %Print the Exif (or other metadata) of a file to stdout
|
||||
class Print : public Task {
|
||||
public:
|
||||
int run(const std::string& path) override;
|
||||
[[nodiscard]] Task::UniquePtr clone() const override;
|
||||
|
||||
//! Print the Jpeg comment
|
||||
int printComment();
|
||||
//! Print list of available preview images
|
||||
int printPreviewList();
|
||||
//! Print Exif summary information
|
||||
int printSummary();
|
||||
//! Print Exif, IPTC and XMP metadata in user defined format
|
||||
int printList();
|
||||
//! Return true if key should be printed, else false
|
||||
static bool grepTag(const std::string& key);
|
||||
//! Return true if key should be printed, else false
|
||||
static bool keyTag(const std::string& key);
|
||||
//! Print all metadata in a user defined format
|
||||
int printMetadata(const Exiv2::Image* image);
|
||||
//! Print a metadatum in a user defined format, return true if something was printed
|
||||
bool printMetadatum(const Exiv2::Metadatum& md, const Exiv2::Image* image);
|
||||
//! Print the label for a summary line
|
||||
void printLabel(const std::string& label) const;
|
||||
/*!
|
||||
@brief Print one summary line with a label (if provided) and requested
|
||||
data. A line break is printed only if a label is provided.
|
||||
@return 1 if a line was written, 0 if the key was not found.
|
||||
*/
|
||||
int printTag(const Exiv2::ExifData& exifData, const std::string& key, const std::string& label = "") const;
|
||||
//! Type for an Exiv2 Easy access function
|
||||
using EasyAccessFct = Exiv2::ExifData::const_iterator (*)(const Exiv2::ExifData&);
|
||||
/*!
|
||||
@brief Print one summary line with a label (if provided) and requested
|
||||
data. A line break is printed only if a label is provided.
|
||||
@return 1 if a line was written, 0 if the information was not found.
|
||||
*/
|
||||
int printTag(const Exiv2::ExifData& exifData, EasyAccessFct easyAccessFct, const std::string& label = "",
|
||||
EasyAccessFct easyAccessFctFallback = nullptr) const;
|
||||
|
||||
private:
|
||||
std::string path_;
|
||||
int align_{0}; // for the alignment of the summary output
|
||||
};
|
||||
|
||||
/// @brief %Rename a file to its metadata creation timestamp, in the specified format.
|
||||
class Rename : public Task {
|
||||
public:
|
||||
int run(const std::string& path) override;
|
||||
[[nodiscard]] Task::UniquePtr clone() const override;
|
||||
}; // class Rename
|
||||
|
||||
//! %Adjust the Exif (or other metadata) timestamps
|
||||
class Adjust : public Task {
|
||||
public:
|
||||
int run(const std::string& path) override;
|
||||
[[nodiscard]] Task::UniquePtr clone() const override;
|
||||
|
||||
private:
|
||||
int adjustDateTime(Exiv2::ExifData& exifData, const std::string& key, const std::string& path) const;
|
||||
|
||||
int64_t adjustment_{0};
|
||||
int64_t yearAdjustment_{0};
|
||||
int64_t monthAdjustment_{0};
|
||||
int64_t dayAdjustment_{0};
|
||||
|
||||
}; // class Adjust
|
||||
|
||||
/// @brief %Erase the entire exif data or only the thumbnail section.
|
||||
class Erase : public Task {
|
||||
public:
|
||||
int run(const std::string& path) override;
|
||||
[[nodiscard]] Task::UniquePtr clone() const override;
|
||||
|
||||
/// @brief Delete the thumbnail image, incl IFD1 metadata from the file.
|
||||
static int eraseThumbnail(Exiv2::Image* image);
|
||||
|
||||
/// @brief Erase the complete Exif data block from the file.
|
||||
static int eraseExifData(Exiv2::Image* image);
|
||||
|
||||
/// @brief Erase all Iptc data from the file.
|
||||
static int eraseIptcData(Exiv2::Image* image);
|
||||
|
||||
/// @brief Erase Jpeg comment from the file.
|
||||
static int eraseComment(Exiv2::Image* image);
|
||||
|
||||
/// @brief Erase XMP packet from the file.
|
||||
static int eraseXmpData(Exiv2::Image* image);
|
||||
|
||||
/// @brief Erase ICCProfile from the file.
|
||||
static int eraseIccProfile(Exiv2::Image* image);
|
||||
|
||||
private:
|
||||
std::string path_;
|
||||
};
|
||||
|
||||
/// @brief %Extract the entire exif data or only the thumbnail section.
|
||||
class Extract : public Task {
|
||||
public:
|
||||
int run(const std::string& path) override;
|
||||
[[nodiscard]] Task::UniquePtr clone() const override;
|
||||
|
||||
/*!
|
||||
@brief Write the thumbnail image to a file. The filename is composed by
|
||||
removing the suffix from the image filename and appending
|
||||
"-thumb" and the appropriate suffix (".jpg" or ".tif"), depending
|
||||
on the format of the Exif thumbnail image.
|
||||
*/
|
||||
[[nodiscard]] int writeThumbnail() const;
|
||||
|
||||
/// @brief Write preview images to files.
|
||||
[[nodiscard]] int writePreviews() const;
|
||||
|
||||
/// @brief Write one preview image to a file. The filename is composed by removing the suffix from the image
|
||||
/// filename and appending "-preview<num>" and the appropriate suffix (".jpg" or ".tif"), depending on the
|
||||
/// format of the Exif thumbnail image.
|
||||
void writePreviewFile(const Exiv2::PreviewImage& pvImg, size_t num) const;
|
||||
|
||||
/// @brief Write embedded iccProfile files.
|
||||
[[nodiscard]] int writeIccProfile(const std::string& target) const;
|
||||
|
||||
private:
|
||||
std::string path_;
|
||||
};
|
||||
|
||||
/// @brief %Insert the Exif data from corresponding *.exv files.
|
||||
class Insert : public Task {
|
||||
public:
|
||||
int run(const std::string& path) override;
|
||||
[[nodiscard]] Task::UniquePtr clone() const override;
|
||||
|
||||
/*!
|
||||
@brief Insert a Jpeg thumbnail image from a file into file \em path.
|
||||
The filename of the thumbnail is expected to be the image
|
||||
filename (\em path) minus its suffix plus "-thumb.jpg".
|
||||
*/
|
||||
static int insertThumbnail(const std::string& path);
|
||||
|
||||
/// @brief Insert an XMP packet from a xmpPath into file \em path.
|
||||
static int insertXmpPacket(const std::string& path, const std::string& xmpPath);
|
||||
|
||||
/// @brief Insert xmp from a DataBuf into file \em path.
|
||||
static int insertXmpPacket(const std::string& path, const Exiv2::DataBuf& xmpBlob, bool usePacket = false);
|
||||
|
||||
/// @brief Insert an ICC profile from iccPath into file \em path.
|
||||
static int insertIccProfile(const std::string& path, const std::string& iccPath);
|
||||
|
||||
/// @brief Insert an ICC profile from binary DataBuf into file \em path.
|
||||
static int insertIccProfile(const std::string& path, Exiv2::DataBuf&& iccProfileBlob);
|
||||
};
|
||||
|
||||
/// @brief %Modify the Exif data according to the commands in the modification table.
|
||||
class Modify : public Task {
|
||||
public:
|
||||
int run(const std::string& path) override;
|
||||
[[nodiscard]] Task::UniquePtr clone() const override;
|
||||
//! Apply modification commands to the \em pImage, return 0 if successful.
|
||||
static int applyCommands(Exiv2::Image* pImage);
|
||||
|
||||
private:
|
||||
//! Add a metadatum to \em pImage according to \em modifyCmd
|
||||
static int addMetadatum(Exiv2::Image* pImage, const ModifyCmd& modifyCmd);
|
||||
//! Set a metadatum in \em pImage according to \em modifyCmd
|
||||
static int setMetadatum(Exiv2::Image* pImage, const ModifyCmd& modifyCmd);
|
||||
//! Delete a metadatum from \em pImage according to \em modifyCmd
|
||||
static void delMetadatum(Exiv2::Image* pImage, const ModifyCmd& modifyCmd);
|
||||
//! Register an XMP namespace according to \em modifyCmd
|
||||
static void regNamespace(const ModifyCmd& modifyCmd);
|
||||
};
|
||||
|
||||
/// @brief %Copy ISO settings from any of the Nikon makernotes to the regular Exif tag, Exif.Photo.ISOSpeedRatings.
|
||||
class FixIso : public Task {
|
||||
public:
|
||||
int run(const std::string& path) override;
|
||||
[[nodiscard]] Task::UniquePtr clone() const override;
|
||||
|
||||
private:
|
||||
std::string path_;
|
||||
};
|
||||
|
||||
/// @brief Fix the character encoding of Exif UNICODE user comments.
|
||||
///
|
||||
/// Decodes the comment using the auto-detected or specified character encoding and writes it back in UCS-2.
|
||||
class FixCom : public Task {
|
||||
public:
|
||||
int run(const std::string& path) override;
|
||||
[[nodiscard]] Task::UniquePtr clone() const override;
|
||||
|
||||
private:
|
||||
std::string path_;
|
||||
};
|
||||
|
||||
} // namespace Action
|
||||
|
||||
#endif // #ifndef ACTIONS_HPP_
|
@ -1,27 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "app_utils.hpp"
|
||||
#include <climits>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
|
||||
namespace Util {
|
||||
bool strtol(const char* nptr, int64_t& n) {
|
||||
if (!nptr || *nptr == '\0')
|
||||
return false;
|
||||
char* endptr = nullptr;
|
||||
long long tmp = std::strtoll(nptr, &endptr, 10);
|
||||
if (*endptr != '\0')
|
||||
return false;
|
||||
// strtoll returns LLONG_MAX or LLONG_MIN if an overflow occurs.
|
||||
if (tmp == LLONG_MAX || tmp == LLONG_MIN)
|
||||
return false;
|
||||
if (tmp < std::numeric_limits<int64_t>::min())
|
||||
return false;
|
||||
if (tmp > std::numeric_limits<int64_t>::max())
|
||||
return false;
|
||||
n = static_cast<int64_t>(tmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Util
|
@ -1,17 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#ifndef APP_UTILS_HPP_
|
||||
#define APP_UTILS_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Util {
|
||||
/*!
|
||||
@brief Convert a C string to an int64_t value, which is returned in n.
|
||||
Returns true if the conversion is successful, else false.
|
||||
n is not modified if the conversion is unsuccessful. See strtol(2).
|
||||
*/
|
||||
bool strtol(const char* nptr, int64_t& n);
|
||||
} // namespace Util
|
||||
|
||||
#endif // APP_UTILS_HPP_
|
File diff suppressed because it is too large
Load Diff
@ -1,302 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*!
|
||||
@brief Defines class Params, used for the command line handling of exiv2
|
||||
@author Andreas Huggel (ahu)
|
||||
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
|
||||
@date 08-Dec-03, ahu: created
|
||||
*/
|
||||
#ifndef EXIV2APP_HPP_
|
||||
#define EXIV2APP_HPP_
|
||||
|
||||
// *****************************************************************************
|
||||
// included header files
|
||||
#include <exiv2/exiv2.hpp>
|
||||
|
||||
#include "getopt.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
// + standard includes
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
#include <set>
|
||||
|
||||
//! Command identifiers
|
||||
enum class CmdId {
|
||||
invalid,
|
||||
add,
|
||||
set,
|
||||
del,
|
||||
reg,
|
||||
};
|
||||
//! Metadata identifiers
|
||||
enum class MetadataId : uint32_t {
|
||||
invalid = Exiv2::mdNone, // 0
|
||||
exif = Exiv2::mdExif, // 1
|
||||
iptc = Exiv2::mdIptc, // 2
|
||||
xmp = Exiv2::mdXmp, // 8
|
||||
};
|
||||
|
||||
inline MetadataId operator&(MetadataId x, MetadataId y) {
|
||||
return static_cast<MetadataId>(static_cast<uint32_t>(x) & static_cast<uint32_t>(y));
|
||||
}
|
||||
|
||||
inline MetadataId operator|(MetadataId x, MetadataId y) {
|
||||
return static_cast<MetadataId>(static_cast<uint32_t>(x) | static_cast<uint32_t>(y));
|
||||
}
|
||||
|
||||
inline MetadataId& operator|=(MetadataId& x, MetadataId y) {
|
||||
return x = x | y;
|
||||
}
|
||||
|
||||
//! Structure for one parsed modification command
|
||||
struct ModifyCmd {
|
||||
//! C'tor
|
||||
ModifyCmd() = default;
|
||||
CmdId cmdId_{CmdId::invalid}; //!< Command identifier
|
||||
std::string key_; //!< Exiv2 key string
|
||||
MetadataId metadataId_{MetadataId::invalid}; //!< Metadata identifier
|
||||
Exiv2::TypeId typeId_{Exiv2::invalidTypeId}; //!< Exiv2 type identifier
|
||||
//! Flag to indicate if the type was explicitly specified (true)
|
||||
bool explicitType_{false};
|
||||
std::string value_; //!< Data
|
||||
};
|
||||
//! Container for modification commands
|
||||
using ModifyCmds = std::vector<ModifyCmd>;
|
||||
/*!
|
||||
@brief Implements the command line handling for the program.
|
||||
|
||||
Derives from Util::Getopt to use the command line argument parsing
|
||||
functionality provided there. This class is implemented as a singleton,
|
||||
i.e., there is only one global instance of it, which can be accessed
|
||||
from everywhere.
|
||||
|
||||
<b>Usage example:</b> <br>
|
||||
@code
|
||||
#include "params.h"
|
||||
|
||||
int main(int argc, char* const argv[])
|
||||
{
|
||||
Params& params = Params::instance();
|
||||
if (params.getopt(argc, argv)) {
|
||||
params.usage();
|
||||
return 1;
|
||||
}
|
||||
if (params.help_) {
|
||||
params.help();
|
||||
return 0;
|
||||
}
|
||||
if (params.version_) {
|
||||
params.version();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// do something useful here...
|
||||
|
||||
return 0;
|
||||
}
|
||||
@endcode
|
||||
*/
|
||||
|
||||
class Params : public Util::Getopt {
|
||||
private:
|
||||
std::string optstring_;
|
||||
|
||||
public:
|
||||
//! Container for command files
|
||||
using CmdFiles = std::vector<std::string>;
|
||||
//! Container for commands from the command line
|
||||
using CmdLines = std::vector<std::string>;
|
||||
//! Container to store filenames.
|
||||
using Files = std::vector<std::string>;
|
||||
//! Container for preview image numbers
|
||||
using PreviewNumbers = std::set<int>;
|
||||
//! Container for keys
|
||||
using Keys = std::vector<std::string>;
|
||||
|
||||
/*!
|
||||
@brief Controls all access to the global Params instance.
|
||||
@return Reference to the global Params instance.
|
||||
*/
|
||||
static Params& instance();
|
||||
|
||||
//! Prevent copy-construction: not implemented.
|
||||
~Params() override = default;
|
||||
Params(const Params&) = delete;
|
||||
Params& operator=(const Params&) = delete;
|
||||
|
||||
//! Enumerates print modes
|
||||
enum PrintMode {
|
||||
pmSummary,
|
||||
pmList,
|
||||
pmComment,
|
||||
pmPreview,
|
||||
pmStructure,
|
||||
pmXMP,
|
||||
pmIccProfile,
|
||||
pmRecursive,
|
||||
};
|
||||
|
||||
//! Individual items to print, bitmap
|
||||
enum PrintItem : uint32_t {
|
||||
prTag = 1,
|
||||
prGroup = 2,
|
||||
prKey = 4,
|
||||
prName = 8,
|
||||
prLabel = 16,
|
||||
prType = 32,
|
||||
prCount = 64,
|
||||
prSize = 128,
|
||||
prValue = 256,
|
||||
prTrans = 512,
|
||||
prHex = 1024,
|
||||
prSet = 2048,
|
||||
prDesc = 4096
|
||||
};
|
||||
|
||||
//! Enumerates common targets, bitmap
|
||||
enum CommonTarget : uint32_t {
|
||||
ctExif = 1,
|
||||
ctIptc = 2,
|
||||
ctComment = 4,
|
||||
ctThumb = 8,
|
||||
ctXmp = 16,
|
||||
ctXmpSidecar = 32,
|
||||
ctPreview = 64,
|
||||
ctIccProfile = 128,
|
||||
ctXmpRaw = 256,
|
||||
ctStdInOut = 512,
|
||||
ctIptcRaw = 1024
|
||||
};
|
||||
|
||||
//! Enumerates the policies to handle existing files in rename action
|
||||
enum FileExistsPolicy {
|
||||
overwritePolicy,
|
||||
renamePolicy,
|
||||
askPolicy,
|
||||
};
|
||||
|
||||
//! Enumerates year, month and day adjustments.
|
||||
enum Yod {
|
||||
yodYear,
|
||||
yodMonth,
|
||||
yodDay,
|
||||
};
|
||||
|
||||
//! Structure for year, month and day adjustment command line arguments.
|
||||
struct YodAdjust {
|
||||
bool flag_; //!< Adjustment flag.
|
||||
const char* option_; //!< Adjustment option string.
|
||||
int64_t adjustment_; //!< Adjustment value.
|
||||
};
|
||||
|
||||
bool help_{false}; //!< Help option flag.
|
||||
bool version_{false}; //!< Version option flag.
|
||||
bool verbose_{false}; //!< Verbose (talkative) option flag.
|
||||
bool force_{false}; //!< Force overwrites flag.
|
||||
bool binary_{false}; //!< Suppress long binary values.
|
||||
bool unknown_{true}; //!< Suppress unknown tags.
|
||||
bool preserve_{false}; //!< Preserve timestamps flag.
|
||||
bool timestamp_{false}; //!< Rename also sets the file timestamp.
|
||||
bool timestampOnly_{false}; //!< Rename only sets the file timestamp.
|
||||
FileExistsPolicy fileExistsPolicy_{askPolicy}; //!< What to do if file to rename exists.
|
||||
bool adjust_{false}; //!< Adjustment flag.
|
||||
PrintMode printMode_{pmSummary}; //!< Print mode.
|
||||
PrintItem printItems_{0}; //!< Print items.
|
||||
MetadataId printTags_{Exiv2::mdNone}; //!< Print tags (bitmap of MetadataId flags).
|
||||
//! %Action (integer rather than TaskType to avoid dependency).
|
||||
int action_{0};
|
||||
CommonTarget target_; //!< What common target to process.
|
||||
|
||||
int64_t adjustment_{0}; //!< Adjustment in seconds.
|
||||
std::array<YodAdjust, 3> yodAdjust_; //!< Year, month and day adjustment info.
|
||||
std::string format_; //!< Filename format (-r option arg).
|
||||
bool formatSet_{false}; //!< Whether the format is set with -r
|
||||
CmdFiles cmdFiles_; //!< Names of the modification command files
|
||||
CmdLines cmdLines_; //!< Commands from the command line
|
||||
ModifyCmds modifyCmds_; //!< Parsed modification commands
|
||||
std::string jpegComment_; //!< Jpeg comment to set in the image
|
||||
std::string directory_; //!< Location for files to extract/insert
|
||||
std::string suffix_; //!< File extension of the file to insert
|
||||
Files files_; //!< List of non-option arguments.
|
||||
PreviewNumbers previewNumbers_; //!< List of preview numbers
|
||||
std::vector<std::regex> greps_; //!< List of keys to 'grep' from the metadata
|
||||
Keys keys_; //!< List of keys to match from the metadata
|
||||
std::string charset_; //!< Charset to use for UNICODE Exif user comment
|
||||
|
||||
Exiv2::DataBuf stdinBuf; //!< DataBuf with the binary bytes from stdin
|
||||
|
||||
private:
|
||||
bool first_{true};
|
||||
|
||||
Params();
|
||||
|
||||
//! @name Helpers
|
||||
//@{
|
||||
int setLogLevel(const std::string& optarg);
|
||||
int evalGrep(const std::string& optarg);
|
||||
int evalKey(const std::string& optarg);
|
||||
int evalRename(int opt, const std::string& optarg);
|
||||
int evalAdjust(const std::string& optarg);
|
||||
int evalYodAdjust(const Yod& yod, const std::string& optarg);
|
||||
int evalPrint(const std::string& optarg);
|
||||
int evalPrintFlags(const std::string& optarg);
|
||||
int evalDelete(const std::string& optarg);
|
||||
int evalExtract(const std::string& optarg);
|
||||
int evalInsert(const std::string& optarg);
|
||||
int evalModify(int opt, const std::string& optarg);
|
||||
//@}
|
||||
|
||||
public:
|
||||
/*!
|
||||
@brief Call Getopt::getopt() with optstring, to initiate command line
|
||||
argument parsing, perform consistency checks after all command line
|
||||
arguments are parsed.
|
||||
|
||||
@param argc Argument count as passed to main() on program invocation.
|
||||
@param argv Argument array as passed to main() on program invocation.
|
||||
|
||||
@return 0 if successful, >0 in case of errors.
|
||||
*/
|
||||
int getopt(int argc, char* const argv[]);
|
||||
|
||||
//! Handle options and their arguments.
|
||||
int option(int opt, const std::string& optarg, int optopt) override;
|
||||
|
||||
//! Handle non-option parameters.
|
||||
int nonoption(const std::string& argv) override;
|
||||
|
||||
//! Print a minimal usage note to an output stream.
|
||||
void usage(std::ostream& os = std::cout) const;
|
||||
|
||||
//! Print further usage explanations to an output stream.
|
||||
void help(std::ostream& os = std::cout) const;
|
||||
|
||||
//! Print version information to an output stream.
|
||||
static void version(bool verbose = false, std::ostream& os = std::cout);
|
||||
|
||||
//! getStdin binary data read from stdin to DataBuf
|
||||
/*
|
||||
stdin can be used by multiple images in the exiv2 command line:
|
||||
For example: $ cat foo.icc | exiv2 -iC- a.jpg b.jpg c.jpg will modify the ICC profile in several images.
|
||||
*/
|
||||
void getStdin(Exiv2::DataBuf& buf);
|
||||
|
||||
}; // class Params
|
||||
|
||||
inline Params::CommonTarget operator|(Params::CommonTarget x, Params::CommonTarget y) {
|
||||
return static_cast<Params::CommonTarget>(static_cast<uint32_t>(x) | static_cast<uint32_t>(y));
|
||||
}
|
||||
|
||||
inline Params::CommonTarget& operator|=(Params::CommonTarget& x, Params::CommonTarget y) {
|
||||
return x = x | y;
|
||||
}
|
||||
|
||||
inline Params::PrintItem operator|(Params::PrintItem x, Params::PrintItem y) {
|
||||
return static_cast<Params::PrintItem>(static_cast<uint32_t>(x) | static_cast<uint32_t>(y));
|
||||
}
|
||||
|
||||
inline Params::PrintItem& operator|=(Params::PrintItem& x, Params::PrintItem y) {
|
||||
return x = x | y;
|
||||
}
|
||||
|
||||
#endif // #ifndef EXIV2APP_HPP_
|
@ -1,112 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// included header files
|
||||
#include "getopt.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#if __has_include(<filesystem>)
|
||||
#include <filesystem>
|
||||
namespace fs = std::filesystem;
|
||||
#else
|
||||
#include <experimental/filesystem>
|
||||
namespace fs = std::experimental::filesystem;
|
||||
#endif
|
||||
|
||||
namespace Util {
|
||||
// https://raw.githubusercontent.com/skeeto/getopt/master/getopt.h
|
||||
int optind = 0;
|
||||
int opterr = 1;
|
||||
int optopt;
|
||||
int optpos = 1;
|
||||
const char* optarg;
|
||||
|
||||
/* A minimal POSIX getopt() implementation in ANSI C
|
||||
*
|
||||
* This is free and unencumbered software released into the public domain.
|
||||
*
|
||||
* This implementation supports the convention of resetting the option
|
||||
* parser by assigning optind to 0. This resets the internal state
|
||||
* appropriately.
|
||||
*
|
||||
* Ref: http://pubs.opengroup.org/onlinepubs/9699919799/functions/getopt.html
|
||||
*/
|
||||
|
||||
int getopt(int argc, char* const argv[], const char* optstring) {
|
||||
const char* arg;
|
||||
(void)argc;
|
||||
|
||||
/* Reset? */
|
||||
if (optind == 0) {
|
||||
optind = 1;
|
||||
optpos = 1;
|
||||
}
|
||||
|
||||
arg = argv[optind];
|
||||
if (arg && strcmp(arg, "--") == 0) {
|
||||
optind++;
|
||||
return -1;
|
||||
}
|
||||
if (!arg || arg[0] != '-' || !isalnum(arg[1])) {
|
||||
return -1;
|
||||
}
|
||||
const char* opt = strchr(optstring, arg[optpos]);
|
||||
optopt = arg[optpos];
|
||||
if (!opt) {
|
||||
if (opterr && *optstring != ':')
|
||||
fprintf(stderr, "%s: illegal option: %c\n", argv[0], optopt);
|
||||
return '?';
|
||||
}
|
||||
if (opt[1] == ':') {
|
||||
if (arg[optpos + 1]) {
|
||||
optarg = const_cast<char*>(arg) + optpos + 1;
|
||||
optind++;
|
||||
optpos = 1;
|
||||
return optopt;
|
||||
}
|
||||
if (argv[optind + 1]) {
|
||||
optarg = argv[optind + 1];
|
||||
optind += 2;
|
||||
optpos = 1;
|
||||
return optopt;
|
||||
}
|
||||
if (opterr && *optstring != ':')
|
||||
fprintf(stderr, "%s: option requires an argument: %c\n", argv[0], optopt);
|
||||
return *optstring == ':' ? ':' : '?';
|
||||
}
|
||||
if (!arg[++optpos]) {
|
||||
optind++;
|
||||
optpos = 1;
|
||||
}
|
||||
return optopt;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// class Getopt
|
||||
int Getopt::getopt(int argc, char* const argv[], const std::string& optstring) {
|
||||
progname_ = fs::path(argv[0]).filename().string();
|
||||
Util::optind = 0; // reset the Util::Getopt scanner
|
||||
|
||||
while (!errcnt_) {
|
||||
int c = Util::getopt(argc, argv, optstring.c_str());
|
||||
if (c == -1) {
|
||||
break;
|
||||
}
|
||||
errcnt_ += option(c, Util::optarg ? Util::optarg : "", Util::optopt);
|
||||
if (c == '?') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = Util::optind; i < argc; i++) {
|
||||
errcnt_ += nonoption(argv[i]);
|
||||
}
|
||||
|
||||
return errcnt_;
|
||||
}
|
||||
|
||||
int Getopt::nonoption(const std::string& /*argv*/) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Util
|
@ -1,104 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#ifndef GETOPT_H
|
||||
#define GETOPT_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Util {
|
||||
extern int optind;
|
||||
extern int opterr;
|
||||
extern int optopt;
|
||||
extern int optpos;
|
||||
extern const char* optarg;
|
||||
|
||||
int getopt(int argc, char* const argv[], const char* optstring);
|
||||
|
||||
// *********************************************************************
|
||||
// class definitions
|
||||
|
||||
/*!
|
||||
@brief Parse the command line options of a program.
|
||||
|
||||
A wrapper around the POSIX %getopt(3) function. Parses the command line
|
||||
options and passes each option to virtual option(). A derived class
|
||||
implements this method to handle options as needed. Similarly,
|
||||
remaining non-option parameters are passed to the virtual nonoption()
|
||||
method.
|
||||
*/
|
||||
class Getopt {
|
||||
public:
|
||||
//! Default constructor.
|
||||
Getopt() = default;
|
||||
|
||||
//! Destructor.
|
||||
virtual ~Getopt() = default;
|
||||
|
||||
/*!
|
||||
@brief Parse command line arguments.
|
||||
|
||||
Parses the command line arguments. Calls option() with the
|
||||
character value of the option and its argument (if any) for each
|
||||
recognized option and with ':' or '?' for unrecognized options.
|
||||
See the manual pages for %getopt(3) for details. In addition,
|
||||
nonoption() is invoked for each remaining non-option parameter on
|
||||
the command line.
|
||||
|
||||
@param argc Argument count as passed to main() on program invocation.
|
||||
@param argv Argument array as passed to main() on program invocation.
|
||||
@param optstring String containing the legitimate option characters.
|
||||
|
||||
@return Number of errors (the sum of the return values from option()
|
||||
and nonoption()).
|
||||
*/
|
||||
int getopt(int argc, char* const argv[], const std::string& optstring);
|
||||
|
||||
/*!
|
||||
@brief Callback used by getopt() to pass on each option and its
|
||||
argument (if any).
|
||||
|
||||
Implement this method in a derived class to handle the options as
|
||||
needed. See the manual pages for %getopt(3) for further details, in
|
||||
particular, the semantics of optarg and optopt.
|
||||
|
||||
@param opt Value of the option character as returned by %getopt(3).
|
||||
@param optarg The corresponding option argument.
|
||||
@param optopt The actual option character in case of an unrecognized
|
||||
option or a missing option argument (opt is '?' or ':').
|
||||
|
||||
@return 0 if successful, 1 in case of an error.
|
||||
*/
|
||||
virtual int option(int opt, const std::string& optarg, int optopt) = 0;
|
||||
|
||||
/*!
|
||||
@brief Callback used by getopt() to pass on each non-option parameter
|
||||
found on the command line.
|
||||
|
||||
Implement this method in a derived class to handle the non-option
|
||||
parameters as needed. The default implementation ignores all non-option
|
||||
parameters.
|
||||
|
||||
@param argv The non-option parameter from the command line.
|
||||
|
||||
@return 0 if successful, 1 in case of an error.
|
||||
*/
|
||||
virtual int nonoption(const std::string& argv);
|
||||
|
||||
//! Program name (argv[0])
|
||||
[[nodiscard]] const std::string& progname() const {
|
||||
return progname_;
|
||||
}
|
||||
|
||||
//! Total number of errors returned by calls to option()
|
||||
[[nodiscard]] int errcnt() const {
|
||||
return errcnt_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string progname_;
|
||||
int errcnt_{0};
|
||||
};
|
||||
|
||||
} // namespace Util
|
||||
|
||||
#endif
|
@ -1,40 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
extern int __cdecl main(int, char*[]);
|
||||
|
||||
int wmain(int argc, wchar_t* argv[]) {
|
||||
char** args;
|
||||
int nbytes = static_cast<int>(sizeof(char*) * (argc + 1));
|
||||
HANDLE heap = GetProcessHeap();
|
||||
|
||||
for (int i = 0; i < argc; ++i)
|
||||
nbytes += WideCharToMultiByte(CP_UTF8, 0, argv[i], -1, nullptr, 0, nullptr, nullptr);
|
||||
|
||||
args = reinterpret_cast<char**>(HeapAlloc(heap, 0, nbytes));
|
||||
args[0] = reinterpret_cast<char*>(args + argc + 1);
|
||||
|
||||
for (int i = 0; i < argc; ++i)
|
||||
args[i + 1] = args[i] + WideCharToMultiByte(CP_UTF8, 0, argv[i], -1, args[i], nbytes, nullptr, nullptr);
|
||||
|
||||
args[argc] = nullptr;
|
||||
|
||||
argc = main(argc, args);
|
||||
HeapFree(heap, 0, args);
|
||||
return argc;
|
||||
}
|
||||
|
||||
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) {
|
||||
(void)hInstance;
|
||||
(void)hPrevInstance;
|
||||
(void)lpCmdLine;
|
||||
(void)nCmdShow;
|
||||
|
||||
int argc;
|
||||
wchar_t** argv;
|
||||
argv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||||
argc = wmain(argc, argv);
|
||||
LocalFree(argv);
|
||||
return argc;
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
# Configuration rescued from 'old-master' branch.
|
||||
# Only one Visual Studio (latest one), and all possible configurations
|
||||
image: Visual Studio 2019
|
||||
|
||||
configuration:
|
||||
- Debug
|
||||
- Release
|
||||
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
|
||||
environment:
|
||||
VCVARS: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat
|
||||
|
||||
PYTHON: "C:\\Python39-x64"
|
||||
|
||||
matrix:
|
||||
- SHARED: ON
|
||||
- SHARED: OFF
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
install:
|
||||
- set PATH=%PATH%;%PYTHON%/Scripts/
|
||||
- echo %APPVEYOR_BUILD_FOLDER%
|
||||
- if not exist deps mkdir deps
|
||||
- cd deps
|
||||
- if not exist ninja appveyor DownloadFile https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-win.zip -FileName ninja.zip
|
||||
- if not exist ninja 7z x ninja.zip -o%APPVEYOR_BUILD_FOLDER%\deps\ninja > nul
|
||||
- set PATH=%APPVEYOR_BUILD_FOLDER%\deps\ninja;%PATH%
|
||||
- ninja --version
|
||||
- python -m pip install --upgrade pip
|
||||
- pip3.exe install conan==1.35.2
|
||||
- pip3.exe install lxml
|
||||
- cd %APPVEYOR_BUILD_FOLDER%
|
||||
|
||||
before_build:
|
||||
- cmd: conan remote list
|
||||
- cmd: conan config set storage.path=c:\Users\appveyor\conanCache
|
||||
- cmd: conan profile new --detect default
|
||||
- cmd: conan profile update settings.compiler.version=16 default
|
||||
- cmd: if "%platform%"=="x64" (set ARCHITECTURE=x86_64) else (set ARCHITECTURE=x86)
|
||||
- cmd: if "%CONFIGURATION%"=="Debug" (set RUNTIME=MDd) else (set RUNTIME=MD)
|
||||
- cmd: conan profile update settings.arch=%ARCHITECTURE% default
|
||||
- cmd: conan profile update settings.arch_build=%ARCHITECTURE% default
|
||||
- cmd: conan profile update settings.build_type=%CONFIGURATION% default
|
||||
- cmd: conan profile update settings.compiler.runtime=%RUNTIME% default
|
||||
- cmd: cat c:\Users\appveyor\.conan\conan.conf
|
||||
- cmd: cat c:\Users\appveyor\.conan\profiles\default
|
||||
|
||||
build_script:
|
||||
- cmd: md build
|
||||
- cmd: cd build
|
||||
- cmd: if "%platform%"=="x64" (set VC_ARCH=x86_amd64) else (set VC_ARCH=x86)
|
||||
- cmd: call "%VCVARS%" %VC_ARCH%
|
||||
- cmd: conan install .. --build missing -o webready=True
|
||||
- cmd: cmake -GNinja -DBUILD_SHARED_LIBS=%SHARED% -DEXIV2_TEAM_WARNINGS_AS_ERRORS=ON -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DEXIV2_ENABLE_NLS=OFF -DEXIV2_ENABLE_PNG=ON -DEXIV2_ENABLE_WEBREADY=ON -DEXIV2_ENABLE_CURL=ON -DEXIV2_BUILD_UNIT_TESTS=ON -DEXIV2_ENABLE_WIN_UNICODE=OFF -DEXIV2_ENABLE_BMFF=ON -DCMAKE_INSTALL_PREFIX=install ..
|
||||
- cmd: ninja
|
||||
- cmd: ninja install
|
||||
- cmd: cd bin
|
||||
- cmd: unit_tests.exe
|
||||
- cmd: cd ../../tests/
|
||||
- cmd: set EXIV2_EXT=.exe
|
||||
- cmd: c:\Python39-x64\python.exe runner.py -v
|
||||
|
||||
cache:
|
||||
- deps # Ninja installation
|
||||
#- c:\Users\appveyor\conanCache # Conan cache
|
@ -1,64 +0,0 @@
|
||||
init:
|
||||
- echo %PYTHON%
|
||||
|
||||
environment:
|
||||
PYTHON: "C:/Python37-x64"
|
||||
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
BUILD: MINGW64
|
||||
INTEGRATION_TESTS: 1
|
||||
ARCHITECTURE: x86_64
|
||||
UNIT_TESTS: 1
|
||||
WEBREADY: False
|
||||
WARNINGS_AS_ERRORS: OFF
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
BUILD: CYGWIN64
|
||||
INTEGRATION_TESTS: 1
|
||||
ARCHITECTURE: x86_64
|
||||
UNIT_TESTS: 1
|
||||
WEBREADY: False
|
||||
WARNINGS_AS_ERRORS: OFF
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
install:
|
||||
- echo %APPVEYOR_BUILD_FOLDER%
|
||||
- if "%BUILD%"=="MINGW64" set "PATH=c:\msys64\mingw64\bin;c:\msys64\usr\bin;c:\msys64\usr\local\bin;"
|
||||
- if "%BUILD%"=="MINGW64" C:\msys64\usr\bin\bash -c "python -m pip install --upgrade pip;pip3.exe install lxml ; for i in base-devel git coreutils dos2unix tar diffutils make \
|
||||
mingw-w64-x86_64-toolchain mingw-w64-x86_64-gcc mingw-w64-x86_64-gdb \
|
||||
mingw-w64-x86_64-cmake mingw-w64-x86_64-gettext mingw-w64-x86_64-python3 \
|
||||
mingw-w64-x86_64-libexpat mingw-w64-x86_64-libiconv mingw-w64-x86_64-zlib \
|
||||
mingw-w64-x86_64-gtest ; do (echo y | pacman -S $i) ; done
|
||||
- cd %APPVEYOR_BUILD_FOLDER%
|
||||
- if "%BUILD%"=="CYGWIN64" set "PATH=c:\cygwin64\usr\local\bin;c:\cygwin64\bin;c:\cygwin64\usr\bin;c:\cygwin64\usr\sbin;"
|
||||
- if "%BUILD%"=="CYGWIN64" C:\cygwin64\bin\bash -c "wget https://raw.githubusercontent.com/transcode-open/apt-cyg/master/apt-cyg ; chmod +x apt-cyg; mv apt-cyg /usr/local/bin"
|
||||
- if "%BUILD%"=="CYGWIN64" C:\cygwin64\bin\bash -c "apt-cyg install cmake zlib-devel libexpat-devel libxml2-devel libxslt-devel python38 python38-pip python38-libxml2"
|
||||
- if "%BUILD%"=="CYGWIN64" C:\cygwin64\bin\bash -c "/usr/bin/python3.8.exe -m pip install --upgrade pip"
|
||||
|
||||
build_script:
|
||||
- cmd: set CMD=mkdir -p build
|
||||
- cmd: set CMD=%CMD%; cd build
|
||||
- cmd: set CMD=%CMD%; cmake .. -G 'Unix Makefiles'
|
||||
- cmd: set CMD=%CMD%; cmake --build . --config Release
|
||||
- cmd: rem echo %CMD%
|
||||
- cd %APPVEYOR_BUILD_FOLDER%
|
||||
- cmd: if "%BUILD%"=="MINGW64" C:\msys64\usr\bin\bash -c "%CMD%"
|
||||
- cmd: set CMD=which python3 python
|
||||
- cmd: set CMD=%CMD%; python --version
|
||||
- cmd: set CMD=%CMD%; build/bin/exiv2 --verbose --version; pwd ; ls -l
|
||||
- cmd: set CMD=%CMD%; cd build ; cmake --build . --config Release --target python_tests
|
||||
- cmd: echo %CMD%
|
||||
- cd %APPVEYOR_BUILD_FOLDER%
|
||||
- cmd: if "%BUILD%"=="MINGW64" C:\msys64\usr\bin\bash -c "%CMD%"
|
||||
- cmd: set "PATH=c:\cygwin64\usr\local\bin;c:\cygwin64\bin;c:\cygwin64\usr\bin;c:\cygwin64\usr\sbin;"
|
||||
- cmd: set CMD=rm -rf build
|
||||
- cmd: set CMD=%CMD%; mkdir -p build
|
||||
- cmd: set CMD=%CMD%; cd build
|
||||
- cmd: set CMD=%CMD%;cmake ..
|
||||
- cmd: set CMD=%CMD%; make
|
||||
- cmd: set CMD=%CMD%; make python_tests
|
||||
- cmd: echo %CMD%
|
||||
- cd %APPVEYOR_BUILD_FOLDER%
|
||||
- cmd: if "%BUILD%"=="CYGWIN64" C:\cygwin64\bin\bash -c "%CMD%"
|
||||
|
@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
set -e # Enables cheking of return values from each command
|
||||
set -x # Prints every command
|
||||
|
||||
python --version
|
||||
python3 --version
|
||||
|
||||
if [[ "$(uname -s)" == 'Linux' ]]; then
|
||||
sudo apt-get update
|
||||
sudo apt-get install cmake zlib1g-dev libssh-dev python-pip libxml2-utils
|
||||
if [ -n "$WITH_VALGRIND" ]; then
|
||||
sudo apt-get install valgrind
|
||||
fi
|
||||
sudo pip install virtualenv
|
||||
virtualenv conan
|
||||
source conan/bin/activate
|
||||
pip install conan==1.22.0
|
||||
pip install codecov
|
||||
else
|
||||
sudo pip3 install virtualenv
|
||||
virtualenv conan
|
||||
source conan/bin/activate
|
||||
pip3 install conan==1.22.0
|
||||
pip3 install codecov
|
||||
fi
|
||||
|
||||
conan --version
|
||||
conan config set storage.path=~/conanData
|
||||
conan profile new default --detect
|
||||
|
||||
if [[ "$(uname -s)" == 'Linux' ]]; then
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 default
|
||||
fi
|
||||
|
@ -0,0 +1,41 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
set -x
|
||||
|
||||
source conan/bin/activate
|
||||
|
||||
if [[ "$(uname -s)" == 'Linux' ]]; then
|
||||
if [ "$CC" == "clang" ]; then
|
||||
# clang + Ubuntu don't like to run with UBSAN, but ASAN works
|
||||
export CMAKE_OPTIONS="$CMAKE_OPTIONS -DCMAKE_CXX_FLAGS=\"-fsanitize=address\" -DCMAKE_C_FLAGS=\"-fsanitize=address\" -DCMAKE_EXE_LINKER_FLAGS=\"-fsanitize=address\" -DCMAKE_MODULE_LINKER_FLAGS=\"-fsanitize=address\""
|
||||
elif [ -n "$WITH_VALGRIND" ]; then
|
||||
export EXIV2_VALGRIND="valgrind --quiet"
|
||||
else
|
||||
export CMAKE_OPTIONS="$CMAKE_OPTIONS -DEXIV2_TEAM_USE_SANITIZERS=ON"
|
||||
fi
|
||||
else
|
||||
export CMAKE_OPTIONS="$CMAKE_OPTIONS -DEXIV2_TEAM_USE_SANITIZERS=ON"
|
||||
fi
|
||||
CMAKE_OPTIONS="$CMAKE_OPTIONS -DCMAKE_CXX_FLAGS=-Wno-deprecated"
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
conan install .. -o webready=True --build missing
|
||||
cmake ${CMAKE_OPTIONS} -DEXIV2_TEAM_WARNINGS_AS_ERRORS=ON -DCMAKE_INSTALL_PREFIX=install ..
|
||||
make -j 2
|
||||
make tests
|
||||
make install
|
||||
|
||||
# Check for detecting issues with the installation of headers
|
||||
if [ `ls install/include/exiv2/ | wc -l` > 10 ]; then
|
||||
echo Headers installed correctly
|
||||
else
|
||||
echo There was some problem with the installation of the public headers
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "$COVERAGE" ]; then
|
||||
bash <(curl -s https://codecov.io/bash)
|
||||
fi
|
||||
|
@ -1,45 +0,0 @@
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at https://curl.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is
|
||||
# furnished to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
###########################################################################
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_path(BROTLI_INCLUDE_DIR "brotli/decode.h")
|
||||
|
||||
find_library(BROTLICOMMON_LIBRARY NAMES brotlicommon)
|
||||
find_library(BROTLIDEC_LIBRARY NAMES brotlidec)
|
||||
|
||||
find_package_handle_standard_args(Brotli
|
||||
FOUND_VAR
|
||||
BROTLI_FOUND
|
||||
REQUIRED_VARS
|
||||
BROTLIDEC_LIBRARY
|
||||
BROTLICOMMON_LIBRARY
|
||||
BROTLI_INCLUDE_DIR
|
||||
FAIL_MESSAGE
|
||||
"Could NOT find Brotli"
|
||||
)
|
||||
|
||||
set(Brotli_INCLUDE_DIRS ${BROTLI_INCLUDE_DIR})
|
||||
set(Brotli_LIBRARIES ${BROTLICOMMON_LIBRARY} ${BROTLIDEC_LIBRARY})
|
||||
|
||||
mark_as_advanced(BROTLI_INCLUDE_DIR)
|
||||
mark_as_advanced(BROTLICOMMON_LIBRARY)
|
||||
mark_as_advanced(BROTLIDEC_LIBRARY)
|
@ -1,247 +0,0 @@
|
||||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
|
||||
FindFilesystem
|
||||
##############
|
||||
|
||||
This module supports the C++17 standard library's filesystem utilities. Use the
|
||||
:imp-target:`std::filesystem` imported target to
|
||||
|
||||
Options
|
||||
*******
|
||||
|
||||
The ``COMPONENTS`` argument to this module supports the following values:
|
||||
|
||||
.. find-component:: Experimental
|
||||
:name: fs.Experimental
|
||||
|
||||
Allows the module to find the "experimental" Filesystem TS version of the
|
||||
Filesystem library. This is the library that should be used with the
|
||||
``std::experimental::filesystem`` namespace.
|
||||
|
||||
.. find-component:: Final
|
||||
:name: fs.Final
|
||||
|
||||
Finds the final C++17 standard version of the filesystem library.
|
||||
|
||||
If no components are provided, behaves as if the
|
||||
:find-component:`fs.Final` component was specified.
|
||||
|
||||
If both :find-component:`fs.Experimental` and :find-component:`fs.Final` are
|
||||
provided, first looks for ``Final``, and falls back to ``Experimental`` in case
|
||||
of failure. If ``Final`` is found, :imp-target:`std::filesystem` and all
|
||||
:ref:`variables <fs.variables>` will refer to the ``Final`` version.
|
||||
|
||||
|
||||
Imported Targets
|
||||
****************
|
||||
|
||||
.. imp-target:: std::filesystem
|
||||
|
||||
The ``std::filesystem`` imported target is defined when any requested
|
||||
version of the C++ filesystem library has been found, whether it is
|
||||
*Experimental* or *Final*.
|
||||
|
||||
If no version of the filesystem library is available, this target will not
|
||||
be defined.
|
||||
|
||||
.. note::
|
||||
This target has ``cxx_std_17`` as an ``INTERFACE``
|
||||
:ref:`compile language standard feature <req-lang-standards>`. Linking
|
||||
to this target will automatically enable C++17 if no later standard
|
||||
version is already required on the linking target.
|
||||
|
||||
|
||||
.. _fs.variables:
|
||||
|
||||
Variables
|
||||
*********
|
||||
|
||||
.. variable:: CXX_FILESYSTEM_IS_EXPERIMENTAL
|
||||
|
||||
Set to ``TRUE`` when the :find-component:`fs.Experimental` version of C++
|
||||
filesystem library was found, otherwise ``FALSE``.
|
||||
|
||||
.. variable:: CXX_FILESYSTEM_HAVE_FS
|
||||
|
||||
Set to ``TRUE`` when a filesystem header was found.
|
||||
|
||||
.. variable:: CXX_FILESYSTEM_HEADER
|
||||
|
||||
Set to either ``filesystem`` or ``experimental/filesystem`` depending on
|
||||
whether :find-component:`fs.Final` or :find-component:`fs.Experimental` was
|
||||
found.
|
||||
|
||||
.. variable:: CXX_FILESYSTEM_NAMESPACE
|
||||
|
||||
Set to either ``std::filesystem`` or ``std::experimental::filesystem``
|
||||
depending on whether :find-component:`fs.Final` or
|
||||
:find-component:`fs.Experimental` was found.
|
||||
|
||||
|
||||
Examples
|
||||
********
|
||||
|
||||
Using `find_package(Filesystem)` with no component arguments:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
find_package(Filesystem REQUIRED)
|
||||
|
||||
add_executable(my-program main.cpp)
|
||||
target_link_libraries(my-program PRIVATE std::filesystem)
|
||||
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
|
||||
if(TARGET std::filesystem)
|
||||
# This module has already been processed. Don't do it again.
|
||||
return()
|
||||
endif()
|
||||
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
include(CMakePushCheckState)
|
||||
include(CheckIncludeFileCXX)
|
||||
|
||||
# If we're not cross-compiling, try to run test executables.
|
||||
# Otherwise, assume that compile + link is a sufficient check.
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
include(CheckCXXSourceCompiles)
|
||||
macro(_cmcm_check_cxx_source code var)
|
||||
check_cxx_source_compiles("${code}" ${var})
|
||||
endmacro()
|
||||
else()
|
||||
include(CheckCXXSourceRuns)
|
||||
macro(_cmcm_check_cxx_source code var)
|
||||
check_cxx_source_runs("${code}" ${var})
|
||||
endmacro()
|
||||
endif()
|
||||
|
||||
cmake_push_check_state()
|
||||
|
||||
set(CMAKE_REQUIRED_QUIET ${Filesystem_FIND_QUIETLY})
|
||||
|
||||
# All of our tests required C++17 or later
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
# Normalize and check the component list we were given
|
||||
set(want_components ${Filesystem_FIND_COMPONENTS})
|
||||
if(Filesystem_FIND_COMPONENTS STREQUAL "")
|
||||
set(want_components Final)
|
||||
endif()
|
||||
|
||||
# Warn on any unrecognized components
|
||||
set(extra_components ${want_components})
|
||||
list(REMOVE_ITEM extra_components Final Experimental)
|
||||
foreach(component IN LISTS extra_components)
|
||||
message(WARNING "Extraneous find_package component for Filesystem: ${component}")
|
||||
endforeach()
|
||||
|
||||
# Detect which of Experimental and Final we should look for
|
||||
set(find_experimental TRUE)
|
||||
set(find_final TRUE)
|
||||
if(NOT "Final" IN_LIST want_components)
|
||||
set(find_final FALSE)
|
||||
endif()
|
||||
if(NOT "Experimental" IN_LIST want_components)
|
||||
set(find_experimental FALSE)
|
||||
endif()
|
||||
|
||||
if(find_final)
|
||||
check_include_file_cxx("filesystem" _CXX_FILESYSTEM_HAVE_HEADER)
|
||||
mark_as_advanced(_CXX_FILESYSTEM_HAVE_HEADER)
|
||||
if(_CXX_FILESYSTEM_HAVE_HEADER)
|
||||
# We found the non-experimental header. Don't bother looking for the
|
||||
# experimental one.
|
||||
set(find_experimental FALSE)
|
||||
endif()
|
||||
else()
|
||||
set(_CXX_FILESYSTEM_HAVE_HEADER FALSE)
|
||||
endif()
|
||||
|
||||
if(find_experimental)
|
||||
check_include_file_cxx("experimental/filesystem" _CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER)
|
||||
mark_as_advanced(_CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER)
|
||||
else()
|
||||
set(_CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER FALSE)
|
||||
endif()
|
||||
|
||||
if(_CXX_FILESYSTEM_HAVE_HEADER)
|
||||
set(_have_fs TRUE)
|
||||
set(_fs_header filesystem)
|
||||
set(_fs_namespace std::filesystem)
|
||||
set(_is_experimental FALSE)
|
||||
elseif(_CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER)
|
||||
set(_have_fs TRUE)
|
||||
set(_fs_header experimental/filesystem)
|
||||
set(_fs_namespace std::experimental::filesystem)
|
||||
set(_is_experimental TRUE)
|
||||
else()
|
||||
set(_have_fs FALSE)
|
||||
endif()
|
||||
|
||||
set(CXX_FILESYSTEM_HAVE_FS ${_have_fs} CACHE BOOL "TRUE if we have the C++ filesystem headers")
|
||||
set(CXX_FILESYSTEM_HEADER ${_fs_header} CACHE STRING "The header that should be included to obtain the filesystem APIs")
|
||||
set(CXX_FILESYSTEM_NAMESPACE ${_fs_namespace} CACHE STRING "The C++ namespace that contains the filesystem APIs")
|
||||
set(CXX_FILESYSTEM_IS_EXPERIMENTAL ${_is_experimental} CACHE BOOL "TRUE if the C++ filesystem library is the experimental version")
|
||||
|
||||
set(_found FALSE)
|
||||
|
||||
if(CXX_FILESYSTEM_HAVE_FS)
|
||||
# We have some filesystem library available. Do link checks
|
||||
string(CONFIGURE [[
|
||||
#include <cstdlib>
|
||||
#include <@CXX_FILESYSTEM_HEADER@>
|
||||
|
||||
int main() {
|
||||
auto cwd = @CXX_FILESYSTEM_NAMESPACE@::current_path();
|
||||
printf("%s", cwd.c_str());
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
]] code @ONLY)
|
||||
|
||||
# Check a simple filesystem program without any linker flags
|
||||
_cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_NO_LINK_NEEDED)
|
||||
|
||||
set(can_link ${CXX_FILESYSTEM_NO_LINK_NEEDED})
|
||||
|
||||
if(NOT CXX_FILESYSTEM_NO_LINK_NEEDED)
|
||||
set(prev_libraries ${CMAKE_REQUIRED_LIBRARIES})
|
||||
# Add the libstdc++ flag
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lstdc++fs)
|
||||
_cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_STDCPPFS_NEEDED)
|
||||
set(can_link ${CXX_FILESYSTEM_STDCPPFS_NEEDED})
|
||||
if(NOT CXX_FILESYSTEM_STDCPPFS_NEEDED)
|
||||
# Try the libc++ flag
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lc++fs)
|
||||
_cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_CPPFS_NEEDED)
|
||||
set(can_link ${CXX_FILESYSTEM_CPPFS_NEEDED})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(can_link)
|
||||
add_library(std::filesystem INTERFACE IMPORTED)
|
||||
set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_COMPILE_FEATURES cxx_std_17)
|
||||
set(_found TRUE)
|
||||
|
||||
if(CXX_FILESYSTEM_NO_LINK_NEEDED)
|
||||
# Nothing to add...
|
||||
elseif(CXX_FILESYSTEM_STDCPPFS_NEEDED)
|
||||
set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_LINK_LIBRARIES -lstdc++fs)
|
||||
elseif(CXX_FILESYSTEM_CPPFS_NEEDED)
|
||||
set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_LINK_LIBRARIES -lc++fs)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
cmake_pop_check_state()
|
||||
|
||||
set(Filesystem_FOUND ${_found} CACHE BOOL "TRUE if we can run a program using std::filesystem" FORCE)
|
||||
|
||||
if(Filesystem_FIND_REQUIRED AND NOT Filesystem_FOUND)
|
||||
message(FATAL_ERROR "Cannot run simple program using std::filesystem")
|
||||
endif()
|
@ -0,0 +1,127 @@
|
||||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
FindIconv
|
||||
---------
|
||||
|
||||
This module finds the ``iconv()`` POSIX.1 functions on the system.
|
||||
These functions might be provided in the regular C library or externally
|
||||
in the form of an additional library.
|
||||
|
||||
The following variables are provided to indicate iconv support:
|
||||
|
||||
.. variable:: Iconv_FOUND
|
||||
|
||||
Variable indicating if the iconv support was found.
|
||||
|
||||
.. variable:: Iconv_INCLUDE_DIRS
|
||||
|
||||
The directories containing the iconv headers.
|
||||
|
||||
.. variable:: Iconv_LIBRARIES
|
||||
|
||||
The iconv libraries to be linked.
|
||||
|
||||
.. variable:: Iconv_IS_BUILT_IN
|
||||
|
||||
A variable indicating whether iconv support is stemming from the
|
||||
C library or not. Even if the C library provides `iconv()`, the presence of
|
||||
an external `libiconv` implementation might lead to this being false.
|
||||
|
||||
Additionally, the following :prop_tgt:`IMPORTED` target is being provided:
|
||||
|
||||
.. variable:: Iconv::Iconv
|
||||
|
||||
Imported target for using iconv.
|
||||
|
||||
The following cache variables may also be set:
|
||||
|
||||
.. variable:: Iconv_INCLUDE_DIR
|
||||
|
||||
The directory containing the iconv headers.
|
||||
|
||||
.. variable:: Iconv_LIBRARY
|
||||
|
||||
The iconv library (if not implicitly given in the C library).
|
||||
|
||||
.. note::
|
||||
On POSIX platforms, iconv might be part of the C library and the cache
|
||||
variables ``Iconv_INCLUDE_DIR`` and ``Iconv_LIBRARY`` might be empty.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
if (WIN32)
|
||||
# If neither C nor CXX are loaded, implicit iconv makes no sense.
|
||||
set(Iconv_IS_BUILT_IN FALSE)
|
||||
endif()
|
||||
|
||||
# iconv can only be provided in libc on a POSIX system.
|
||||
# If any cache variable is already set, we'll skip this test.
|
||||
if(NOT DEFINED Iconv_IS_BUILT_IN)
|
||||
if(UNIX AND NOT DEFINED Iconv_INCLUDE_DIR AND NOT DEFINED Iconv_LIBRARY)
|
||||
include(CheckCSourceCompiles)
|
||||
# We always suppress the message here: Otherwise on supported systems
|
||||
# not having iconv in their C library (e.g. those using libiconv)
|
||||
# would always display a confusing "Looking for iconv - not found" message
|
||||
set(CMAKE_FIND_QUIETLY TRUE)
|
||||
# The following code will not work, but it's sufficient to see if it compiles.
|
||||
# Note: libiconv will define the iconv functions as macros, so CheckSymbolExists
|
||||
# will not yield correct results.
|
||||
set(Iconv_IMPLICIT_TEST_CODE
|
||||
"
|
||||
#include <stddef.h>
|
||||
#include <iconv.h>
|
||||
int main() {
|
||||
char *a, *b;
|
||||
size_t i, j;
|
||||
iconv_t ic;
|
||||
ic = iconv_open(\"to\", \"from\");
|
||||
iconv(ic, &a, &i, &b, &j);
|
||||
iconv_close(ic);
|
||||
}
|
||||
"
|
||||
)
|
||||
if(CMAKE_C_COMPILER_LOADED)
|
||||
check_c_source_compiles("${Iconv_IMPLICIT_TEST_CODE}" Iconv_IS_BUILT_IN)
|
||||
else()
|
||||
check_cxx_source_compiles("${Iconv_IMPLICIT_TEST_CODE}" Iconv_IS_BUILT_IN)
|
||||
endif()
|
||||
else()
|
||||
set(Iconv_IS_BUILT_IN FALSE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT Iconv_IS_BUILT_IN)
|
||||
find_path(Iconv_INCLUDE_DIR
|
||||
NAMES "iconv.h"
|
||||
DOC "iconv include directory")
|
||||
set(Iconv_LIBRARY_NAMES "iconv" "libiconv")
|
||||
else()
|
||||
set(Iconv_INCLUDE_DIR "" CACHE FILEPATH "iconv include directory")
|
||||
set(Iconv_LIBRARY_NAMES "c")
|
||||
endif()
|
||||
|
||||
find_library(Iconv_LIBRARY
|
||||
NAMES ${Iconv_LIBRARY_NAMES}
|
||||
DOC "iconv library (potentially the C library)")
|
||||
|
||||
mark_as_advanced(Iconv_INCLUDE_DIR)
|
||||
mark_as_advanced(Iconv_LIBRARY)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
if(NOT Iconv_IS_BUILT_IN)
|
||||
find_package_handle_standard_args(Iconv REQUIRED_VARS Iconv_LIBRARY Iconv_INCLUDE_DIR)
|
||||
else()
|
||||
find_package_handle_standard_args(Iconv REQUIRED_VARS Iconv_LIBRARY)
|
||||
endif()
|
||||
|
||||
if(Iconv_FOUND)
|
||||
set(Iconv_INCLUDE_DIRS "${Iconv_INCLUDE_DIR}")
|
||||
set(Iconv_LIBRARIES "${Iconv_LIBRARY}")
|
||||
if(NOT TARGET Iconv::Iconv)
|
||||
add_library(Iconv::Iconv INTERFACE IMPORTED)
|
||||
endif()
|
||||
set_property(TARGET Iconv::Iconv PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${Iconv_INCLUDE_DIRS}")
|
||||
set_property(TARGET Iconv::Iconv PROPERTY INTERFACE_LINK_LIBRARIES "${Iconv_LIBRARIES}")
|
||||
endif()
|
@ -0,0 +1,50 @@
|
||||
# - Try to find the Regex library
|
||||
#
|
||||
# Once done this will define
|
||||
#
|
||||
# REGEX_FOUND - system has libregex
|
||||
# REGEX_INCLUDE_DIR - the libregex include directory
|
||||
# REGEX_LIBRARIES - Link these to use libregex
|
||||
#
|
||||
# Copyright (c) 2018, Gilles Caulier, <caulier dot gilles at gmail dot com>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
if ( NOT MSVC AND NOT MINGW AND NOT MSYS )
|
||||
find_path(Regex_INCLUDE_DIR
|
||||
NAMES regex.h
|
||||
DOC "libregex include directory"
|
||||
)
|
||||
|
||||
mark_as_advanced(Regex_INCLUDE_DIR)
|
||||
|
||||
find_library(Regex_LIBRARY "regex"
|
||||
DOC "libregex libraries"
|
||||
)
|
||||
|
||||
mark_as_advanced(Regex_LIBRARY)
|
||||
|
||||
find_package_handle_standard_args(Regex
|
||||
FOUND_VAR Regex_FOUND
|
||||
REQUIRED_VARS Regex_INCLUDE_DIR
|
||||
FAIL_MESSAGE "Failed to find libregex"
|
||||
)
|
||||
|
||||
if(REGEX_FOUND)
|
||||
|
||||
set(REGEX_INCLUDE_DIRS ${Regex_INCLUDE_DIRS})
|
||||
|
||||
if(Regex_LIBRARY)
|
||||
|
||||
set(REGEX_LIBRARIES ${Regex_LIBRARY})
|
||||
|
||||
else()
|
||||
|
||||
unset(REGEX_LIBRARIES)
|
||||
|
||||
endif()
|
||||
|
||||
endif()
|
||||
endif()
|
||||
|
@ -1,45 +0,0 @@
|
||||
set(inih_LIBRARY_NAMES "inih" "libinih")
|
||||
set(inih_inireader_LIBRARY_NAMES "INIReader" "libINIReader")
|
||||
|
||||
find_path(inih_INCLUDE_DIR
|
||||
NAMES "ini.h"
|
||||
DOC "inih include directory")
|
||||
|
||||
find_path(inih_inireader_INCLUDE_DIR
|
||||
NAMES "INIReader.h"
|
||||
DOC "INIReader include directory")
|
||||
|
||||
find_library(inih_LIBRARY
|
||||
NAMES ${inih_LIBRARY_NAMES}
|
||||
DOC "inih library")
|
||||
|
||||
find_library(inih_inireader_LIBRARY
|
||||
NAMES ${inih_inireader_LIBRARY_NAMES}
|
||||
DOC "inih library")
|
||||
|
||||
mark_as_advanced(inih_INCLUDE_DIR)
|
||||
mark_as_advanced(inih_LIBRARY)
|
||||
mark_as_advanced(inih_inireader_INCLUDE_DIR)
|
||||
mark_as_advanced(inih_inireader_LIBRARY)
|
||||
|
||||
find_package_handle_standard_args(inih REQUIRED_VARS inih_LIBRARY inih_INCLUDE_DIR inih_inireader_INCLUDE_DIR inih_inireader_LIBRARY)
|
||||
|
||||
if(NOT inih_FOUND)
|
||||
message(FATAL_ERROR "inih library not found")
|
||||
endif()
|
||||
|
||||
set(inih_INCLUDE_DIRS "${inih_INCLUDE_DIR}")
|
||||
set(inih_LIBRARIES "${inih_LIBRARY}")
|
||||
if(NOT TARGET inih::libinih)
|
||||
add_library(inih::libinih INTERFACE IMPORTED)
|
||||
endif()
|
||||
set_property(TARGET inih::libinih PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${inih_INCLUDE_DIRS}")
|
||||
set_property(TARGET inih::libinih PROPERTY INTERFACE_LINK_LIBRARIES "${inih_LIBRARIES}")
|
||||
|
||||
set(inih_inireader_INCLUDE_DIRS "${inih_inireader_INCLUDE_DIR}")
|
||||
set(inih_inireader_LIBRARIES "${inih_inireader_LIBRARY}")
|
||||
if(NOT TARGET inih::inireader)
|
||||
add_library(inih::inireader INTERFACE IMPORTED)
|
||||
endif()
|
||||
set_property(TARGET inih::inireader PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${inih_inireader_INCLUDE_DIRS}")
|
||||
set_property(TARGET inih::inireader PROPERTY INTERFACE_LINK_LIBRARIES "${inih_inireader_LIBRARIES}")
|
@ -1,13 +1,11 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
libdir=@EXIV2_LIBDIR@
|
||||
includedir=@EXIV2_INCLUDEDIR@
|
||||
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
|
||||
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
||||
|
||||
Name: exiv2
|
||||
Description: @PROJECT_DESCRIPTION@
|
||||
Version: @PROJECT_VERSION@
|
||||
URL: @PACKAGE_URL@
|
||||
Requires.private: @requires_private_for_pc_file@
|
||||
Libs: -L${libdir} -lexiv2
|
||||
Libs.private: @libs_private_for_pc_file@
|
||||
Cflags: -I${includedir}
|
||||
|
@ -1,19 +0,0 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
include(CMakeFindDependencyMacro)
|
||||
|
||||
if(@EXIV2_ENABLE_PNG@) # if(EXIV2_ENABLE_PNG)
|
||||
find_dependency(ZLIB REQUIRED)
|
||||
endif()
|
||||
|
||||
if(@EXIV2_ENABLE_XMP@) # if(EXIV2_ENABLE_XMP)
|
||||
find_dependency(EXPAT REQUIRED)
|
||||
endif()
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/exiv2Export.cmake")
|
||||
|
||||
check_required_components(exiv2)
|
||||
|
||||
# compatibility with non-aliased users
|
||||
add_library(exiv2lib ALIAS Exiv2::exiv2lib)
|
@ -1,24 +0,0 @@
|
||||
# Intended usage
|
||||
# cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_WITH_COVERAGE=yes ../
|
||||
# cmake --build . --config Debug
|
||||
# ctest
|
||||
# cmake --build . --config Debug --target coverage
|
||||
|
||||
if(BUILD_WITH_COVERAGE)
|
||||
find_program (GCOVR gcovr)
|
||||
|
||||
if(GCOVR)
|
||||
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/coverage_output )
|
||||
add_custom_command(OUTPUT _run_gcovr_parser
|
||||
POST_BUILD
|
||||
COMMAND ${GCOVR} --root ${PROJECT_SOURCE_DIR} --object-dir=${CMAKE_BINARY_DIR} --html --html-details -o coverage_output/coverage.html
|
||||
--exclude-directories xmpsdk --exclude-directories unitTests --exclude-directories samples
|
||||
--exclude '.*xmpsdk.*' --exclude '.*unitTests.*' --exclude '.*samples.*'
|
||||
--exclude-unreachable-branches --exclude-throw-branches
|
||||
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
add_custom_target (coverage DEPENDS _run_gcovr_parser)
|
||||
endif()
|
||||
|
||||
endif(BUILD_WITH_COVERAGE)
|
@ -1,12 +0,0 @@
|
||||
[build_requires]
|
||||
[settings]
|
||||
arch=x86
|
||||
build_type=Debug
|
||||
compiler=Visual Studio
|
||||
compiler.runtime=MDd
|
||||
compiler.version=16
|
||||
os=Windows
|
||||
arch_build=x86
|
||||
os_build=Windows
|
||||
[options]
|
||||
[env]
|
@ -1,12 +0,0 @@
|
||||
[build_requires]
|
||||
[settings]
|
||||
arch=x86_64
|
||||
build_type=Debug
|
||||
compiler=Visual Studio
|
||||
compiler.runtime=MDd
|
||||
compiler.version=16
|
||||
os=Windows
|
||||
arch_build=x86_64
|
||||
os_build=Windows
|
||||
[options]
|
||||
[env]
|
@ -1,12 +0,0 @@
|
||||
[build_requires]
|
||||
[settings]
|
||||
arch=x86
|
||||
build_type=Release
|
||||
compiler=Visual Studio
|
||||
compiler.runtime=MD
|
||||
compiler.version=16
|
||||
os=Windows
|
||||
arch_build=x86
|
||||
os_build=Windows
|
||||
[options]
|
||||
[env]
|
@ -1,12 +0,0 @@
|
||||
[build_requires]
|
||||
[settings]
|
||||
arch=x86_64
|
||||
build_type=Release
|
||||
compiler=Visual Studio
|
||||
compiler.runtime=MD
|
||||
compiler.version=16
|
||||
os=Windows
|
||||
arch_build=x86_64
|
||||
os_build=Windows
|
||||
[options]
|
||||
[env]
|
@ -1,25 +0,0 @@
|
||||
# Sample toolchain file for building for Windows from an Ubuntu 20.04 Linux system.
|
||||
#
|
||||
# Typical usage:
|
||||
# *) install cross compiler: `sudo apt-get install mingw-w64`
|
||||
# *) install zlib for mingw: sudo apt install libz-mingw-w64-dev
|
||||
# *) mkdir buildMinGWRelease && cd buildMinGWRelease
|
||||
# *) cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchain/Ubuntu20_04_mingw-w64-x86_64.cmake
|
||||
# -DEXIV2_ENABLE_XMP=OFF -DEXIV2_TEAM_EXTRA_WARNINGS=ON
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Windows)
|
||||
set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)
|
||||
|
||||
# cross compilers to use for C, C++ and Fortran
|
||||
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)
|
||||
set(CMAKE_Fortran_COMPILER ${TOOLCHAIN_PREFIX}-gfortran)
|
||||
set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres)
|
||||
|
||||
# target environment on the build host system
|
||||
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
|
||||
|
||||
# modify default behavior of FIND_XXX() commands
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
@ -1,25 +1,2 @@
|
||||
coverage:
|
||||
precision: 2
|
||||
round: down
|
||||
range: "60..100"
|
||||
|
||||
# we don't care about the coverage of files in these folders
|
||||
ignore:
|
||||
- "xmpsdk"
|
||||
- "unitTests"
|
||||
- "samples"
|
||||
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
threshold: 1 # decrease by up to 1% doesn't result in failure
|
||||
branches:
|
||||
- main
|
||||
|
||||
# check only the diff of the PR
|
||||
patch:
|
||||
default:
|
||||
threshold: 1
|
||||
branches:
|
||||
- main
|
||||
only_pulls: true
|
||||
ignore:
|
||||
- "xmpsdk" # Not interested about the coverage of XMKSDK
|
||||
|
@ -0,0 +1,235 @@
|
||||
/*
|
||||
* This code implements the MD5 message-digest algorithm.
|
||||
* The algorithm is due to Ron Rivest. This code was
|
||||
* written by Colin Plumb in 1993, no copyright is claimed.
|
||||
* This code is in the public domain; do with it what you wish.
|
||||
*
|
||||
* Equivalent code is available from RSA Data Security, Inc.
|
||||
* This code has been tested against that, and is equivalent,
|
||||
* except that you don't need to include two pages of legalese
|
||||
* with every copy.
|
||||
*
|
||||
* To compute the message digest of a chunk of bytes, declare an
|
||||
* MD5_CTX structure, pass it to MD5Init, call MD5Update as
|
||||
* needed on buffers full of bytes, and then call MD5Final, which
|
||||
* will fill a supplied 16-byte array with the digest.
|
||||
*
|
||||
* Changed so as no longer to depend on Colin Plumb's `usual.h' header
|
||||
* definitions; now uses stuff from dpkg's config.h.
|
||||
* - Ian Jackson <ian@chiark.greenend.org.uk>.
|
||||
* Still in the public domain.
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "MD5.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static void
|
||||
byteSwap(UWORD32 *buf, unsigned words)
|
||||
{
|
||||
const uint32_t byteOrderTest = 0x1;
|
||||
if (((char *)&byteOrderTest)[0] == 0) {
|
||||
md5byte *p = (md5byte *)buf;
|
||||
|
||||
do {
|
||||
*buf++ = (UWORD32)((unsigned)p[3] << 8 | p[2]) << 16 |
|
||||
((unsigned)p[1] << 8 | p[0]);
|
||||
p += 4;
|
||||
} while (--words);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
|
||||
* initialization constants.
|
||||
*/
|
||||
void
|
||||
MD5Init(struct MD5_CTX *ctx)
|
||||
{
|
||||
ctx->buf[0] = 0x67452301;
|
||||
ctx->buf[1] = 0xefcdab89;
|
||||
ctx->buf[2] = 0x98badcfe;
|
||||
ctx->buf[3] = 0x10325476;
|
||||
|
||||
ctx->bytes[0] = 0;
|
||||
ctx->bytes[1] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update context to reflect the concatenation of another buffer full
|
||||
* of bytes.
|
||||
*/
|
||||
void
|
||||
MD5Update(struct MD5_CTX *ctx, md5byte const *buf, unsigned len)
|
||||
{
|
||||
UWORD32 t;
|
||||
|
||||
/* Update byte count */
|
||||
|
||||
t = ctx->bytes[0];
|
||||
if ((ctx->bytes[0] = t + len) < t)
|
||||
ctx->bytes[1]++; /* Carry from low to high */
|
||||
|
||||
t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */
|
||||
if (t > len) {
|
||||
memcpy((md5byte *)ctx->in + 64 - t, buf, len);
|
||||
return;
|
||||
}
|
||||
/* First chunk is an odd size */
|
||||
memcpy((md5byte *)ctx->in + 64 - t, buf, t);
|
||||
byteSwap(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, ctx->in);
|
||||
buf += t;
|
||||
len -= t;
|
||||
|
||||
/* Process data in 64-byte chunks */
|
||||
while (len >= 64) {
|
||||
memcpy(ctx->in, buf, 64);
|
||||
byteSwap(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, ctx->in);
|
||||
buf += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
/* Handle any remaining bytes of data. */
|
||||
memcpy(ctx->in, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
void
|
||||
MD5Final(md5byte digest[16], struct MD5_CTX *ctx)
|
||||
{
|
||||
int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */
|
||||
md5byte *p = (md5byte *)ctx->in + count;
|
||||
|
||||
/* Set the first char of padding to 0x80. There is always room. */
|
||||
*p++ = 0x80;
|
||||
|
||||
/* Bytes of padding needed to make 56 bytes (-8..55) */
|
||||
count = 56 - 1 - count;
|
||||
|
||||
if (count < 0) { /* Padding forces an extra block */
|
||||
memset(p, 0, count + 8);
|
||||
byteSwap(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, ctx->in);
|
||||
p = (md5byte *)ctx->in;
|
||||
count = 56;
|
||||
}
|
||||
memset(p, 0, count);
|
||||
byteSwap(ctx->in, 14);
|
||||
|
||||
/* Append length in bits and transform */
|
||||
ctx->in[14] = ctx->bytes[0] << 3;
|
||||
ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
|
||||
MD5Transform(ctx->buf, ctx->in);
|
||||
|
||||
byteSwap(ctx->buf, 4);
|
||||
memcpy(digest, ctx->buf, 16);
|
||||
memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
|
||||
}
|
||||
|
||||
/* The four core functions - F1 is optimized somewhat */
|
||||
|
||||
/* #define F1(x, y, z) (x & y | ~x & z) */
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
/* This is the central step in the MD5 algorithm. */
|
||||
#define MD5STEP(f,w,x,y,z,in,s) \
|
||||
(w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
|
||||
|
||||
/*
|
||||
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
* reflect the addition of 16 longwords of new data. MD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
void
|
||||
MD5Transform(UWORD32 buf[4], UWORD32 const in[16])
|
||||
{
|
||||
register UWORD32 a, b, c, d;
|
||||
|
||||
a = buf[0];
|
||||
b = buf[1];
|
||||
c = buf[2];
|
||||
d = buf[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
#ifndef __MD5_h__
|
||||
#define __MD5_h__
|
||||
|
||||
/*
|
||||
* This is the header file for the MD5 message-digest algorithm.
|
||||
* The algorithm is due to Ron Rivest. This code was
|
||||
* written by Colin Plumb in 1993, no copyright is claimed.
|
||||
* This code is in the public domain; do with it what you wish.
|
||||
*
|
||||
* Equivalent code is available from RSA Data Security, Inc.
|
||||
* This code has been tested against that, and is equivalent,
|
||||
* except that you don't need to include two pages of legalese
|
||||
* with every copy.
|
||||
*
|
||||
* To compute the message digest of a chunk of bytes, declare an
|
||||
* MD5_CTX structure, pass it to MD5Init, call MD5Update as
|
||||
* needed on buffers full of bytes, and then call MD5Final, which
|
||||
* will fill a supplied 16-byte array with the digest.
|
||||
*
|
||||
* Changed so as no longer to depend on Colin Plumb's `usual.h'
|
||||
* header definitions; now uses stuff from dpkg's config.h
|
||||
* - Ian Jackson <ian@chiark.greenend.org.uk>.
|
||||
* Still in the public domain.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef EXV_HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* MSVC doesn't provide C99 types, but it has MS specific variants */
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#endif
|
||||
|
||||
typedef unsigned char md5byte;
|
||||
typedef uint32_t UWORD32;
|
||||
|
||||
struct MD5_CTX {
|
||||
UWORD32 buf[4];
|
||||
UWORD32 bytes[2];
|
||||
UWORD32 in[16];
|
||||
};
|
||||
|
||||
extern void MD5Init(struct MD5_CTX *context);
|
||||
extern void MD5Update(struct MD5_CTX *context, md5byte const *buf, unsigned len);
|
||||
extern void MD5Final(unsigned char digest[16], struct MD5_CTX *context);
|
||||
extern void MD5Transform(UWORD32 buf[4], UWORD32 const in[16]);
|
||||
|
||||
#endif
|
@ -0,0 +1,144 @@
|
||||
# ************************************************************* -*- Makefile -*-
|
||||
#
|
||||
# Copyright (C) 2004-2015 Andreas Huggel <ahuggel@gmx.net>
|
||||
#
|
||||
# This Makefile is part of the Exiv2 distribution.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following
|
||||
# disclaimer in the documentation and/or other materials provided
|
||||
# with the distribution.
|
||||
# 3. The name of the author may not be used to endorse or promote
|
||||
# products derived from this software without specific prior
|
||||
# written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# File: Makefile
|
||||
# Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
|
||||
# History: 31-Jan-09, ahu: created
|
||||
#
|
||||
# Description:
|
||||
# Simple Makefile to build the organize application. Requires installed
|
||||
# exiv2 library and headers. Adapted from samples/Makefile.
|
||||
#
|
||||
# Restrictions:
|
||||
# Requires GNU make.
|
||||
#
|
||||
|
||||
# ******************************************************************************
|
||||
# Default make target
|
||||
all: ozbin
|
||||
|
||||
# Include system configuration
|
||||
top_srcdir = ../..
|
||||
include $(top_srcdir)/config/config.mk
|
||||
include boost.mk
|
||||
|
||||
# ******************************************************************************
|
||||
# Source files
|
||||
|
||||
# Source files for the organize application
|
||||
OZMAIN = organize.cpp
|
||||
OZSRC = helpers.cpp MD5.cpp
|
||||
|
||||
# ******************************************************************************
|
||||
# Initialisations
|
||||
SHELL = /bin/sh
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .cpp .o .so
|
||||
|
||||
.PRECIOUS: %.cpp
|
||||
|
||||
CPPFLAGS := -I$(BOOST_INC_DIR) `pkg-config exiv2 --cflags`
|
||||
ifdef HAVE_STDINT
|
||||
CPPFLAGS += -DEXV_HAVE_STDINT_H=1
|
||||
endif
|
||||
|
||||
LDFLAGS := $(BOOST_LIBS) `pkg-config exiv2 --libs`
|
||||
|
||||
OZOBJ = $(OZSRC:.cpp=.o) $(OZMAIN:.cpp=.o)
|
||||
OZBIN = $(OZMAIN:.cpp=)
|
||||
OZEXE = $(OZMAIN:.cpp=$(EXEEXT))
|
||||
|
||||
ifdef DEP_TRACKING
|
||||
DEP = $(OZMAIN:%.cpp=$(DEPDIR)/%.d) $(OZSRC:%.cpp=$(DEPDIR)/%.d)
|
||||
endif
|
||||
|
||||
# ******************************************************************************
|
||||
# Rules
|
||||
ozbin: $(OZBIN)
|
||||
|
||||
$(OZOBJ): %.o: %.cpp
|
||||
$(COMPILE.cc) -o $@ $<
|
||||
@$(MAKEDEPEND)
|
||||
@$(POSTDEPEND)
|
||||
|
||||
%.ii: %.cpp
|
||||
set -e; \
|
||||
$(CXXCPP) -E $(CPPFLAGS) $< | sed '/^[ ]*$$/d' > $@
|
||||
|
||||
# ******************************************************************************
|
||||
# Targets
|
||||
.PHONY: all ozbin relink binclean install uninstall mostlyclean clean distclean maintainer-clean
|
||||
|
||||
ifdef DEP_TRACKING
|
||||
# Include targets from dependency files
|
||||
-include $(DEP)
|
||||
endif
|
||||
|
||||
$(OZBIN): $(OZOBJ)
|
||||
$(LIBTOOL) --mode=link $(LINK.cc) -o $@ $(OZOBJ)
|
||||
|
||||
relink: binclean organize
|
||||
|
||||
install:
|
||||
$(INSTALL_DIRS) $(DESTDIR)$(bindir)
|
||||
@$(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $(OZEXE) $(DESTDIR)$(bindir)/$(OZEXE)
|
||||
|
||||
uninstall:
|
||||
@$(LIBTOOL) --mode=uninstall $(RM) $(DESTDIR)$(bindir)/$(OZEXE)
|
||||
-rmdir $(DESTDIR)$(bindir)
|
||||
|
||||
# Remove binaries, e.g., to relink them
|
||||
binclean:
|
||||
$(RM) $(OZEXE)
|
||||
|
||||
mostlyclean:
|
||||
$(RM) core
|
||||
$(RM) $(OZMAIN:.cpp=.ii) $(OZSRC:.cpp=.ii)
|
||||
$(RM) $(OZMAIN:%.cpp=.libs/%.d) $(OZSRC:%.cpp=.libs/%.d)
|
||||
-rmdir .libs
|
||||
$(RM) $(OZOBJ)
|
||||
|
||||
clean: binclean mostlyclean
|
||||
|
||||
# Run `make distclean' from the top source directory to also remove
|
||||
# files created by configuring the program.
|
||||
distclean: clean
|
||||
ifdef DEP_TRACKING
|
||||
$(RM) $(DEP)
|
||||
-rmdir $(DEPDIR)
|
||||
endif
|
||||
$(RM) *~ *.bak *#
|
||||
|
||||
# This command is intended for maintainers to use; it deletes files
|
||||
# that may need special tools to rebuild.
|
||||
maintainer-clean: uninstall distclean
|
@ -0,0 +1,3 @@
|
||||
organize uses the Boost library (http://www.boost.org).
|
||||
Configuration settings for Boost are in the file boost.mk
|
||||
in this directory and should be changed as required.
|
@ -0,0 +1,3 @@
|
||||
# Boost configuration for organize - change paths and library names as needed
|
||||
BOOST_INC_DIR = /usr/local/include/boost-1_37
|
||||
BOOST_LIBS = /usr/local/lib/libboost_system-gcc43-mt-1_37.a /usr/local/lib/libboost_filesystem-gcc43-mt-1_37.a /usr/local/lib/libboost_regex-gcc43-mt-1_37.a /usr/local/lib/libboost_program_options-gcc43-mt-1_37.a
|
@ -0,0 +1,640 @@
|
||||
// ***************************************************************** -*- C++ -*-
|
||||
/*
|
||||
* Copyright (C) 2009 Brad Schick <schickb@gmail.com>
|
||||
*
|
||||
* This file is part of the organize tool.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/*
|
||||
File: helpers.cpp
|
||||
Author(s): Brad Schick (brad) <schickb@gmail.com>
|
||||
History: 19-Jan-09, brad: created
|
||||
*/
|
||||
// *****************************************************************************
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <exiv2/image.hpp>
|
||||
#include <exiv2/easyaccess.hpp>
|
||||
#include <exiv2/exif.hpp>
|
||||
#include <exiv2/iptc.hpp>
|
||||
#include <exiv2/tags.hpp>
|
||||
//#include <exiv2/xmp.hpp>
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <ctime>
|
||||
#include "helpers.hpp"
|
||||
|
||||
#define BOOST_FILESYSTEM_NO_DEPRECATED
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
typedef Exiv2::ExifData::const_iterator (*EasyAccessFct)(const Exiv2::ExifData& ed);
|
||||
|
||||
|
||||
std::string scrub(const std::string &dirty, bool strip_space = false)
|
||||
{
|
||||
std::string scrub = boost::trim_copy(dirty);
|
||||
if(strip_space) {
|
||||
boost::regex space("\\s");
|
||||
scrub = boost::regex_replace(scrub, space, "");
|
||||
}
|
||||
boost::regex dash("[:/\\\\|<>]");
|
||||
boost::regex under("[\"'\\[\\]\\{\\}#=%\\$\\?,\\+\\*]");
|
||||
scrub = boost::regex_replace(scrub, dash, "-");
|
||||
|
||||
return boost::regex_replace(scrub, under, "_");
|
||||
}
|
||||
|
||||
bool exif_data(const Exiv2::Image *image, const char *key, Exiv2::ExifData::const_iterator &md)
|
||||
{
|
||||
assert(image && key);
|
||||
bool ok = false;
|
||||
try {
|
||||
const Exiv2::ExifData &exifData = image->exifData();
|
||||
Exiv2::ExifKey exifKey(key);
|
||||
md = exifData.findKey(exifKey);
|
||||
if(md != exifData.end() && md->typeId() != Exiv2::undefined)
|
||||
ok = true;
|
||||
}
|
||||
catch(const Exiv2::AnyError&) {
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool exif_data_easy(const Exiv2::Image *image, EasyAccessFct easy, Exiv2::ExifData::const_iterator &md)
|
||||
{
|
||||
assert(image && easy);
|
||||
bool ok = false;
|
||||
try {
|
||||
const Exiv2::ExifData &exifData = image->exifData();
|
||||
md = easy(exifData);
|
||||
if(md != exifData.end() && md->typeId() != Exiv2::undefined)
|
||||
ok = true;
|
||||
}
|
||||
catch(const Exiv2::AnyError&) {
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
bool iptc_data(const Exiv2::Image *image, const char *key, Exiv2::IptcData::const_iterator &md)
|
||||
{
|
||||
bool ok = false;
|
||||
assert(image && key);
|
||||
try {
|
||||
const Exiv2::IptcData &iptcData = image->iptcData();
|
||||
Exiv2::IptcKey iptcKey(key);
|
||||
md = iptcData.findKey(iptcKey);
|
||||
if(md != iptcData.end() && md->typeId() != Exiv2::undefined)
|
||||
ok = true;
|
||||
}
|
||||
catch(const Exiv2::AnyError&) {
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
std::string exif_date(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::ExifData::const_iterator md;
|
||||
bool done = exif_data(image, "Exif.Photo.DateTimeDigitized", md);
|
||||
if(!done)
|
||||
done = exif_data(image, "Exif.Photo.DateTimeOriginal", md);
|
||||
if(!done)
|
||||
return "";
|
||||
|
||||
std::string date = scrub(md->print().substr(0,10));
|
||||
// Some files have zeros for dates, just fail in that case
|
||||
if(boost::lexical_cast<int>(date.substr(0,4))==0)
|
||||
return "";
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
std::string exif_year(const Exiv2::Image *image, const fs::path &path)
|
||||
{
|
||||
std::string date = exif_date(image, path);
|
||||
if(date.length())
|
||||
return date.substr(0,4);
|
||||
else
|
||||
return date;
|
||||
}
|
||||
|
||||
std::string exif_month(const Exiv2::Image *image, const fs::path &path)
|
||||
{
|
||||
std::string date = exif_date(image, path);
|
||||
if(date.length())
|
||||
return date.substr(5,2);
|
||||
else
|
||||
return date;
|
||||
}
|
||||
|
||||
std::string exif_day(const Exiv2::Image *image, const fs::path &path)
|
||||
{
|
||||
std::string date = exif_date(image, path);
|
||||
if(date.length())
|
||||
return date.substr(8,2);
|
||||
else
|
||||
return date;
|
||||
}
|
||||
|
||||
bool iptc_get_date(const Exiv2::Image *image, Exiv2::DateValue::Date &date)
|
||||
{
|
||||
Exiv2::IptcData::const_iterator md;
|
||||
bool done = iptc_data(image, "Iptc.Application2.DigitizationDate", md);
|
||||
if(!done)
|
||||
done = iptc_data(image, "Iptc.Application2.DateCreated", md);
|
||||
if(!done)
|
||||
return false;
|
||||
date = ((Exiv2::DateValue*)md->getValue().get())->getDate();
|
||||
return date.year > 0;
|
||||
}
|
||||
|
||||
std::string iptc_date(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::DateValue::Date date;
|
||||
if(iptc_get_date(image, date))
|
||||
return str(boost::format("%4d-%02d-%02d") % date.year % date.month % date.day);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string iptc_year(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::DateValue::Date date;
|
||||
if(iptc_get_date(image, date))
|
||||
return str(boost::format("%4d") % date.year);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string iptc_month(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::DateValue::Date date;
|
||||
if(iptc_get_date(image, date))
|
||||
return str(boost::format("%02d") % date.month);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string iptc_day(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::DateValue::Date date;
|
||||
if(iptc_get_date(image, date))
|
||||
return str(boost::format("%02d") % date.day);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
bool file_get_tm(const fs::path &path, std::tm &tm)
|
||||
{
|
||||
std::time_t timer = fs::last_write_time(path);
|
||||
if(time > 0) {
|
||||
tm = *localtime(&timer);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string file_date(const Exiv2::Image *, const fs::path &path)
|
||||
{
|
||||
std::tm tm;
|
||||
if(file_get_tm(path, tm))
|
||||
return str(boost::format("%4d-%02d-%02d") % (tm.tm_year + 1900) % (tm.tm_mon + 1) % tm.tm_mday);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string file_year(const Exiv2::Image *, const fs::path &path)
|
||||
{
|
||||
std::tm tm;
|
||||
if(file_get_tm(path, tm))
|
||||
return str(boost::format("%4d") % (tm.tm_year + 1900));
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string file_month(const Exiv2::Image *, const fs::path &path)
|
||||
{
|
||||
std::tm tm;
|
||||
if(file_get_tm(path, tm))
|
||||
return str(boost::format("%02d") % (tm.tm_mon + 1));
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string file_day(const Exiv2::Image *, const fs::path &path)
|
||||
{
|
||||
std::tm tm;
|
||||
if(file_get_tm(path, tm))
|
||||
return str(boost::format("%02d") % tm.tm_mday);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
/*
|
||||
std::string xmp_date(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string xmp_year(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string xmp_month(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string xmp_day(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
return "";
|
||||
}*/
|
||||
|
||||
std::string exif_time(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::ExifData::const_iterator md;
|
||||
bool done = exif_data(image, "Exif.Photo.DateTimeDigitized", md);
|
||||
if(!done)
|
||||
done = exif_data(image, "Exif.Photo.DateTimeOriginal", md);
|
||||
if(!done)
|
||||
return "";
|
||||
|
||||
std::string datetime = md->print();
|
||||
// Some files have zeros for dates, just fail in that case
|
||||
if(boost::lexical_cast<int>(datetime.substr(0,4)) == 0)
|
||||
return "";
|
||||
|
||||
return scrub(datetime.substr(11));
|
||||
}
|
||||
|
||||
std::string exif_hour(const Exiv2::Image *image, const fs::path &path)
|
||||
{
|
||||
std::string time = exif_time(image, path);
|
||||
if(time.length())
|
||||
return time.substr(0,2);
|
||||
else
|
||||
return time;
|
||||
}
|
||||
|
||||
std::string exif_minute(const Exiv2::Image *image, const fs::path &path)
|
||||
{
|
||||
std::string time = exif_time(image, path);
|
||||
if(time.length())
|
||||
return time.substr(3,2);
|
||||
else
|
||||
return time;
|
||||
}
|
||||
|
||||
std::string exif_second(const Exiv2::Image *image, const fs::path &path)
|
||||
{
|
||||
std::string time = exif_time(image, path);
|
||||
if(time.length())
|
||||
return time.substr(6,2);
|
||||
else
|
||||
return time;
|
||||
}
|
||||
|
||||
bool iptc_get_time(const Exiv2::Image *image, Exiv2::TimeValue::Time &time)
|
||||
{
|
||||
Exiv2::IptcData::const_iterator md;
|
||||
bool done = iptc_data(image, "Iptc.Application2.DigitizationTime", md);
|
||||
if(!done)
|
||||
done = iptc_data(image, "Iptc.Application2.TimeCreated", md);
|
||||
if(!done)
|
||||
return false;
|
||||
time = ((Exiv2::TimeValue*)md->getValue().get())->getTime();
|
||||
// Zero is a valid time, so this one is hard to check.
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string iptc_time(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::TimeValue::Time time;
|
||||
if(iptc_get_time(image, time))
|
||||
return str(boost::format("%02d-%02d-%02d") % time.hour % time.minute % time.second);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string iptc_hour(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::TimeValue::Time time;
|
||||
if(iptc_get_time(image, time))
|
||||
return str(boost::format("%02d") % time.hour);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string iptc_minute(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::TimeValue::Time time;
|
||||
if(iptc_get_time(image, time))
|
||||
return str(boost::format("%02d") % time.minute);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string iptc_second(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::TimeValue::Time time;
|
||||
if(iptc_get_time(image, time))
|
||||
return str(boost::format("%02d") % time.second);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string file_time(const Exiv2::Image *, const fs::path &path)
|
||||
{
|
||||
std::tm tm;
|
||||
if(file_get_tm(path, tm))
|
||||
return str(boost::format("%02d-%02d-%02d") % tm.tm_hour % tm.tm_min % tm.tm_sec);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string file_hour(const Exiv2::Image *, const fs::path &path)
|
||||
{
|
||||
std::tm tm;
|
||||
if(file_get_tm(path, tm))
|
||||
return str(boost::format("%02d") % tm.tm_hour);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string file_minute(const Exiv2::Image *, const fs::path &path)
|
||||
{
|
||||
std::tm tm;
|
||||
if(file_get_tm(path, tm))
|
||||
return str(boost::format("%02d") % tm.tm_min);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string file_second(const Exiv2::Image *, const fs::path &path)
|
||||
{
|
||||
std::tm tm;
|
||||
if(file_get_tm(path, tm))
|
||||
return str(boost::format("%02d") % tm.tm_sec);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
/*std::string xmp_time(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string xmp_hour(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string xmp_minute(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string xmp_second(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
return "";
|
||||
}*/
|
||||
|
||||
std::string exif_dimension(const Exiv2::Image *image, const fs::path &path)
|
||||
{
|
||||
return exif_width(image, path) + "-" + exif_height(image, path);
|
||||
}
|
||||
|
||||
std::string exif_width(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::ExifData::const_iterator md;
|
||||
bool done = exif_data(image, "Exif.Photo.PixelXDimension", md);
|
||||
if(!done)
|
||||
return "";
|
||||
return scrub(md->print());
|
||||
}
|
||||
|
||||
std::string exif_height(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::ExifData::const_iterator md;
|
||||
bool done = exif_data(image, "Exif.Photo.PixelYDimension", md);
|
||||
if(!done)
|
||||
return "";
|
||||
return scrub(md->print());
|
||||
}
|
||||
|
||||
std::string file_dimension(const Exiv2::Image *image, const fs::path &path)
|
||||
{
|
||||
if(image)
|
||||
return file_width(image, path) + "-" + file_height(image, path);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string file_width(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
if(image)
|
||||
return str(boost::format("%02d") % image->pixelWidth());
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string file_height(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
if(image)
|
||||
return str(boost::format("%02d") % image->pixelHeight());
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
/*
|
||||
std::string xmp_dimension(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
return ""
|
||||
}
|
||||
|
||||
std::string xmp_width(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string xmp_height(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
return "";
|
||||
}*/
|
||||
|
||||
std::string exif_model(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::ExifData::const_iterator md;
|
||||
bool done = exif_data(image, "Exif.Image.Model", md);
|
||||
if(!done)
|
||||
return "";
|
||||
return scrub(md->print());
|
||||
}
|
||||
|
||||
std::string exif_make(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::ExifData::const_iterator md;
|
||||
bool done = exif_data(image, "Exif.Image.Make", md);
|
||||
if(!done)
|
||||
return "";
|
||||
return scrub(md->print());
|
||||
}
|
||||
|
||||
/*std::string xmp_model(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
return "";
|
||||
}*/
|
||||
|
||||
std::string exif_speed(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::ExifData::const_iterator md;
|
||||
bool done = exif_data(image, "Exif.Photo.ShutterSpeedValue", md);
|
||||
if(!done)
|
||||
done = exif_data(image, "Exif.Photo.ExposureTime", md);
|
||||
if(!done)
|
||||
return "";
|
||||
return scrub(md->print());
|
||||
}
|
||||
|
||||
/*std::string xmp_speed(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
return "";
|
||||
}*/
|
||||
|
||||
std::string exif_aperture(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::ExifData::const_iterator md;
|
||||
bool done = exif_data(image, "Exif.Photo.ApertureValue", md);
|
||||
if(!done)
|
||||
done = exif_data(image, "Exif.Photo.FNumber", md);
|
||||
if(!done)
|
||||
return "";
|
||||
return scrub(md->print());
|
||||
}
|
||||
|
||||
/*std::string xmp_aperture(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
return "";
|
||||
}*/
|
||||
|
||||
std::string exif_focal(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::ExifData::const_iterator md;
|
||||
bool done = exif_data(image, "Exif.Photo.FocalLength", md);
|
||||
if(!done)
|
||||
return "";
|
||||
return scrub(md->print());
|
||||
}
|
||||
|
||||
/*std::string xmp_focal(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
return "";
|
||||
}*/
|
||||
|
||||
std::string exif_distance(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::ExifData::const_iterator md;
|
||||
bool done = exif_data(image, "Exif.Photo.SubjectDistance", md);
|
||||
if(!done)
|
||||
return "";
|
||||
return scrub(md->print());
|
||||
}
|
||||
|
||||
/*std::string xmp_distance(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
return "";
|
||||
}*/
|
||||
|
||||
std::string exif_meter(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::ExifData::const_iterator md;
|
||||
bool done = exif_data(image, "Exif.Photo.MeteringMode", md);
|
||||
if(!done)
|
||||
return "";
|
||||
return scrub(md->print());
|
||||
}
|
||||
|
||||
std::string exif_macro(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::ExifData::const_iterator md;
|
||||
bool done = exif_data_easy(image, Exiv2::macroMode, md);
|
||||
if(!done)
|
||||
return "";
|
||||
return scrub(md->print());
|
||||
}
|
||||
|
||||
std::string exif_orientation(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::ExifData::const_iterator md;
|
||||
bool done = exif_data_easy(image, Exiv2::orientation, md);
|
||||
if(!done)
|
||||
return "";
|
||||
return scrub(md->print(), true);
|
||||
}
|
||||
|
||||
std::string exif_lens(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::ExifData::const_iterator md;
|
||||
bool done = exif_data_easy(image, Exiv2::lensName, md);
|
||||
if(!done)
|
||||
return "";
|
||||
return scrub(md->print());
|
||||
}
|
||||
|
||||
|
||||
std::string exif_iso(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::ExifData::const_iterator md;
|
||||
bool done = exif_data_easy(image, Exiv2::isoSpeed, md);
|
||||
if(!done)
|
||||
return "";
|
||||
return scrub(md->print());
|
||||
}
|
||||
|
||||
/*std::string xmp_meter(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
return "";
|
||||
}*/
|
||||
|
||||
std::string exif_keyword(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::ExifData::const_iterator md;
|
||||
bool done = exif_data(image, "Exif.Photo.UserComment", md);
|
||||
if(!done)
|
||||
return "";
|
||||
return scrub(md->print());
|
||||
}
|
||||
|
||||
std::string iptc_keyword(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
Exiv2::IptcData::const_iterator md;
|
||||
bool done = iptc_data(image, "Iptc.Application2.Keywords", md);
|
||||
if(!done)
|
||||
return "";
|
||||
return scrub(md->print());
|
||||
}
|
||||
|
||||
/*std::string xmp_keyword(const Exiv2::Image *image, const fs::path &)
|
||||
{
|
||||
return "";
|
||||
}*/
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue