Fix even more leaks
[pandora-libraries.git] / minimenu / mmcustom_cats.c
1
2 #include <stdio.h>
3 #include <limits.h> /* for PATH_MAX */
4 #define __USE_GNU /* for strndup */
5 #include <string.h> /* for strdup */
6 #include <stdlib.h> /* getenv */
7
8 #include "pnd_container.h"
9 #include "pnd_conf.h"
10 #include "pnd_discovery.h"
11 #include "pnd_notify.h"
12 #include "pnd_dbusnotify.h"
13 #include "pnd_logger.h"
14
15 #include "mmenu.h"
16 #include "mmcustom_cats.h"
17
18 mmcustom_cat_t mmcustom_complete [ MMCUSTOM_CATS_MAX ];
19 unsigned int mmcustom_count = 0;
20
21 pnd_conf_handle g_custom_h = 0;
22
23 char *mmcustom_determine_path ( void ) {
24   char *home = getenv ( "HOME" );
25   static char path [ PATH_MAX ];
26   bzero ( path, PATH_MAX );
27
28   snprintf ( path, PATH_MAX - 1, "%s/%s", home ? home : ".", MMCUSTOM_CATS_PREF_FILENAME );
29
30   return ( path );
31 }
32
33 static unsigned char loaded = 0;
34 unsigned char mmcustom_setup ( void ) {
35
36   if ( ! loaded ) {
37     loaded = 1;
38
39     // inhale conf file
40     char *path = mmcustom_determine_path();
41
42     g_custom_h = pnd_conf_fetch_by_path ( path );
43
44     if ( ! g_custom_h ) {
45       pnd_log ( pndn_rem, "Custom category conf file %s not found; is okay.\n", path );
46       return ( 1 ); // file does not exist most likely
47     }
48
49     // find its head; if no head (empty file), bail
50     char *iter = pnd_box_get_head ( g_custom_h );
51
52     if ( ! iter ) {
53       pnd_log ( pndn_rem, "Custom category conf file %s is empty. Fine.\n", path );
54       return ( 1 );
55     }
56
57     // walk the conf, plucking out the values
58     while ( iter ) {
59       char *k = pnd_box_get_key ( iter );
60
61       // does this entry look like it is a custom category?
62       if ( strncmp ( k, MMCUSTOM_CATS_SECTION, strlen ( MMCUSTOM_CATS_SECTION ) ) == 0 ) {
63         // determine the actual category name part
64         k += ( strlen ( MMCUSTOM_CATS_SECTION ) + 1 );
65
66         mmcustom_complete [ mmcustom_count ].cat = strdup ( k );
67         if ( iter && strcmp ( iter, MMCUSTOM_CATS_NOCAT ) != 0 ) {
68           mmcustom_complete [ mmcustom_count ].parent_cat = strdup ( iter );
69         } else {
70           mmcustom_complete [ mmcustom_count ].parent_cat = NULL;
71         }
72
73         mmcustom_count += 1;
74
75       }
76
77       // next!
78       iter = pnd_box_get_next ( iter );
79
80     } // while
81
82     //pnd_log ( pndn_rem, "Found %u custom categories.\n", mmcustom_count );
83
84   } // loaded already?
85
86   return ( 1 );
87 }
88
89 void mmcustom_shutdown ( void ) {
90
91   bzero ( mmcustom_complete, sizeof(mmcustom_cat_t) * MMCUSTOM_CATS_MAX );
92   mmcustom_count = 0;
93   loaded = 0;
94
95   return;
96 }
97
98 unsigned char mmcustom_is_ready ( void ) {
99   return ( loaded );
100 }
101
102 unsigned char mmcustom_write ( char *fullpath /* if NULL, uses canonical location */ ) {
103
104   if ( ! fullpath ) {
105     fullpath = mmcustom_determine_path();
106   }
107
108   FILE *f = fopen ( fullpath, "w" );
109
110   if ( ! f ) {
111     return ( 0 );
112   }
113
114   int i;
115   for ( i = 0; i < mmcustom_count; i++ ) {
116     if ( mmcustom_complete [ i ].cat ) {
117       fprintf ( f, "%s.%s\t%s\n", MMCUSTOM_CATS_SECTION, mmcustom_complete [ i ].cat, mmcustom_complete [ i ].parent_cat ? mmcustom_complete [ i ].parent_cat : MMCUSTOM_CATS_NOCAT );
118     }
119   }
120
121   fclose ( f );
122
123   return ( 1 );
124 }
125
126 mmcustom_cat_t *mmcustom_query ( char *name, char *parentcatname ) {
127   int i;
128
129   // search for the cat/parent combination
130   for ( i = 0; i < mmcustom_count; i++ ) {
131     mmcustom_cat_t *p = &(mmcustom_complete [ i ]);
132
133     if ( strcasecmp ( p -> cat, name ) == 0 ) {
134
135       if ( parentcatname == NULL && p -> parent_cat == NULL ) {
136         return ( p );
137       } else if ( parentcatname && p -> parent_cat && strcasecmp ( p -> parent_cat, parentcatname ) == 0 ) {
138         return ( p );
139       }
140
141     }
142
143   } // for
144
145   return ( NULL );
146 }
147
148 unsigned int mmcustom_subcount ( char *parentcatname ) {
149   unsigned int counter = 0;
150
151   int i;
152
153   // search for the cat/parent combination
154   for ( i = 0; i < mmcustom_count; i++ ) {
155
156     if ( mmcustom_complete [ i ].parent_cat &&
157          strcmp ( mmcustom_complete [ i ].parent_cat, parentcatname ) == 0 )
158     {
159       counter++;
160     }
161
162   } // for
163
164   return ( counter );
165 }
166
167 mmcustom_cat_t *mmcustom_register ( char *catname, char *parentcatname ) {
168   mmcustom_complete [ mmcustom_count ].cat = strdup ( catname );
169   if ( parentcatname ) {
170     mmcustom_complete [ mmcustom_count ].parent_cat = strdup ( parentcatname );
171   }
172   mmcustom_count += 1;
173   return ( &(mmcustom_complete [ mmcustom_count - 1 ]) );
174 }
175
176 unsigned int mmcustom_count_subcats ( char *catname ) {
177   int i;
178   unsigned int counter = 0;
179
180   for ( i = 0; i < mmcustom_count; i++ ) {
181
182     if ( mmcustom_complete [ i ].parent_cat && strcasecmp ( mmcustom_complete [ i ].parent_cat, catname ) == 0 ) {
183       counter++;
184     }
185
186   }
187
188   return ( counter );
189 }
190
191 void mmcustom_unregister ( char *catname, char *parentcatname ) {
192   int i;
193   int parent_index = -1;
194
195   if ( parentcatname ) {
196     pnd_log ( pndn_warning, "Goal: Remove subcat %s of %s\n", catname, parentcatname );
197   } else {
198     pnd_log ( pndn_warning, "Goal: Remove parent cat %s and descendants\n", catname );
199   }
200
201   for ( i = 0; i < mmcustom_count; i++ ) {
202
203     // killing a parent cat, or just a subcat?
204     if ( parentcatname ) {
205
206       // killing a subcat, so match cat+subcat to kill
207       if ( mmcustom_complete [ i ].cat && strcmp ( mmcustom_complete [ i ].cat, catname ) == 0 &&
208            mmcustom_complete [ i ].parent_cat && strcasecmp ( mmcustom_complete [ i ].parent_cat, parentcatname ) == 0 )
209       {
210         pnd_log ( pndn_warning, "  Removing subcat: %s of %s\n", catname, parentcatname );
211         free ( mmcustom_complete [ i ].cat );
212         mmcustom_complete [ i ].cat = NULL;
213         break;
214       }
215
216     } else {
217
218       // killing a parent cat, so kill it, and any children of it
219       if ( mmcustom_complete [ i ].parent_cat == NULL &&
220            mmcustom_complete [ i ].cat &&
221            strcmp ( mmcustom_complete [ i ].cat, catname ) == 0 )
222       {
223         // flag the prent for future death (we need its name for now, since the caller is using it)
224         parent_index = i;
225       }
226       else if ( mmcustom_complete [ i ].cat &&
227                 mmcustom_complete [ i ].parent_cat &&
228                 strcmp ( mmcustom_complete [ i ].parent_cat, catname ) == 0 )
229       {
230         // kill children of it
231         pnd_log ( pndn_warning, "  Removing cascading subcat: %s of %s\n", mmcustom_complete [ i ].cat, mmcustom_complete [ i ].parent_cat );
232         free ( mmcustom_complete [ i ].cat );
233         mmcustom_complete [ i ].cat = NULL;
234       }
235
236     }
237
238   } // for
239
240   // kill the actual cat itself
241   if ( parent_index >= 0 ) {
242     pnd_log ( pndn_warning, "  Removing cat: %s\n", catname );
243     free ( mmcustom_complete [ parent_index ].cat );
244     mmcustom_complete [ parent_index ].cat = NULL;
245   }
246
247   return;
248 }