#!/usr/bin/python2 # -*- coding: UTF-8 -*- import compressout import os import time import cgitb cgitb.enable() import sitemapdata def lastmod_changefreq(filename, mod_compressout): changefreq = [ ('hourly', 21600), # 6 hours ('daily', 259200), # 3 days ('weekly', 1209600), # 2 weeks ('monthly', 5184000), # 60 days ('yearly', -1) # Stop ] last_modifed = os.stat(filename).st_mtime mod_compressout.write_b(' <lastmod>{}</lastmod>\n'.format( time.strftime('%Y-%m-%d', time.gmtime(last_modifed)) )) # Use highest frequency that is at most 2/T # T is the time between the previous change and the next change. # As the next change has not yet occurred, assume that # now = previous + T/2, ie. right in the middle. time_delta = time.time() - last_modifed changefreq_kw = None for keyword, limit in changefreq: if limit/2.0 > time_delta: break changefreq_kw = keyword if limit < 0: break mod_compressout.write_b( ' <changefreq>{}</changefreq>\n'.format(keyword) ) def pretty(text): text = text.replace('\n', ' ') while 2*' ' in text: text = text.replace(2*' ', 1*' ') text = text.replace('&', '&') text = text.replace('<', '<') text = text.replace('>', '>') return text.strip() def XML(): compressout.write_h('Content-Type: application/xml; charset=UTF-8\n\n') compressout.write_b('<?xml version="1.0" encoding="UTF-8"?>\n') compressout.write_b( '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"\n' ) compressout.write_b( 'xmlns:i="http://www.google.com/schemas/sitemap-image/1.1"\n' ) compressout.write_b( 'xmlns:v="http://www.google.com/schemas/sitemap-video/1.1"\n' ) compressout.write_b('>\n\n') # Flatten subsitemaps for url in sitemapdata.sitemap: if 'subsitemap' in url: sitemapdata.sitemap.extend(url['subsitemap']) del url['subsitemap'] for url in sitemapdata.sitemap: compressout.write_b('<url>\n') compressout.write_b(' <loc>{}</loc>\n'.format( sitemapdata.site + url['URL'] )) if 'priority' in url: compressout.write_b(' <priority>{}</priority>\n'.format( url['priority'] )) if 'file' in url: lastmod_changefreq(url['file'], compressout) if 'images' in url: for image in url['images']: compressout.write_b(' <i:image>\n') compressout.write_b( ' <i:loc>{}</i:loc>\n'.format( sitemapdata.imgsite + image['URL'] ) ) if 'description' in image: compressout.write_b( ' <i:caption>{}</i:caption>\n'.format( pretty(image['description']) ) ) # Image license. if 'license' in image: license = image['license'] else: license = sitemapdata.imglicense if license is not None: compressout.write_b( ' <i:license>{}</i:license>\n'.format( license ) ) compressout.write_b(' </i:image>\n') if 'videos' in url: for video in url['videos']: compressout.write_b(' <v:video>\n') compressout.write_b( ' <v:title>{}</v:title>\n'.format( video['title'] ) ) if 'content' in video: compressout.write_b( ' <v:content_loc>{}</v:content_loc>\n'.format( video['content'] ) ) if 'player' in video: compressout.write_b( ' <v:player_loc>{}</v:player_loc>\n'.format( video['player'] ) ) compressout.write_b( ' <v:description>{}</v:description>\n'.format( video['description'] ) ) compressout.write_b( ' <v:thumbnail_loc>{}</v:thumbnail_loc>\n'.format( video['thumbnail'] ) ) compressout.write_b(' </v:video>\n') compressout.write_b('</url>\n') compressout.write_b('\n</urlset>\n') def HTML(): if 'application/xhtml+xml' in os.getenv('HTTP_ACCEPT', ''): content_type = 'application/xhtml+xml' else: content_type = 'text/html' compressout.write_h('Content-Type: {}; charset=UTF-8\n\n'.format( content_type )) compressout.write_b('''<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <link rel="stylesheet" href="https://oskog97.com/style.css" type="text/css"/> <link rel="icon" type="image/png" href="/favicon.png"/> <!-- End html5nc macro. --> ''') compressout.write_b(''' <title>Sitemap</title> <meta name="robots" content="noindex, follow"/> </head> <body> <!-- BEGIN autogenerated navigation --> <nav><div id="navigation"><div id="nav_inner"> <p><a href="#content" class="textonly">Skip navigation</a></p> <p class="row"> <span class="textonly" translate="no">[</span><a class="head" href="/">Home</a><span class="textonly" translate="no">]</span> >> <span class="textonly" translate="no">[</span><a class="sub" href="/projects/anonymine/">Anonymine</a><span class="textonly" translate="no">]</span> <span class="textonly" translate="no">[</span><a class="sub" href="/projects/light-sensor/">Analog light sensor</a><span class="textonly" translate="no">]</span> <span class="textonly" translate="no">[</span><a class="sub" href="/projects/PLLM-M702A/">Reverse-engineered schematics for PLLM-M702A</a><span class="textonly" translate="no">]</span> <span class="textonly" translate="no">[</span><a class="sub" href="/small-scripts/">Small scripts</a><span class="textonly" translate="no">]</span> <span class="textonly" translate="no">[</span><a class="sub" href="/thinkpad/">-> My IBM thinkpad</a><span class="textonly" translate="no">]</span> </p> <p class="row"> <span class="textonly" translate="no">]</span><span class="sub active">Sitemap</span><span class="textonly" translate="no">[</span> </p> <hr class="textonly"/> </div></div></nav> <!-- END autogenerated navigation --> <main><div id="content"> <h1 id="title">Sitemap</h1> ''') def write_sitemap(sitemap): compressout.write_b('<ul>\n') for url in sitemap: compressout.write_b('<li><a href="{}">{}</a>'.format( url['URL'].replace('&', '&').replace('"', '"'), pretty(url['description']) )) if 'subsitemap' in url: write_sitemap(url['subsitemap']) compressout.write_b('</li>\n') compressout.write_b('</ul>\n') write_sitemap(sitemapdata.sitemap) compressout.write_b(''' <h2>Other sitemaps</h2> <ul> ''') for URL, name in sitemapdata.html_sitemaps: compressout.write_b('<li><a href="{}">{}</a></li>\n'.format( URL.replace('&', '&').replace('"', '"'), pretty(name) )) compressout.write_b(''' </ul> </div></main> <!-- INCLUDED FOOTER --> <footer><div id="footer"> <hr class="textonly"/> <p> Copyright © Oskar Skog<br/> Website content released under the <a href="https://creativecommons.org/licenses/by/4.0/" rel="license noopener" target="_blank">Creative Commons Attribution (CC-BY 4.0)</a> license and my software usually under the <span class="a"><a target="_blank" rel="noopener" href="https://opensource.org/licenses/BSD-2-Clause">FreeBSD license (2-clause)</a>.</span> <br/> Images may be from other sites, I should have cited useful sources somewhere on the page. <span class="notprint">Contact me if I haven't.</span> </p> <p id="contact" class="notprint"> You can contact me at: <a href="mailto:oskar@oskog97.com" rel="noopener" target="_blank">oskar@oskog97.com</a> <span class="a">(<a href="/pgp-pub/oskar.asc" >PGP public key</a>)</span> </p> <p> <a class="notprint" href="https://oskog97.com/read/?path=/style.css"> CSS Stylesheet </a> <a href="https://validator.w3.org/check/referrer" rel="nofollow noopener" target="_blank" class="notprint"><span class="img">Valid HTML5</span ></a><br/> </p> </div></footer> <!-- END OF INCLUDED FOOTER --> </body> </html> ''') def main(): os.chdir(sitemapdata.basedir) compressout.init() compressout.write_h('X-Robots-Tag: noindex, follow\n') query_string = os.getenv('QUERY_STRING') if query_string == 'xml': XML() else: HTML() compressout.done() if __name__ == '__main__': main()