| 
									
										
										
										
											2024-03-02 13:15:00 +00:00
										 |  |  | __filename__ = "daemon_get_favicon.py" | 
					
						
							|  |  |  | __author__ = "Bob Mottram" | 
					
						
							|  |  |  | __license__ = "AGPL3+" | 
					
						
							|  |  |  | __version__ = "1.5.0" | 
					
						
							|  |  |  | __maintainer__ = "Bob Mottram" | 
					
						
							|  |  |  | __email__ = "bob@libreserver.org" | 
					
						
							|  |  |  | __status__ = "Production" | 
					
						
							| 
									
										
										
										
											2024-03-23 15:11:05 +00:00
										 |  |  | __module_group__ = "Core GET" | 
					
						
							| 
									
										
										
										
											2024-03-02 13:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import urllib.parse | 
					
						
							|  |  |  | from fitnessFunctions import fitness_performance | 
					
						
							|  |  |  | from httpheaders import set_headers_etag | 
					
						
							|  |  |  | from httpcodes import write2 | 
					
						
							|  |  |  | from httpcodes import http_304 | 
					
						
							|  |  |  | from httpcodes import http_404 | 
					
						
							|  |  |  | from daemon_utils import has_accept | 
					
						
							|  |  |  | from daemon_utils import etag_exists | 
					
						
							|  |  |  | from utils import get_config_param | 
					
						
							|  |  |  | from utils import media_file_mime_type | 
					
						
							|  |  |  | from utils import binary_is_image | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_favicon(self, calling_domain: str, | 
					
						
							|  |  |  |                 base_dir: str, debug: bool, | 
					
						
							| 
									
										
										
										
											2024-04-23 09:23:31 +00:00
										 |  |  |                 fav_filename: str, | 
					
						
							|  |  |  |                 icons_cache: {}, domain_full: str) -> None: | 
					
						
							| 
									
										
										
										
											2024-03-02 13:15:00 +00:00
										 |  |  |     """Return the site favicon or default newswire favicon
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     fav_type = 'image/x-icon' | 
					
						
							|  |  |  |     if has_accept(self, calling_domain): | 
					
						
							|  |  |  |         if 'image/webp' in self.headers['Accept']: | 
					
						
							|  |  |  |             fav_type = 'image/webp' | 
					
						
							|  |  |  |             fav_filename = fav_filename.split('.')[0] + '.webp' | 
					
						
							|  |  |  |         if 'image/avif' in self.headers['Accept']: | 
					
						
							|  |  |  |             fav_type = 'image/avif' | 
					
						
							|  |  |  |             fav_filename = fav_filename.split('.')[0] + '.avif' | 
					
						
							|  |  |  |         if 'image/heic' in self.headers['Accept']: | 
					
						
							|  |  |  |             fav_type = 'image/heic' | 
					
						
							|  |  |  |             fav_filename = fav_filename.split('.')[0] + '.heic' | 
					
						
							|  |  |  |         if 'image/jxl' in self.headers['Accept']: | 
					
						
							|  |  |  |             fav_type = 'image/jxl' | 
					
						
							|  |  |  |             fav_filename = fav_filename.split('.')[0] + '.jxl' | 
					
						
							|  |  |  |     if not self.server.theme_name: | 
					
						
							|  |  |  |         self.theme_name = get_config_param(base_dir, 'theme') | 
					
						
							|  |  |  |     if not self.server.theme_name: | 
					
						
							|  |  |  |         self.server.theme_name = 'default' | 
					
						
							|  |  |  |     # custom favicon | 
					
						
							|  |  |  |     favicon_filename = \ | 
					
						
							|  |  |  |         base_dir + '/theme/' + self.server.theme_name + \ | 
					
						
							|  |  |  |         '/icons/' + fav_filename | 
					
						
							|  |  |  |     if not fav_filename.endswith('.ico'): | 
					
						
							|  |  |  |         if not os.path.isfile(favicon_filename): | 
					
						
							|  |  |  |             if fav_filename.endswith('.webp'): | 
					
						
							|  |  |  |                 fav_filename = fav_filename.replace('.webp', '.ico') | 
					
						
							|  |  |  |             elif fav_filename.endswith('.avif'): | 
					
						
							|  |  |  |                 fav_filename = fav_filename.replace('.avif', '.ico') | 
					
						
							|  |  |  |             elif fav_filename.endswith('.heic'): | 
					
						
							|  |  |  |                 fav_filename = fav_filename.replace('.heic', '.ico') | 
					
						
							|  |  |  |             elif fav_filename.endswith('.jxl'): | 
					
						
							|  |  |  |                 fav_filename = fav_filename.replace('.jxl', '.ico') | 
					
						
							|  |  |  |     if not os.path.isfile(favicon_filename): | 
					
						
							|  |  |  |         # default favicon | 
					
						
							|  |  |  |         favicon_filename = \ | 
					
						
							|  |  |  |             base_dir + '/theme/default/icons/' + fav_filename | 
					
						
							|  |  |  |     if etag_exists(self, favicon_filename): | 
					
						
							|  |  |  |         # The file has not changed | 
					
						
							|  |  |  |         if debug: | 
					
						
							|  |  |  |             print('favicon icon has not changed: ' + calling_domain) | 
					
						
							|  |  |  |         http_304(self) | 
					
						
							|  |  |  |         return | 
					
						
							| 
									
										
										
										
											2024-04-23 09:23:31 +00:00
										 |  |  |     if icons_cache.get(fav_filename): | 
					
						
							|  |  |  |         fav_binary = icons_cache[fav_filename] | 
					
						
							| 
									
										
										
										
											2024-03-02 13:15:00 +00:00
										 |  |  |         set_headers_etag(self, favicon_filename, | 
					
						
							|  |  |  |                          fav_type, | 
					
						
							|  |  |  |                          fav_binary, None, | 
					
						
							| 
									
										
										
										
											2024-04-23 09:23:31 +00:00
										 |  |  |                          domain_full, | 
					
						
							| 
									
										
										
										
											2024-03-02 13:15:00 +00:00
										 |  |  |                          False, None) | 
					
						
							|  |  |  |         write2(self, fav_binary) | 
					
						
							|  |  |  |         if debug: | 
					
						
							|  |  |  |             print('Sent favicon from cache: ' + calling_domain) | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     if os.path.isfile(favicon_filename): | 
					
						
							|  |  |  |         fav_binary = None | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2024-07-14 13:01:46 +00:00
										 |  |  |             with open(favicon_filename, 'rb') as fp_fav: | 
					
						
							|  |  |  |                 fav_binary = fp_fav.read() | 
					
						
							| 
									
										
										
										
											2024-03-02 13:15:00 +00:00
										 |  |  |         except OSError: | 
					
						
							|  |  |  |             print('EX: unable to read favicon ' + favicon_filename) | 
					
						
							|  |  |  |         if fav_binary: | 
					
						
							|  |  |  |             set_headers_etag(self, favicon_filename, | 
					
						
							|  |  |  |                              fav_type, | 
					
						
							|  |  |  |                              fav_binary, None, | 
					
						
							| 
									
										
										
										
											2024-04-23 09:23:31 +00:00
										 |  |  |                              domain_full, | 
					
						
							| 
									
										
										
										
											2024-03-02 13:15:00 +00:00
										 |  |  |                              False, None) | 
					
						
							|  |  |  |             write2(self, fav_binary) | 
					
						
							| 
									
										
										
										
											2024-04-23 09:23:31 +00:00
										 |  |  |             icons_cache[fav_filename] = fav_binary | 
					
						
							| 
									
										
										
										
											2024-04-08 14:00:47 +00:00
										 |  |  |             if debug: | 
					
						
							| 
									
										
										
										
											2024-03-02 13:15:00 +00:00
										 |  |  |                 print('Sent favicon from file: ' + calling_domain) | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |     if debug: | 
					
						
							|  |  |  |         print('favicon not sent: ' + calling_domain) | 
					
						
							|  |  |  |     http_404(self, 17) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def show_cached_favicon(self, referer_domain: str, path: str, | 
					
						
							| 
									
										
										
										
											2024-04-23 09:23:31 +00:00
										 |  |  |                         base_dir: str, getreq_start_time, | 
					
						
							|  |  |  |                         favicons_cache: {}, | 
					
						
							|  |  |  |                         fitness: {}, debug: bool) -> None: | 
					
						
							| 
									
										
										
										
											2024-03-02 13:15:00 +00:00
										 |  |  |     """Shows a favicon image obtained from the cache
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     fav_file = path.replace('/favicons/', '') | 
					
						
							|  |  |  |     fav_filename = base_dir + urllib.parse.unquote_plus(path) | 
					
						
							|  |  |  |     print('showCachedFavicon: ' + fav_filename) | 
					
						
							| 
									
										
										
										
											2024-04-23 09:23:31 +00:00
										 |  |  |     if favicons_cache.get(fav_file): | 
					
						
							|  |  |  |         media_binary = favicons_cache[fav_file] | 
					
						
							| 
									
										
										
										
											2024-03-02 13:15:00 +00:00
										 |  |  |         mime_type = media_file_mime_type(fav_filename) | 
					
						
							|  |  |  |         set_headers_etag(self, fav_filename, | 
					
						
							|  |  |  |                          mime_type, | 
					
						
							|  |  |  |                          media_binary, None, | 
					
						
							|  |  |  |                          referer_domain, | 
					
						
							|  |  |  |                          False, None) | 
					
						
							|  |  |  |         write2(self, media_binary) | 
					
						
							| 
									
										
										
										
											2024-04-23 09:23:31 +00:00
										 |  |  |         fitness_performance(getreq_start_time, fitness, | 
					
						
							|  |  |  |                             '_GET', '_show_cached_favicon2', debug) | 
					
						
							| 
									
										
										
										
											2024-03-02 13:15:00 +00:00
										 |  |  |         return | 
					
						
							|  |  |  |     if not os.path.isfile(fav_filename): | 
					
						
							|  |  |  |         http_404(self, 44) | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     if etag_exists(self, fav_filename): | 
					
						
							|  |  |  |         # The file has not changed | 
					
						
							|  |  |  |         http_304(self) | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     media_binary = None | 
					
						
							|  |  |  |     try: | 
					
						
							| 
									
										
										
										
											2024-07-14 13:01:46 +00:00
										 |  |  |         with open(fav_filename, 'rb') as fp_av: | 
					
						
							|  |  |  |             media_binary = fp_av.read() | 
					
						
							| 
									
										
										
										
											2024-03-02 13:15:00 +00:00
										 |  |  |     except OSError: | 
					
						
							|  |  |  |         print('EX: unable to read cached favicon ' + fav_filename) | 
					
						
							|  |  |  |     if media_binary: | 
					
						
							|  |  |  |         if binary_is_image(fav_filename, media_binary): | 
					
						
							|  |  |  |             mime_type = media_file_mime_type(fav_filename) | 
					
						
							|  |  |  |             set_headers_etag(self, fav_filename, | 
					
						
							|  |  |  |                              mime_type, | 
					
						
							|  |  |  |                              media_binary, None, | 
					
						
							|  |  |  |                              referer_domain, | 
					
						
							|  |  |  |                              False, None) | 
					
						
							|  |  |  |             write2(self, media_binary) | 
					
						
							| 
									
										
										
										
											2024-04-23 09:23:31 +00:00
										 |  |  |             fitness_performance(getreq_start_time, fitness, | 
					
						
							|  |  |  |                                 '_GET', '_show_cached_favicon', debug) | 
					
						
							|  |  |  |             favicons_cache[fav_file] = media_binary | 
					
						
							| 
									
										
										
										
											2024-03-02 13:15:00 +00:00
										 |  |  |             return | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             print('WARN: favicon is not an image ' + fav_filename) | 
					
						
							|  |  |  |     http_404(self, 45) |