1 /*
2 * Banner routines for the CUPS scheduler.
3 *
4 * Copyright © 2020-2024 by OpenPrinting.
5 * Copyright 2007-2011 by Apple Inc.
6 * Copyright 1997-2006 by Easy Software Products.
7 *
8 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
9 */
10
11 /*
12 * Include necessary headers...
13 */
14
15 #include "cupsd.h"
16 #include <cups/dir.h>
17
18
19 /*
20 * Local functions...
21 */
22
23 static void add_banner(const char *name, const char *filename);
24 static int compare_banners(const cupsd_banner_t *b0,
25 const cupsd_banner_t *b1);
26 static void free_banners(void);
27
28
29 /*
30 * 'cupsdFindBanner()' - Find a named banner.
31 */
32
33 cupsd_banner_t * /* O - Pointer to banner or NULL */
cupsdFindBanner(const char * name)34 cupsdFindBanner(const char *name) /* I - Name of banner */
35 {
36 cupsd_banner_t key; /* Search key */
37
38
39 key.name = (char *)name;
40
41 return ((cupsd_banner_t *)cupsArrayFind(Banners, &key));
42 }
43
44
45 /*
46 * 'cupsdLoadBanners()' - Load all available banner files...
47 */
48
49 void
cupsdLoadBanners(const char * d)50 cupsdLoadBanners(const char *d) /* I - Directory to search */
51 {
52 cups_dir_t *dir; /* Directory pointer */
53 cups_dentry_t *dent; /* Directory entry */
54 char filename[1024], /* Name of banner */
55 *ext; /* Pointer to extension */
56
57
58 /*
59 * Free old banner info...
60 */
61
62 free_banners();
63
64 /*
65 * Try opening the banner directory...
66 */
67
68 if ((dir = cupsDirOpen(d)) == NULL)
69 {
70 cupsdLogMessage(CUPSD_LOG_ERROR, "cupsdLoadBanners: Unable to open banner directory \"%s\": %s",
71 d, strerror(errno));
72 return;
73 }
74
75 /*
76 * Read entries, skipping directories and backup files.
77 */
78
79 Banners = cupsArrayNew((cups_array_func_t)compare_banners, NULL);
80
81 while ((dent = cupsDirRead(dir)) != NULL)
82 {
83 /*
84 * Check the file to make sure it isn't a directory or a backup
85 * file of some sort...
86 */
87
88 snprintf(filename, sizeof(filename), "%s/%s", d, dent->filename);
89
90 if (S_ISDIR(dent->fileinfo.st_mode))
91 continue;
92
93 if (dent->filename[0] == '~' ||
94 dent->filename[strlen(dent->filename) - 1] == '~')
95 continue;
96
97 if ((ext = strrchr(dent->filename, '.')) != NULL)
98 if (!strcmp(ext, ".bck") ||
99 !strcmp(ext, ".bak") ||
100 !strcmp(ext, ".sav"))
101 continue;
102
103 /*
104 * Must be a valid file; add it!
105 */
106
107 add_banner(dent->filename, filename);
108 }
109
110 /*
111 * Close the directory...
112 */
113
114 cupsDirClose(dir);
115 }
116
117
118 /*
119 * 'add_banner()' - Add a banner to the array.
120 */
121
122 static void
add_banner(const char * name,const char * filename)123 add_banner(const char *name, /* I - Name of banner */
124 const char *filename) /* I - Filename for banner */
125 {
126 mime_type_t *filetype; /* Filetype */
127 cupsd_banner_t *temp; /* New banner data */
128
129
130 /*
131 * See what the filetype is...
132 */
133
134 if ((filetype = mimeFileType(MimeDatabase, filename, NULL, NULL)) == NULL)
135 {
136 cupsdLogMessage(CUPSD_LOG_WARN,
137 "add_banner: Banner \"%s\" (\"%s\") is of an unknown file "
138 "type - skipping!", name, filename);
139 return;
140 }
141
142 /*
143 * Allocate memory...
144 */
145
146 if ((temp = calloc(1, sizeof(cupsd_banner_t))) == NULL)
147 {
148 cupsdLogMessage(CUPSD_LOG_WARN,
149 "add_banner: Unable to allocate memory for banner \"%s\" - "
150 "skipping!", name);
151 return;
152 }
153
154 /*
155 * Copy the new banner data over...
156 */
157
158 if ((temp->name = strdup(name)) == NULL)
159 {
160 cupsdLogMessage(CUPSD_LOG_WARN,
161 "add_banner: Unable to allocate memory for banner \"%s\" - "
162 "skipping!", name);
163 free(temp);
164 return;
165 }
166
167 temp->filetype = filetype;
168
169 cupsArrayAdd(Banners, temp);
170 }
171
172
173 /*
174 * 'compare_banners()' - Compare two banners.
175 */
176
177 static int /* O - -1 if name0 < name1, etc. */
compare_banners(const cupsd_banner_t * b0,const cupsd_banner_t * b1)178 compare_banners(
179 const cupsd_banner_t *b0, /* I - First banner */
180 const cupsd_banner_t *b1) /* I - Second banner */
181 {
182 return (_cups_strcasecmp(b0->name, b1->name));
183 }
184
185
186 /*
187 * 'free_banners()' - Free all banners.
188 */
189
190 static void
free_banners(void)191 free_banners(void)
192 {
193 cupsd_banner_t *temp; /* Current banner */
194
195
196 for (temp = (cupsd_banner_t *)cupsArrayFirst(Banners);
197 temp;
198 temp = (cupsd_banner_t *)cupsArrayNext(Banners))
199 {
200 free(temp->name);
201 free(temp);
202 }
203
204 cupsArrayDelete(Banners);
205 Banners = NULL;
206 }
207