Skip to content

Commit f6aaba6

Browse files
authored
First relaese at darktable github
1 parent 694b6c4 commit f6aaba6

File tree

1 file changed

+323
-0
lines changed

1 file changed

+323
-0
lines changed

contrib/steghideexport.lua

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
--[[
2+
Steghide storage for darktable
3+
4+
copyright (c) 2016 Holger Klemm
5+
6+
darktable is free software: you can redistribute it and/or modify
7+
it under the terms of the GNU General Public License as published by
8+
the Free Software Foundation, either version 3 of the License, or
9+
(at your option) any later version.
10+
11+
darktable is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU General Public License for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with darktable. If not, see <http://www.gnu.org/licenses/>.
18+
]]
19+
20+
--[[
21+
Version 2.1
22+
23+
24+
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
25+
* steghide
26+
27+
USAGE
28+
* require this file from your main luarc config file.
29+
30+
This plugin will add a new storage option and calls hugin after export.
31+
]]
32+
33+
local dt = require "darktable"
34+
local gettext = dt.gettext
35+
36+
-- works only with darktable API version 4.0.0
37+
dt.configuration.check_version(...,{4,0,0})
38+
39+
-- Tell gettext where to find the .mo file translating messages for a particular domain
40+
gettext.bindtextdomain("steghideexport",dt.configuration.config_dir.."/lua/")
41+
42+
local function _(msgid)
43+
return gettext.dgettext("steghideexport", msgid)
44+
end
45+
46+
47+
48+
49+
local check_button_selected_file = dt.new_widget("check_button")
50+
{
51+
label = _('Use selected text file'),
52+
value = true,
53+
tooltip =_('Default text file: ~/.config/darktable/steghide/steghide_default'),
54+
reset_callback = function(self)
55+
self.value = true
56+
end
57+
58+
}
59+
60+
61+
local check_button_usertext = dt.new_widget("check_button")
62+
{
63+
label = _('Use user text line'),
64+
value = false,
65+
tooltip =_('Embed the user text line'),
66+
reset_callback = function(self)
67+
self.value = false
68+
end
69+
70+
}
71+
72+
73+
local label_password = dt.new_widget("label")
74+
{
75+
label = _('Password:'),
76+
ellipsize = "start",
77+
halign = "start",
78+
tooltip = _('Steghide requires a password')
79+
}
80+
81+
local entrypassword = dt.new_widget("entry")
82+
{
83+
text = "",
84+
placeholder = _('Please enter a password'),
85+
is_password = false,
86+
editable = true,
87+
tooltip = _('Enter a password'),
88+
reset_callback = function(self)
89+
self.text = ""
90+
end
91+
}
92+
93+
94+
local label_usertext= dt.new_widget("label")
95+
{
96+
label = _('User text line:'),
97+
ellipsize = "start",
98+
halign = "start"
99+
}
100+
101+
102+
local entrytext = dt.new_widget("entry")
103+
{
104+
text = "",
105+
sensitive = true,
106+
is_password = true,
107+
editable = true,
108+
tooltip = _('Enter the user text to embed'),
109+
reset_callback = function(self)
110+
self.text = ""
111+
end
112+
113+
}
114+
115+
116+
local label_path = dt.new_widget("label")
117+
{
118+
label = _('Target directory:'),
119+
ellipsize = "start",
120+
halign = "start"
121+
}
122+
123+
local label_textfile= dt.new_widget("label")
124+
{
125+
label = _('Selected text file:'),
126+
ellipsize = "start",
127+
halign = "start"
128+
}
129+
130+
local label_enc= dt.new_widget("label")
131+
{
132+
label = _('Encryption algorithm / mode:'),
133+
ellipsize = "start",
134+
halign = "start"
135+
}
136+
137+
138+
-- Target directory dialog
139+
local file_chooser_button = dt.new_widget("file_chooser_button")
140+
{
141+
title = _('Export Steghide JPEG'), -- The title of the window when choosing a file
142+
is_directory = true -- True if the file chooser button only allows directories to be selecte
143+
}
144+
145+
146+
-- Text file dialog
147+
local textfile_chooser_button = dt.new_widget("file_chooser_button")
148+
{
149+
title = _('Text file'), -- The title of the window when choosing a file
150+
value = ".config/darktable/steghide/steghide_default",
151+
reset_callback = function(self)
152+
self.value = ".config/darktable/steghide/steghide_default"
153+
end
154+
}
155+
156+
157+
local selection = dt.gui.selection()
158+
local result = ""
159+
local array = {}
160+
for _,img in pairs(selection) do
161+
array[img.path] = true
162+
end
163+
for path in pairs(array) do
164+
if result == "" then
165+
result = path
166+
else
167+
result = result.."\n"..path
168+
end
169+
end
170+
file_chooser_button.value = result
171+
172+
local enc_combobox = dt.new_widget("combobox")
173+
{
174+
label = "",
175+
value = 15, "cast-128 cbc", "cast-128 cfb", "cast-128 ctr","cast-128 ecb","cast-128 ncfb","cast-128 nofb","cast-128 ofb","gost cbc","gost cfb","gost ctr","gost ecb","gost ncfb","gost nofb","gost ofb","rijndael-128 cbc","rijndael-128 cfb","rijndael-128 ctr","rijndael-128 ecb","rijndael-128 ncfb","rijndael-128 nofb","rijndael-128 ofb","twofish cbc","twofish cfb","twofish ctr","twofish ecb","twofish ncfb","twofish nofb","twofish ofb","arcfour stream","cast-256 cbc","cast-256 cfb","cast-256 ctr","cast-256 ecb","cast-256 ncfb","cast-256 nofb","cast-256 ofb","loki97 cbc","loki97 cfb","loki97 ctr","loki97 ecb","loki97 ncfb","loki97 nofb","loki97 ofb","rijndael-192 cbc","rijndael-192 cfb","rijndael-192 ctr","rijndael-192 ecb","rijndael-192 ncfb","rijndael-192 nofb","rijndael-192 ofb","saferplus cbc","saferplus cfb","saferplus ctr","saferplus ecb","saferplus ncfb","saferplus nofb","saferplus ofb","wake stream","des cbc","des cfb","des ctr","des ecb","des ncfb","des nofb","des ofb","rijndael-256 cbc","rijndael-256 cfb","rijndael-256 ctr","rijndael-256 ecb","rijndael-256 ncfb","rijndael-256 nofb","rijndael-256 ofb","serpent cbc","serpent cfb","serpent ctr","serpent ecb","serpent ncfb","serpent nofb","serpent ofb","xtea cbc","xtea cfb","xtea ctr","xtea ecb","xtea ncfb","xtea nofb","xtea ofb","blowfish cbc","blowfish cfb","blowfish ctr","blowfish ecb","blowfish ncfb","blowfish nofb","blowfish ofb","enigma stream","rc2 cbc","rc2 cfb","rc2 ctr","rc2 ecb","rc2 ncfb","rc2 nofb","rc2 ofb","tripledes cbc","tripledes cfb","tripledes ctr","tripledes ecb","tripledes ncfb","tripledes nofb","tripledes ofb",
176+
reset_callback = function(self)
177+
self.value = 15
178+
end
179+
}
180+
181+
182+
local widget = dt.new_widget("box") {
183+
orientation = "vertical",
184+
check_button_selected_file,
185+
check_button_usertext,
186+
label_textfile,
187+
textfile_chooser_button,
188+
label_usertext,
189+
entrytext,
190+
label_password,
191+
entrypassword,
192+
label_enc,
193+
enc_combobox,
194+
label_path,
195+
file_chooser_button,
196+
}
197+
198+
199+
200+
local function checkIfBinExists(bin)
201+
local handle = io.popen("which "..bin)
202+
local result = handle:read()
203+
local ret
204+
handle:close()
205+
if (result) then
206+
-- dt.print_error("true checkIfBinExists: "..bin)
207+
ret = true
208+
else
209+
dt.print_error(bin.." not found")
210+
ret = false
211+
end
212+
213+
214+
return ret
215+
end
216+
217+
218+
219+
local function show_status(storage, image, format, filename,
220+
number, total, high_quality, extra_data)
221+
if (not (entrypassword.text == "")) then
222+
dt.print(_('Export JPEG to Steghide ')..tostring(number).."/"..tostring(total))
223+
else
224+
dt.print(_('ERROR: No password found'))
225+
end
226+
end
227+
228+
229+
encmode = enc_combobox.value
230+
231+
local function create_steghidefoto(storage, image_table, extra_data) --finalize
232+
if (not (checkIfBinExists("steghide"))) then
233+
dt.print(_('ERROR: Steghide not found. Please install steghide.'))
234+
dt.print_error(_('Steghide not found. Please install steghide.'))
235+
return
236+
end
237+
238+
local steghide_executor = false
239+
if (checkIfBinExists("steghide")) then
240+
steghide_executor = true
241+
end
242+
243+
244+
-- password check
245+
steghidepassword = entrypassword.text
246+
if steghidepassword =="" then
247+
dt.print(_('ERROR: No password found'))
248+
else
249+
dt.print(_('Will try to embed text'))
250+
251+
-- textline check
252+
if ((check_button_usertext.value) and (entrytext.text == "")) then
253+
dt.print(_('ERROR: No user text found'))
254+
else
255+
256+
257+
-- create text file
258+
if ((check_button_selected_file.value) and (check_button_usertext.value)) then
259+
textline = entrytext.text
260+
default_file = io.open(textfile_chooser_button.value,"r")
261+
defaulttext = default_file:read("*a")
262+
combinetext = defaulttext.."\n\n"..textline
263+
combine_file = io.open("/tmp/steghide_combine", "w")
264+
combine_file:write(combinetext)
265+
io.close(combine_file)
266+
textfile = "/tmp/steghide_combine"
267+
elseif (check_button_selected_file.value) then
268+
textfile = textfile_chooser_button.value
269+
elseif (check_button_usertext.value) then
270+
textline_file = io.open("/tmp/steghide_text_line", "w")
271+
textline_file:write(entrytext.text)
272+
io.close(textline_file)
273+
textfile = "/tmp/steghide_text_line"
274+
elseif ((textfile =="") or (textfile=="(None)")) then
275+
dt.print(_('ERROR: No textfile created or selected'))
276+
return
277+
else
278+
dt.print(_('ERROR: No text file selected'))
279+
return
280+
end
281+
282+
283+
-- embed text with steghide
284+
local steghideStartCommand
285+
img_path = file_chooser_button.value
286+
if (steghide_executor) then
287+
if (textfile =="") then
288+
dt.print(_('ERROR: No textfile created or selected'))
289+
return
290+
else
291+
dt.print(_('Embeding text...'))
292+
for _,v in pairs(image_table) do
293+
steghideStartCommand = "steghide --embed --encryption " ..encmode.. " --nochecksum -q -p " ..steghidepassword.. " -cf "..v.." -ef "..textfile
294+
dt.control.execute( steghideStartCommand)
295+
moveFileCommand = "mv " ..v.. " "..img_path
296+
dt.control.execute( moveFileCommand)
297+
end
298+
end
299+
else
300+
dt.print(_('ERROR: Embeding not working'))
301+
end
302+
end
303+
304+
end
305+
306+
end
307+
308+
309+
-- limit export to jpeg (8 bit)
310+
local function support_format(storage, format)
311+
fmt = string.lower(format.name)
312+
if string.match(fmt,"jpeg%s%g8%sbit%g") == nil then
313+
return false
314+
else
315+
return true
316+
end
317+
end
318+
319+
320+
321+
-- Register
322+
dt.register_storage("module_steghide", _('Steghide JPEG Photo'), show_status, create_steghidefoto, support_format, nil, widget)
323+

0 commit comments

Comments
 (0)