';
+ }
+ if($(this).children('content').length>0&&top.feedOpt.getItemSummary) {
+ // prkl mitä paskaa taas javascriptan kans.
+ // tästäkö ne meinaa jotain serverikieltä, hä?
+ // ei saa raw outputtia (innerHTML) XML inputista
+ var itemSummary = $(this).children('content');
+ var div = document.createElement("div");
+ div.appendChild(itemSummary.get(0).childNodes[0].cloneNode(true));
+ itemSummary = div.innerHTML;
+ top.setHtml += '
';
+ }
+ // wrong xml
+ if($(xml).children('rss').length==0&&$(xml).children('feed').length==0) {
+ top.setHtml += top.feedOpt.wrongXmlText;
+ }
+ $(top.selected).append(top.setHtml);
+ if(typeof callbackFunc == 'function'){
+ callbackFunc.call(this, xml);
+ }
+ },
+ // Error Handling
+ error: function (xhr, status, error) {
+ if(xhr.statusText=='timeout') {
+ top.setHtml += top.feedOpt.timeoutText;
+ }
+ if(xhr.statusText=='error') {
+ top.setHtml += top.feedOpt.errorText;
+ }
+ if(xhr.statusText=='notmodified') {
+ top.setHtml += top.feedOpt.notModifiedText;
+ }
+ if(xhr.statusText=='parsererror') {
+ top.setHtml += top.feedOpt.parserErrorText;
+ }
+ $(top.selected).append(top.setHtml);
+ }
+ });
+ }
+
+$(document).ready(function() {
+ // Need to pipe through proxy due XSS not allowed in sites.google.com
+ var url = "http://sites.google.com/a/python.fi/tiedotus/tiedotteet/posts.xml";
+ var url = "/proxy?url=" + encodeURI(url);
+ $('.posts').miniFeed(url, { limit: 10, getFeedTitle : false, getItemDate: false, getItemDescription : true});
+});
\ No newline at end of file
diff --git a/src/media/simplerss.js b/src/media/simplerss.js
new file mode 100644
index 0000000..0bbaeb3
--- /dev/null
+++ b/src/media/simplerss.js
@@ -0,0 +1,93 @@
+/**
+ * Copyright (c) 2010, Till Klampaeckel
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * o Neither the name of the nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category RSS
+ * @package simplerss
+ * @author Till Klampaeckel
+ * @license http://www.opensource.org/licenses/bsd-license.php The New BSD License
+ * @link http://github.com/till/jquery-simplerss
+ */
+(function($){
+ jQuery.fn.extend({
+
+ /**
+ * simplerss
+ *
+ * @param array options To override the defaults.
+ *
+ * @return this
+ */
+ simplerss: function(options) {
+
+ var defaults = {
+ url: '',
+ html: '{title} {text}',
+ wrapper: 'li',
+ dataType: 'xml',
+ display: 2
+ }
+ var options = jQuery.extend(defaults, options);
+
+ return this.each(function() {
+ var o = options;
+ var c = jQuery(this);
+
+ if (o.url == '') {
+ return; // avoid the request
+ }
+
+ jQuery.ajax({
+ url: o.url,
+ type: 'GET',
+ dataType: o.dataType,
+ error: function (xhr, status, e) {
+ console.debug('C: #%s, Error: %s, Feed: %s', $(c).attr('id'), e, o.url);
+ },
+ success: function(feed){
+
+ jQuery(feed).find('item').each(function(i){
+
+ var itemHtml = o.html.replace(/{title}/, jQuery(this).find('title').text());
+ itemHtml = itemHtml.replace(/{text}/, jQuery(this).find('description').text());
+ itemHtml = itemHtml.replace(/{link}/, jQuery(this).find('guid').text());
+
+ jQuery(c).append(jQuery('<' + o.wrapper + '>').append(itemHtml));
+
+ if (i == o.display) {
+ return false;
+ }
+
+ });
+ }
+ });
+ });
+ return this;
+ }
+ });
+})(jQuery);
+
+
diff --git a/src/proxy.py b/src/proxy.py
new file mode 100644
index 0000000..9869847
--- /dev/null
+++ b/src/proxy.py
@@ -0,0 +1,71 @@
+# http://gregdoesit.com/2010/12/using-google-app-engine-as-proxy-for-cross-domain-requests/
+
+import logging
+import pickle
+import urllib
+import re
+import time
+import urllib
+import wsgiref.handlers
+import hashlib
+
+from google.appengine.api import memcache
+from google.appengine.api import urlfetch
+from google.appengine.ext import db
+from google.appengine.ext import webapp
+from google.appengine.ext.webapp import template
+from google.appengine.runtime import apiproxy_errors
+
+CACHE_TIME = 1 # number of minutes to cache content for
+
+URL_PREFIXES = ["http://sites.google.com/a/python.fi"] # only allow URLs to be queried from certain domain(s)
+
+def getMemcacheKey(url):
+ url_hash = hashlib.sha256()
+ url_hash.update(url)
+ return "hash_" + url_hash.hexdigest()
+
+class ProxyHandler(webapp.RequestHandler):
+
+ def get(self):
+ url = self.request.get('url')
+ url = urllib.unquote(url)
+ # only allow urls that start with prefixes defined in URL_PREFIXES to be used
+ if not self.isUrlAllowed(url):
+ self.response.out.write("The URL passed can not be proxied due to security reasons.")
+ return
+ memcacheKey = getMemcacheKey(url)
+
+ # Use memcache to store the request for CACHE_TIME
+ proxiedContent = memcache.get(memcacheKey)
+ proxiedContentInMemcache = True
+ if proxiedContent is None:
+ proxiedContentInMemcache = False
+ try:
+ response = urlfetch.fetch(url)
+ except (urlfetch.Error, apiproxy_errors.Error):
+ return self.error(404)
+ proxiedContent = response.content
+ if proxiedContent is None:
+ return self.error(404)
+
+ # Add the fetched content to memcache
+ if (not proxiedContentInMemcache):
+ memcache.add(memcacheKey,proxiedContent,CACHE_TIME)
+ self.response.out.write(proxiedContent)
+
+ def isUrlAllowed(self, url):
+ for urlPrefix in URL_PREFIXES:
+ if url.startswith(urlPrefix):
+ return True
+ return False
+
+app = webapp.WSGIApplication([
+ ("/proxy", ProxyHandler),
+], debug=True)
+
+def main():
+ wsgiref.handlers.CGIHandler().run(app)
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
diff --git a/src/templates/main.html b/src/templates/main.html
index 214dce3..0f5dac1 100644
--- a/src/templates/main.html
+++ b/src/templates/main.html
@@ -26,40 +26,8 @@
Yhdistys perustettu
-
-
Yhdistyksen perustamiskokous
-
- Python Interest Group Finland ry:n perustamiskokous
- järjestetään lauantaina 7.5.2011 klo
- 10:00 DjangoCon Finlandin
- yhteydessä Aalto Venture Garagen tiloissa, Betonimiehenkuja 3,
- Espoo. Perustamiskokouksessa mm. hiotaan kuntoon yhdistyksen
- säännöt
- (työversio
- Google Docsissa) sekä valitaan yhdistyksen ensimmäinen
- hallitus. Kaikki ovat tervetulleita!
-
-
- Virallinen kokouskutsu yhdistyksen perustamiskokoukseen
- löytyy täältä.
-
-
-
-
-
Kehittäjä hakusessa
-
- Mikäli olet aloitteleva Python-kehittäjä ja haluat osallistua vapaaehtoistyöhön, meillä
- olisi juuri oikea erikoistehtävä sinulle.
-
-
-
- Pääset kehittämään python.fi-sivustoa Suomen kovimpien web-ammattilaisten ohjaamana.
-
-
-
- Työ on palkatonta, mutta voimme järjestää tämän oppilaitoksen yms. harjoitustyön tai
- työharjoittelun puitteissa.
-