indent -kr -i8 -brf -bbb -fnc -l132 -nce on all of webcit-classic
[citadel.git] / webcit / icontheme.c
1
2 /*
3  * Displays and customizes the iconbar.
4  *
5  * Copyright (c) 1996-2012 by the citadel.org team
6  *
7  * This program is open source software.  You can redistribute it and/or
8  * modify it under the terms of the GNU General Public License, version 3.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <dirent.h>
19 #include <errno.h>
20
21 #include <unistd.h>
22 #include <stdio.h>
23 #include <stdarg.h>
24 #include <stddef.h>
25
26 #include "webcit.h"
27 #include "webserver.h"
28
29 HashList *AvailableThemes = NULL;
30
31 const StrBuf *DefaultTheme = NULL;
32 void LoadIconthemeSettings(StrBuf * icontheme, long lvalue) {
33         wcsession *WCC = WC;
34         void *vTheme;
35         const StrBuf *theme;
36
37         if (GetHash(AvailableThemes, SKEY(icontheme), &vTheme))
38                 theme = (StrBuf *) vTheme;
39         else
40                 theme = DefaultTheme;
41
42         if (WCC->IconTheme != NULL)
43                 StrBufPlain(WCC->IconTheme, SKEY(theme));
44         else
45                 WCC->IconTheme = NewStrBufDup(theme);
46 }
47
48
49 void tmplput_icontheme(StrBuf * Target, WCTemplputParams * TP) {
50         wcsession *WCC = WC;
51         if ((WCC != NULL) && (WCC->IconTheme != NULL)) {
52                 StrBufAppendTemplate(Target, TP, WCC->IconTheme, 0);
53         }
54         else {
55                 StrBufAppendTemplate(Target, TP, DefaultTheme, 0);
56         }
57 }
58
59
60 int LoadThemeDir(const char *DirName) {
61         StrBuf *Dir = NULL;
62         DIR *filedir = NULL;
63         struct dirent *d;
64         struct dirent *filedir_entry;
65         int d_type = 0;
66         int d_namelen;
67
68         filedir = opendir(DirName);
69         if (filedir == NULL) {
70                 return 0;
71         }
72
73         d = (struct dirent *) malloc(offsetof(struct dirent, d_name) + PATH_MAX + 1);
74         if (d == NULL) {
75                 return 0;
76         }
77
78         while ((readdir_r(filedir, d, &filedir_entry) == 0) && (filedir_entry != NULL)) {
79 #ifdef _DIRENT_HAVE_D_NAMELEN
80                 d_namelen = filedir_entry->d_namlen;
81                 d_type = filedir_entry->d_type;
82 #else
83
84 #ifndef DT_UNKNOWN
85 #define DT_UNKNOWN     0
86 #define DT_DIR         4
87 #define DT_REG         8
88 #define DT_LNK         10
89
90 #define IFTODT(mode)   (((mode) & 0170000) >> 12)
91 #define DTTOIF(dirtype)        ((dirtype) << 12)
92 #endif
93                 d_namelen = strlen(filedir_entry->d_name);
94                 d_type = DT_UNKNOWN;
95 #endif
96                 if ((d_namelen > 1) && filedir_entry->d_name[d_namelen - 1] == '~')
97                         continue;       /* Ignore backup files... */
98
99                 if ((d_namelen == 1) && (filedir_entry->d_name[0] == '.'))
100                         continue;
101
102                 if ((d_namelen == 2) && (filedir_entry->d_name[0] == '.') && (filedir_entry->d_name[1] == '.'))
103                         continue;
104
105                 if (d_type == DT_UNKNOWN) {
106                         struct stat s;
107                         char path[PATH_MAX];
108                         snprintf(path, PATH_MAX, "%s/%s", DirName, filedir_entry->d_name);
109                         if (stat(path, &s) == 0) {
110                                 d_type = IFTODT(s.st_mode);
111                         }
112                 }
113
114                 switch (d_type) {
115                 case DT_LNK:    /* TODO: check whether its a file or a directory */
116                 case DT_DIR:
117                         /* Skip directories we are not interested in... */
118                         if ((strcmp(filedir_entry->d_name, ".svn") == 0) || (strcmp(filedir_entry->d_name, "t") == 0))
119                                 break;
120
121                         Dir = NewStrBufPlain(filedir_entry->d_name, d_namelen);
122                         if (DefaultTheme == NULL)
123                                 DefaultTheme = Dir;
124                         Put(AvailableThemes, SKEY(Dir), Dir, HFreeStrBuf);
125                         break;
126                 case DT_REG:
127                 default:
128                         break;
129                 }
130
131
132         }
133         free(d);
134         closedir(filedir);
135
136         return 1;
137 }
138
139 HashList *GetValidThemeHash(StrBuf * Target, WCTemplputParams * TP) {
140         return AvailableThemes;
141 }
142
143 void ServerStartModule_ICONTHEME(void) {
144         AvailableThemes = NewHash(1, NULL);
145 }
146
147 void InitModule_ICONTHEME(void) {
148         StrBuf *Themes = NewStrBufPlain(static_dirs[0], -1);
149
150         StrBufAppendBufPlain(Themes, HKEY("/"), 0);
151         StrBufAppendBufPlain(Themes, HKEY("webcit_icons"), 0);
152         LoadThemeDir(ChrPtr(Themes));
153         FreeStrBuf(&Themes);
154
155         RegisterPreference("icontheme", _("Icon Theme"), PRF_STRING, LoadIconthemeSettings);
156         RegisterNamespace("ICONTHEME", 0, 0, tmplput_icontheme, NULL, CTX_NONE);
157
158         RegisterIterator("PREF:VALID:THEME", 0, NULL, GetValidThemeHash, NULL, NULL, CTX_STRBUF, CTX_NONE, IT_NOFLAG);
159 }
160
161 void ServerShutdownModule_ICONTHEME(void) {
162         DeleteHash(&AvailableThemes);
163 }
164
165 void SessionDestroyModule_ICONTHEME(wcsession * sess) {
166         FreeStrBuf(&sess->IconTheme);
167 }