getDefaultMusicDir(MUS_CLASSIC_SUBDIR) : "");
}
-static char *getUserGraphicsDir(void)
+char *getUserGraphicsDir(void)
{
static char *usergraphics_dir = NULL;
return usergraphics_dir;
}
-static char *getUserSoundsDir(void)
+char *getUserSoundsDir(void)
{
static char *usersounds_dir = NULL;
return usersounds_dir;
}
-static char *getUserMusicDir(void)
+char *getUserMusicDir(void)
{
static char *usermusic_dir = NULL;
// functions for loading level info and custom artwork info
// ----------------------------------------------------------------------------
+int GetZipFileTreeType(char *zip_filename)
+{
+ static char *top_dir_path = NULL;
+ static char *top_dir_conf_filename[NUM_BASE_TREE_TYPES] = { NULL };
+ static char *conf_basename[NUM_BASE_TREE_TYPES] =
+ {
+ GRAPHICSINFO_FILENAME,
+ SOUNDSINFO_FILENAME,
+ MUSICINFO_FILENAME,
+ LEVELINFO_FILENAME
+ };
+ int j;
+
+ checked_free(top_dir_path);
+ top_dir_path = NULL;
+
+ for (j = 0; j < NUM_BASE_TREE_TYPES; j++)
+ {
+ checked_free(top_dir_conf_filename[j]);
+ top_dir_conf_filename[j] = NULL;
+ }
+
+ char **zip_entries = zip_list(zip_filename);
+
+ // check if zip file successfully opened
+ if (zip_entries == NULL || zip_entries[0] == NULL)
+ return TREE_TYPE_UNDEFINED;
+
+ // first zip file entry is expected to be top level directory
+ char *top_dir = zip_entries[0];
+
+ // check if valid top level directory found in zip file
+ if (!strSuffix(top_dir, "/"))
+ return TREE_TYPE_UNDEFINED;
+
+ // get filenames of valid configuration files in top level directory
+ for (j = 0; j < NUM_BASE_TREE_TYPES; j++)
+ top_dir_conf_filename[j] = getStringCat2(top_dir, conf_basename[j]);
+
+ int tree_type = TREE_TYPE_UNDEFINED;
+ int e = 0;
+
+ while (zip_entries[e] != NULL)
+ {
+ // check if every zip file entry is below top level directory
+ if (!strPrefix(zip_entries[e], top_dir))
+ return TREE_TYPE_UNDEFINED;
+
+ // check if this zip file entry is a valid configuration filename
+ for (j = 0; j < NUM_BASE_TREE_TYPES; j++)
+ {
+ if (strEqual(zip_entries[e], top_dir_conf_filename[j]))
+ {
+ // only exactly one valid configuration file allowed
+ if (tree_type != TREE_TYPE_UNDEFINED)
+ return TREE_TYPE_UNDEFINED;
+
+ tree_type = j;
+ }
+ }
+
+ e++;
+ }
+
+ return tree_type;
+}
+
static boolean CheckZipFileForDirectory(char *zip_filename, char *directory,
int tree_type)
{
return TRUE;
}
-static boolean ExtractZipFileIntoDirectory(char *zip_filename, char *directory,
- int tree_type)
+char *ExtractZipFileIntoDirectory(char *zip_filename, char *directory,
+ int tree_type)
{
boolean zip_file_valid = CheckZipFileForDirectory(zip_filename, directory,
tree_type);
- Error(ERR_DEBUG, "zip file '%s': %s", zip_filename,
- (zip_file_valid ? "EXTRACT" : "REJECT"));
-
if (!zip_file_valid)
- return FALSE;
+ {
+ Error(ERR_WARN, "zip file '%s' rejected!", zip_filename);
+
+ return NULL;
+ }
char **zip_entries = zip_extract(zip_filename, directory);
- boolean zip_file_extracted = (zip_entries != NULL);
+ if (zip_entries == NULL)
+ {
+ Error(ERR_WARN, "zip file '%s' could not be extracted!", zip_filename);
- if (zip_file_extracted)
- Error(ERR_DEBUG, "zip file successfully extracted!");
- else
- Error(ERR_DEBUG, "zip file could not be extracted!");
+ return NULL;
+ }
+
+ Error(ERR_INFO, "zip file '%s' successfully extracted!", zip_filename);
+
+ // first zip file entry contains top level directory
+ char *top_dir = zip_entries[0];
+
+ // remove trailing directory separator from top level directory
+ top_dir[strlen(top_dir) - 1] = '\0';
- return zip_file_extracted;
+ return top_dir;
}
static void ProcessZipFilesInDirectory(char *directory, int tree_type)
if (!fileExists(zip_filename_extracted) &&
!fileExists(zip_filename_rejected))
{
- boolean zip_file_extracted = ExtractZipFileIntoDirectory(zip_filename,
- directory,
- tree_type);
- char *marker_filename = (zip_file_extracted ? zip_filename_extracted :
+ char *top_dir = ExtractZipFileIntoDirectory(zip_filename, directory,
+ tree_type);
+ char *marker_filename = (top_dir != NULL ? zip_filename_extracted :
zip_filename_rejected);
FILE *marker_file;
Error(ERR_EXIT, "internal level set structure corrupted -- aborting");
}
+static boolean AddUserArtworkSetToArtworkInfoExt(char *artwork_subdir_new,
+ int type)
+{
+ // get artwork info tree node of first artwork set
+ TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
+ char *artwork_user_dir = USER_ARTWORK_DIRECTORY(type);
+
+ int draw_deactivation_mask = GetDrawDeactivationMask();
+
+ // override draw deactivation mask (temporarily disable drawing)
+ SetDrawDeactivationMask(REDRAW_ALL);
+
+ // load new artwork set config and add it next to first artwork set
+ LoadArtworkInfoFromArtworkConf(&artwork_first_node->next, NULL,
+ artwork_user_dir, artwork_subdir_new, type);
+
+ // set draw deactivation mask to previous value
+ SetDrawDeactivationMask(draw_deactivation_mask);
+
+ // get artwork info tree node of newly added artwork set
+ LevelDirTree *artwork_new = getTreeInfoFromIdentifier(artwork_first_node,
+ artwork_subdir_new);
+ if (artwork_new == NULL) // should not happen
+ return FALSE;
+
+ // correct top link and parent node link of newly created tree node
+ artwork_new->node_top = artwork_first_node->node_top;
+ artwork_new->node_parent = artwork_first_node->node_parent;
+
+ // sort artwork info tree to adjust position of newly added artwork set
+ sortTreeInfo(&artwork_first_node);
+
+ return TRUE;
+}
+
+void AddUserArtworkSetToArtworkInfo(char *artwork_subdir_new, int type)
+{
+ if (!AddUserArtworkSetToArtworkInfoExt(artwork_subdir_new, type))
+ Error(ERR_EXIT, "internal artwork set structure corrupted -- aborting");
+}
+
+static boolean AddUserTreeSetToTreeInfoExt(char *tree_subdir_new, int type)
+{
+ TreeInfo **tree_node_first, *tree_node_old, *tree_node_new;
+ char *tree_user_dir = TREE_USERDIR(type);
+
+ if (tree_user_dir == NULL) // should not happen
+ return FALSE;
+
+ // get first node of level or artwork tree
+ tree_node_first = TREE_FIRST_NODE_PTR(type);
+
+ if (tree_node_first == NULL) // should not happen
+ return FALSE;
+
+ if (type == TREE_TYPE_LEVEL_DIR)
+ {
+ // get level info tree node of personal user level set
+ tree_node_old = getTreeInfoFromIdentifier(*tree_node_first, getLoginName());
+ }
+ else
+ {
+ // get artwork info tree node of first artwork set
+ tree_node_old = *tree_node_first;
+ }
+
+ if (tree_node_old == NULL) // should not happen
+ return FALSE;
+
+ int draw_deactivation_mask = GetDrawDeactivationMask();
+
+ // override draw deactivation mask (temporarily disable drawing)
+ SetDrawDeactivationMask(REDRAW_ALL);
+
+ if (type == TREE_TYPE_LEVEL_DIR)
+ {
+ // load new level set config and add it next to first user level set
+ LoadLevelInfoFromLevelConf(&tree_node_old->next, NULL,
+ tree_user_dir, tree_subdir_new);
+ }
+ else
+ {
+ // load new artwork set config and add it next to first artwork set
+ LoadArtworkInfoFromArtworkConf(&tree_node_old->next, NULL,
+ tree_user_dir, tree_subdir_new, type);
+ }
+
+ // set draw deactivation mask to previous value
+ SetDrawDeactivationMask(draw_deactivation_mask);
+
+ // get tree info tree node of newly added tree set
+ tree_node_new = getTreeInfoFromIdentifier(*tree_node_first, tree_subdir_new);
+
+ if (tree_node_new == NULL) // should not happen
+ return FALSE;
+
+ // correct top link and parent node link of newly created tree node
+ tree_node_new->node_top = tree_node_old->node_top;
+ tree_node_new->node_parent = tree_node_old->node_parent;
+
+ // sort tree info tree to adjust position of newly added tree set
+ sortTreeInfo(tree_node_first);
+
+ return TRUE;
+}
+
+void AddUserTreeSetToTreeInfo(char *tree_subdir_new, int type)
+{
+ if (!AddUserTreeSetToTreeInfoExt(tree_subdir_new, type))
+ Error(ERR_EXIT, "internal tree set structure corrupted -- aborting");
+}
+
char *getArtworkIdentifierForUserLevelSet(int type)
{
char *classic_artwork_set = getClassicArtworkSet(type);