Skip to content

Commit a7210ca

Browse files
glebmishdictoon
authored andcommitted
Save packed project feature (#1345)
1 parent a135e51 commit a7210ca

File tree

15 files changed

+2973
-273
lines changed

15 files changed

+2973
-273
lines changed

src/appleseed.studio/mainwindow/mainwindow.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,14 +1237,14 @@ void MainWindow::slot_save_project_as()
12371237
get_save_filename(
12381238
this,
12391239
"Save As...",
1240-
"Project Files (*.appleseed)",
1240+
"Plain Project Files (*.appleseed);;Packed Project Files (*.appleseedz)",
12411241
m_settings,
12421242
SETTINGS_FILE_DIALOG_PROJECTS);
12431243

12441244
if (!filepath.isEmpty())
12451245
{
12461246
if (QFileInfo(filepath).suffix().isEmpty())
1247-
filepath += ".appleseed";
1247+
filepath += get_extension(m_settings, SETTINGS_FILE_DIALOG_PROJECTS);
12481248

12491249
filepath = QDir::toNativeSeparators(filepath);
12501250

src/appleseed.studio/mainwindow/project/projectmanager.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,10 @@ bool ProjectManager::save_project()
9494

9595
bool ProjectManager::save_project_as(const string& filepath)
9696
{
97-
return do_save_project(filepath, ProjectFileWriter::Defaults);
97+
if (ends_with(filepath, ".appleseedz"))
98+
return do_save_project(filepath, ProjectFileWriter::PackedProject);
99+
else
100+
return do_save_project(filepath, ProjectFileWriter::Defaults);
98101
}
99102

100103
void ProjectManager::close_project()

src/appleseed.studio/utility/miscellaneous.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,19 @@ namespace
183183
}
184184
}
185185

186+
QString get_extension(ParamArray& settings, const QString& target_dialog)
187+
{
188+
QString filter = get_value(settings, target_dialog + SETTINGS_SELECTED_FILTER);
189+
190+
const int ext_start = filter.lastIndexOf('(') + 2;
191+
const int ext_end = filter.lastIndexOf(')');
192+
193+
if (ext_start != string::npos && ext_end != string::npos && ext_start < ext_end)
194+
return filter.mid(ext_start, ext_end - ext_start);
195+
else
196+
return QString("");
197+
}
198+
186199
QString get_open_filename(
187200
QWidget* parent,
188201
const QString& caption,

src/appleseed.studio/utility/miscellaneous.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ bool file_exists(const QString& path);
6565
// Load an icon and its variants (hover, disabled...) from the application's icons directory.
6666
QIcon load_icons(const QString& base_name);
6767

68+
QString get_extension(renderer::ParamArray& settings, const QString& target_dialog);
69+
6870
QString get_open_filename(
6971
QWidget* parent,
7072
const QString& caption,

src/appleseed/CMakeLists.txt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -454,11 +454,11 @@ set (foundation_meta_tests_sources
454454
foundation/meta/tests/test_transform.cpp
455455
foundation/meta/tests/test_triangulator.cpp
456456
foundation/meta/tests/test_typetraits.cpp
457-
foundation/meta/tests/test_unzipper.cpp
458457
foundation/meta/tests/test_utility_filter.cpp
459458
foundation/meta/tests/test_vector.cpp
460459
foundation/meta/tests/test_voxelgrid.cpp
461460
foundation/meta/tests/test_windows.cpp
461+
foundation/meta/tests/test_zipper.cpp
462462
)
463463
if (WITH_DISNEY_MATERIAL)
464464
list (APPEND foundation_meta_tests_sources
@@ -703,10 +703,13 @@ source_group ("foundation\\utility\\test" FILES
703703
)
704704

705705
set (foundation_utility_minizip_sources
706+
foundation/utility/minizip/crypt.h
706707
foundation/utility/minizip/ioapi.c
707708
foundation/utility/minizip/ioapi.h
708709
foundation/utility/minizip/unzip.c
709710
foundation/utility/minizip/unzip.h
711+
foundation/utility/minizip/zip.c
712+
foundation/utility/minizip/zip.h
710713
)
711714
list (APPEND appleseed_sources
712715
${foundation_utility_minizip_sources}
@@ -772,14 +775,14 @@ set (foundation_utility_sources
772775
foundation/utility/typetraits.h
773776
foundation/utility/uid.cpp
774777
foundation/utility/uid.h
775-
foundation/utility/unzipper.cpp
776-
foundation/utility/unzipper.h
777778
foundation/utility/version.h
778779
foundation/utility/vpythonfile.cpp
779780
foundation/utility/vpythonfile.h
780781
foundation/utility/xercesc.cpp
781782
foundation/utility/xercesc.h
782783
foundation/utility/xmlelement.h
784+
foundation/utility/zipper.cpp
785+
foundation/utility/zipper.h
783786
)
784787
if (WITH_DISNEY_MATERIAL)
785788
list (APPEND foundation_utility_sources

src/appleseed/foundation/meta/tests/test_unzipper.cpp renamed to src/appleseed/foundation/meta/tests/test_zipper.cpp

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
// appleseed.foundation headers.
3030
#include "foundation/utility/test.h"
31-
#include "foundation/utility/unzipper.h"
31+
#include "foundation/utility/zipper.h"
3232

3333
// Boost headers
3434
#include "boost/filesystem.hpp"
@@ -46,31 +46,6 @@ TEST_SUITE(Foundation_Utility_Unzipper)
4646
const string valid_project = "unit tests/inputs/test_packed_project_valid.appleseedz";
4747
const string invalid_project = "unit tests/inputs/test_packed_project_invalid.appleseedz";
4848

49-
set<string> recursive_ls(bf::path dir)
50-
{
51-
set<string> files;
52-
53-
// A default constructed directory_iterator acts as the end iterator
54-
bf::directory_iterator end_iter;
55-
for (bf::directory_iterator dir_itr(dir); dir_itr != end_iter; ++dir_itr)
56-
{
57-
const bf::path current_path = dir_itr->path();
58-
59-
if (bf::is_directory(current_path))
60-
{
61-
const string dirname = current_path.filename().string();
62-
const set<string> files_in_subdir = recursive_ls(current_path);
63-
64-
for (set<string>::iterator it = files_in_subdir.begin(); it != files_in_subdir.end(); ++it)
65-
files.insert(dirname + "/" + *it);
66-
}
67-
else
68-
files.insert(current_path.filename().string());
69-
}
70-
71-
return files;
72-
}
73-
7449
TEST_CASE(UnzipTest)
7550
{
7651
const string unpacked_dir = valid_project + ".unpacked";
@@ -79,8 +54,8 @@ TEST_SUITE(Foundation_Utility_Unzipper)
7954
{
8055
unzip(valid_project, unpacked_dir);
8156

82-
EXPECT_TRUE(bf::exists(bf::path(unpacked_dir)));
83-
EXPECT_FALSE(bf::is_empty(bf::path(unpacked_dir)));
57+
EXPECT_TRUE(bf::exists(unpacked_dir));
58+
EXPECT_FALSE(bf::is_empty(unpacked_dir));
8459

8560
const string expected_files[] =
8661
{
@@ -97,18 +72,18 @@ TEST_SUITE(Foundation_Utility_Unzipper)
9772
"geometry/Plane001.binarymesh"
9873
};
9974

100-
const set<string> actual_files = recursive_ls(bf::path(unpacked_dir));
75+
const set<string> actual_files = recursive_ls(unpacked_dir);
10176

10277
for (size_t i = 0; i < 11; ++i)
10378
{
10479
EXPECT_EQ(1, actual_files.count(expected_files[i]));
10580
}
10681

107-
bf::remove_all(bf::path(unpacked_dir));
82+
bf::remove_all(unpacked_dir);
10883
}
10984
catch (exception e)
11085
{
111-
bf::remove_all(bf::path(unpacked_dir));
86+
bf::remove_all(unpacked_dir);
11287
throw e;
11388
}
11489
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/* crypt.h -- base code for crypt/uncrypt ZIPfile
2+
3+
4+
Version 1.01e, February 12th, 2005
5+
6+
Copyright (C) 1998-2005 Gilles Vollant
7+
8+
This code is a modified version of crypting code in Infozip distribution
9+
10+
The encryption/decryption parts of this source code (as opposed to the
11+
non-echoing password parts) were originally written in Europe. The
12+
whole source package can be freely distributed, including from the USA.
13+
(Prior to January 2000, re-export from the US was a violation of US law.)
14+
15+
This encryption code is a direct transcription of the algorithm from
16+
Roger Schlafly, described by Phil Katz in the file appnote.txt. This
17+
file (appnote.txt) is distributed with the PKZIP program (even in the
18+
version without encryption capabilities).
19+
20+
If you don't need crypting in your application, just define symbols
21+
NOCRYPT and NOUNCRYPT.
22+
23+
This code support the "Traditional PKWARE Encryption".
24+
25+
The new AES encryption added on Zip format by Winzip (see the page
26+
http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
27+
Encryption is not supported.
28+
*/
29+
30+
#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
31+
32+
/***********************************************************************
33+
* Return the next byte in the pseudo-random sequence
34+
*/
35+
static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab)
36+
{
37+
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
38+
* unpredictable manner on 16-bit systems; not a problem
39+
* with any known compiler so far, though */
40+
41+
temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
42+
return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
43+
}
44+
45+
/***********************************************************************
46+
* Update the encryption keys with the next byte of plain text
47+
*/
48+
static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c)
49+
{
50+
(*(pkeys+0)) = CRC32((*(pkeys+0)), c);
51+
(*(pkeys+1)) += (*(pkeys+0)) & 0xff;
52+
(*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
53+
{
54+
register int keyshift = (int)((*(pkeys+1)) >> 24);
55+
(*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
56+
}
57+
return c;
58+
}
59+
60+
61+
/***********************************************************************
62+
* Initialize the encryption keys and the random header according to
63+
* the given password.
64+
*/
65+
static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab)
66+
{
67+
*(pkeys+0) = 305419896L;
68+
*(pkeys+1) = 591751049L;
69+
*(pkeys+2) = 878082192L;
70+
while (*passwd != '\0') {
71+
update_keys(pkeys,pcrc_32_tab,(int)*passwd);
72+
passwd++;
73+
}
74+
}
75+
76+
#define zdecode(pkeys,pcrc_32_tab,c) \
77+
(update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
78+
79+
#define zencode(pkeys,pcrc_32_tab,c,t) \
80+
(t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
81+
82+
#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
83+
84+
#define RAND_HEAD_LEN 12
85+
/* "last resort" source for second part of crypt seed pattern */
86+
# ifndef ZCR_SEED2
87+
# define ZCR_SEED2 3141592654UL /* use PI as default pattern */
88+
# endif
89+
90+
static int crypthead(const char* passwd, /* password string */
91+
unsigned char* buf, /* where to write header */
92+
int bufSize,
93+
unsigned long* pkeys,
94+
const z_crc_t* pcrc_32_tab,
95+
unsigned long crcForCrypting)
96+
{
97+
int n; /* index in random header */
98+
int t; /* temporary */
99+
int c; /* random byte */
100+
unsigned char header[RAND_HEAD_LEN-2]; /* random header */
101+
static unsigned calls = 0; /* ensure different random header each time */
102+
103+
if (bufSize<RAND_HEAD_LEN)
104+
return 0;
105+
106+
/* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
107+
* output of rand() to get less predictability, since rand() is
108+
* often poorly implemented.
109+
*/
110+
if (++calls == 1)
111+
{
112+
srand((unsigned)(time(NULL) ^ ZCR_SEED2));
113+
}
114+
init_keys(passwd, pkeys, pcrc_32_tab);
115+
for (n = 0; n < RAND_HEAD_LEN-2; n++)
116+
{
117+
c = (rand() >> 7) & 0xff;
118+
header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
119+
}
120+
/* Encrypt random header (last two bytes is high word of crc) */
121+
init_keys(passwd, pkeys, pcrc_32_tab);
122+
for (n = 0; n < RAND_HEAD_LEN-2; n++)
123+
{
124+
buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
125+
}
126+
buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
127+
buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
128+
return n;
129+
}
130+
131+
#endif

0 commit comments

Comments
 (0)