Changeset 3093 for trunk


Ignore:
Timestamp:
11/05/10 11:04:05 (9 years ago)
Author:
jukka
Message:

Modified embedded blocks to use safer oEmbed-format.

Location:
trunk
Files:
1 deleted
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/FieldsWidgets.py

    r3090 r3093  
    3636from copy import copy 
    3737from xml.dom.minidom import parseString as parse_xml 
     38from urlparse import urlparse 
    3839from xml.sax.saxutils import unescape 
    3940import re, os, shutil 
     
    304305        elif chapter_type=='embed_block': 
    305306            changes['text']='' 
    306             changes['embed']=form.get('embed_textarea') 
     307            changes['embed']=form.get('embed_field','') 
     308            changes['embed_old']=form.get('embed_field_old', '') 
    307309        # Save & edit buttons 
    308310        if form.get('saveChapter', None): 
     
    10151017                elif ctype == 'embed_block': 
    10161018                    new_chapter['text']='' 
    1017                     new_chapter['embed']=value['embed'] 
     1019                    if 'embed_old' in value and value['embed_old'] and not value['embed']: 
     1020                        new_chapter['embed']=value['embed_old'] 
     1021                    else: 
     1022                        new_chapter['embed']=value['embed'] 
    10181023                else:             
    10191024                    new_chapter['text']=value['text'] 
     
    10891094            return None 
    10901095 
     1096 
     1097    def isOEmbedChapter(self, chapter): 
     1098        """ Check if this chapter should use oembed query or just paste embed code """ 
     1099        if not ('type' in chapter and chapter['type']=='embed_block'): 
     1100            return False 
     1101        code=chapter['embed'] 
     1102        try: 
     1103            parsetuple=urlparse(code) 
     1104            return parsetuple[0]=='http' 
     1105        except TypeError: 
     1106            return False 
     1107        return False 
     1108 
    10911109    def getLength(self, piece): 
    10921110        as_time=piece.getLength() 
  • trunk/LeMillCatalogTool.py

    r3087 r3093  
    99 
    1010from Products.ZCatalog.ZCatalog import ZCatalog 
     11from Products.ZCTextIndex.ParseTree import ParseError 
    1112from Products.CMFPlone.CatalogTool import CatalogTool as PloneCatalogTool 
    1213from Products.CMFPlone.PloneBatch import Batch 
     
    439440    def browsingSearch(self, REQUEST=None, **kw):         
    440441        """ This is a general purpose catalog search that can convert readable keywords from request into actual search terms. 
    441         recognized keywords: language, subject_area, target_group, type, tags, state, author, created, edited                  
     442        recognized keywords: language, subject_area, target_group, type, tags, state, author, created, edited, group, country. 
     443         
     444        These same keywords are used all over in interface to build selection boxes, select page headers etc.  
     445        The actual search indexes like 'getTags' etc. are used only here and should not be used elsewhere.                 
    442446        """ 
    443447        src=REQUEST.form 
     
    475479            del keywords['group'] 
    476480        if 'state' in keywords: 
    477             keywords['getState']=keywords['state'] 
     481            if keywords['state']=='draft': 
     482                lutool=getToolByName(self,'lemill_usertool')                 
     483                if 'listCreators' in keywords and keywords['listCreators'] == lutool.getAuthenticatedId(): # only allow authenticated author to view privates 
     484                    keywords['getState']=('draft', 'private') 
     485                else: 
     486                    keywords['getState']='draft'  
     487            elif keywords['state']=='private': # don't allow manually mungling browse terms 
     488                return [] 
     489            else: 
     490                keywords['getState']=keywords['state']             
    478491            del keywords['state'] 
    479492        if 'country' in keywords: 
     
    580593        else: 
    581594            return self.author_cache[user] 
    582         return None         
     595        return (user,'')         
    583596 
    584597    def getEntry(self, index, key, empty=[]): 
  • trunk/skins/lemill/lemill_grid.css

    r3079 r3093  
    106106.right { 
    107107    float: right; 
     108} 
     109 
     110input[readonly], textarea[readonly] { 
     111    background-color: #dddddd; 
    108112} 
    109113 
     
    254258    height:60px; 
    255259    text-align:center; 
    256     padding-top:20px; 
     260    padding-top:30px; 
    257261    padding-bottom:20px; 
    258262    background-color: #dddddd; 
     
    672676    background:#eeeeff; 
    673677} 
     678 
     679div.editorPaddings { 
     680    padding: 1em; 
     681} 
     682 
    674683img.handle { 
    675684    cursor: move; 
  • trunk/skins/lemill/main_template.pt

    r3052 r3093  
    6767<div class="clear" height="24px"></div>  
    6868<div class="footer grid"> 
    69     <metal:footer define-slot="footerslot"><metal:block use-macro="here/footer/macros/portal_footer" /></metal:footer> 
     69    <metal:footer define-slot="footerslot"> 
     70        <p> 
     71            <a i18n:translate="label_about_lemill" href="#" tal:attributes="href string:${portal_url}/content/webpages/about-lemill">About</a> | 
     72            <a i18n:translate="label_blog_lemill" href="http://blog.lemill.net">Blog</a> | 
     73            <a i18n:translate="label_faq" href="#" tal:attributes="href string:${portal_url}/content/webpages/lemill-faq">FAQ</a> | 
     74            <a i18n:translate="label_lemill_development_site" href="http://lemill.org/trac/">LeMill development site</a> | 
     75            <a i18n:translate="label_feedback_report_a_problem" href="http://lemill.org/trac/wiki/support">Feedback / Report a problem</a>  
     76        </p> 
     77    </metal:footer> 
    7078</div> 
    7179<metal:extra define-slot="extraslot"></metal:extra> 
  • trunk/skins/lemill/master.js

    r3075 r3093  
    6666        } 
    6767    } 
     68 
     69/* 5. Embed divs are filled with actual embed code  */ 
     70    $(document).ready(function() { 
     71        $(".oembed").oembed(); 
     72    }); 
     73 
     74 
    6875}); 
    69  
    7076/* *** END INITIALIZATIONS *** */ 
    7177 
     
    11381144}); 
    11391145 
     1146(function(d){d.fn.oembed=function(g,f,h){f=d.extend(true,d.fn.oembed.defaults,f);return this.each(function(){var i=d(this),j=(g!=null)?g:i.attr("href"),k;if(!h){h=function(m,l){d.fn.oembed.insertCode(m,f.embedMethod,l)}}if(j!=null){k=e(j);if(k!=null){k.params=c(f[k.name])||{};k.maxWidth=f.maxWidth;k.maxHeight=f.maxHeight;k.embedCode(i,j,h);return}}h(i,null)})};d.fn.oembed.defaults={maxWidth:null,maxHeight:null,embedMethod:"fill"};d.fn.oembed.insertCode=function(g,h,f){if(f==null){return}switch(h){case"auto":if(g.attr("href")!=null){d.fn.oembed.insertCode(g,"append",f)}else{d.fn.oembed.insertCode(g,"replace",f)}break;case"replace":g.replaceWith(f.code);break;case"fill":g.html(f.code);break;case"append":var i=g.next();if(i==null||!i.hasClass("oembed-container")){i=g.after('<div class="oembed-container"></div>').next(".oembed-container");if(f!=null&&f.provider_name!=null){i.toggleClass("oembed-container-"+f.provider_name)}}i.html(f.code);break}};d.fn.oembed.getPhotoCode=function(f,h){var i=h.title?h.title:"";i+=h.author_name?" - "+h.author_name:"";i+=h.provider_name?" - "+h.provider_name:"";var g='<div><a href="'+f+'" target="_blank"><img src="'+h.url+'" alt="'+i+'"/></a></div>';if(h.html){g+="<div>"+h.html+"</div>"}return g};d.fn.oembed.getVideoCode=function(f,h){var g=h.html;return g};d.fn.oembed.getRichCode=function(f,h){var g=h.html;return g};d.fn.oembed.getGenericCode=function(f,h){var i=(h.title!=null)?h.title:f,g='<a href="'+f+'">'+i+"</a>";if(h.html){g+="<div>"+h.html+"</div>"}return g};d.fn.oembed.isAvailable=function(f){var g=e(f);return(g!=null)};function e(f){for(var g=0;g<b.length;g++){if(b[g].matches(f)){return b[g]}}return null}function c(h){if(h==null){return null}var g={};for(var f in h){if(f!=null){g[f.toLowerCase()]=h[f]}}return g}var b=[new a("fivemin","5min.com"),new a("amazon","amazon.com"),new a("flickr","flickr","http://flickr.com/services/oembed","jsoncallback"),new a("googlevideo","video.google."),new a("hulu","hulu.com"),new a("imdb","imdb.com"),new a("metacafe","metacafe.com"),new a("qik","qik.com"),new a("revision3","revision3.com"),new a("slideshare","slideshare.net"),new a("twitpic","twitpic.com"),new a("viddler","viddler.com"),new a("vimeo","vimeo.com","http://vimeo.com/api/oembed.json"),new a("wikipedia","wikipedia.org"),new a("wordpress","wordpress.com"),new a("youtube","youtube.com"),new a("vids.myspace.com","vids.myspace.com","http://vids.myspace.com/index.cfm?fuseaction=oembed"),new a("screenr","screenr.com","http://screenr.com/api/oembed.json")];function a(f,g,i,h){this.name=f;this.urlPattern=g;this.oEmbedUrl=(i!=null)?i:"http://oohembed.com/oohembed/";this.callbackparameter=(h!=null)?h:"callback";this.maxWidth=500;this.maxHeight=400;this.matches=function(j){return j.indexOf(this.urlPattern)>=0};this.getRequestUrl=function(m){var k=this.oEmbedUrl;if(k.indexOf("?")<=0){k=k+"?"}else{k=k+"&"}var j="";if(this.maxWidth!=null&&this.params.maxwidth==null){this.params.maxwidth=this.maxWidth}if(this.maxHeight!=null&&this.params.maxheight==null){this.params.maxheight=this.maxHeight}for(var l in this.params){if(l==this.callbackparameter){continue}if(this.params[l]!=null){j+="&"+escape(l)+"="+this.params[l]}}k+="format=json&url="+escape(m)+j+"&"+this.callbackparameter+"=?";return k};this.embedCode=function(j,l,m){var k=this.getRequestUrl(l);d.getJSON(k,function(q){var n=d.extend(q);var p,o=q.type;switch(o){case"photo":n.code=d.fn.oembed.getPhotoCode(l,q);break;case"video":n.code=d.fn.oembed.getVideoCode(l,q);break;case"rich":n.code=d.fn.oembed.getRichCode(l,q);break;default:n.code=d.fn.oembed.getGenericCode(l,q);break}m(j,n)})}}})(jQuery); 
  • trunk/skins/lemill/piece_view.pt

    r3045 r3093  
    1313    piece_url here_url; 
    1414    macro_mapping python:{'image':'here/piece_macros/macros/image_with_download', 
    15     'audio':'here/piece_macros/audioplayer_with_download', 
     15    'audio':'here/piece_macros/macros/audioplayer_with_download', 
    1616    'flash':'here/piece_macros/macros/swf_macro', 
    1717    'flv-video':'here/macros_flowplayer/macros/flowplayer_piece', 
    1818    'kml':'here/piece_macros/macros/kml_macro_with_download', 
    19     'unknown':'here/piece_macros/macros/download_only'}"> 
     19    'unknown':'here/piece_macros/macros/download_only'}; 
     20    piece_type test(piece_type in macro_mapping, piece_type, 'unknown');"> 
    2021    <metal:view_macro use-macro="python:path(macro_mapping[piece_type])" /> 
    2122 
  • trunk/skins/lemill/resource_list_macro.pt

    r3067 r3093  
    1313            <p><b><a href="" tal:attributes="href item/url" tal:content="item/title" >Title</a></b><br/> 
    1414            <tal:block i18n:translate="" content="item/readable_type">Resource type</tal:block><tal:block condition="python:'created' in item" tal:define="timedif item/timedif | nothing" >, <tal:tr i18n:translate="label_created">created</tal:tr> <metal:use_nicetimes use-macro="here/macros_timedifference/macros/days_ago" /></tal:block><tal:block condition="python:'edited' in item" tal:define="timedif item/timedif | nothing" >, <tal:tr i18n:translate="label_created">edited</tal:tr> <metal:use_nicetimes use-macro="here/macros_timedifference/macros/days_ago" /></tal:block><br/> 
    15             <tal:block condition="python:item['authors'] and len(item['authors'])>1"><tal:tr i18n:translate="label_authors">Authors</tal:tr>: <tal:block tal:repeat="author item/authors"><a href="" tal:attributes="href python:author[1]" tal:content="python:author[0]">name</a><tal:block condition="not:repeat/author/end">, </tal:block></tal:block><br/></tal:block><tal:block condition="python:item['authors'] and len(item['authors'])==1"><tal:tr i18n:translate="label_author">Author</tal:tr>: <a href="" tal:attributes="href python:item['authors'][0][1]" tal:content="python:item['authors'][0][0]">name</a><br/></tal:block> 
     15            <tal:block condition="python:item['authors'] and len(item['authors'])>1"><tal:tr i18n:translate="label_authors">Authors</tal:tr>: <tal:block tal:repeat="author item/authors"><a href="" tal:condition="author" tal:attributes="href python:author[1]" tal:content="python:author[0]">name</a><tal:block condition="not:repeat/author/end">, </tal:block></tal:block><br/></tal:block><tal:block condition="python:item['authors'] and len(item['authors'])==1"><tal:tr i18n:translate="label_author">Author</tal:tr>: <a href="" tal:attributes="href python:item['authors'][0][1]" tal:content="python:item['authors'][0][0]">name</a><br/></tal:block> 
    1616            <tal:block condition="item/country"><tal:tr i18n:translate="label_location">Location</tal:tr>: <a href="" tal:content="item/country" tal:attributes="href item/country_link">Country</a><br/></tal:block> 
    1717            <tal:block condition="item/tags"><tal:tr i18n:translate="label_tags">Tags</tal:tr>: <tal:block tal:repeat="tag item/tags"><a href="" tal:attributes="href python:tag[1]" tal:content="python:tag[0]">tag</a><tal:block condition="not:repeat/tag/end">, </tal:block></tal:block><br/></tal:block> 
  • trunk/skins/lemill/script_changeCoverImage.cpy

    r3070 r3093  
    1212from Products.CMFCore.utils import getToolByName 
    1313from Products.LeMill import i18nme as gettext 
     14 
    1415file = REQUEST.get('file_file', None) 
    1516uid = REQUEST.get('piece_uid', None) 
     
    3536        # Only .jpg, .png and .gif images are allowed. 
    3637        if file.headers['Content-Type'] not in ['image/jpeg', 'image/pjpeg', 'image/gif', 'image/png', 'image/x-png']: 
    37             lt.addPortalMessage(_(u"Only .jpg, .png and .gif images are allowed.")) 
     38            lt.addPortalMessage(gettext("Only .jpg, .png and .gif images are allowed.")) 
    3839            return state 
    3940    except AttributeError: 
  • trunk/skins/lemill/widget_chapter.pt

    r3086 r3093  
    4242 
    4343<metal:view_embed_block define-macro="view_embed_block"> 
    44 <div class="embed_content" tal:content="structure chapter/embed | python:''" ></div> 
     44<div class="embed_content" tal:define="oembed python:field.isOEmbedChapter(chapter)"> 
     45<tal:oembed condition="oembed"> 
     46<a href="" tal:attributes="href chapter/embed" class="oembed" content="chapter/embed">Embedded content</a> 
     47</tal:oembed> 
     48<tal:old_embed condition="not:oembed" replace="structure chapter/embed | python:''" /></div> 
    4549</metal:view_embed_block> 
    4650 
     
    198202 
    199203<metal:edit_view_embed_block define-macro="edit_view_embed_block"> 
    200 <div tal:replace="structure cleaned_chapter/embed | python:''" /> 
     204<div class="embed_content" tal:define="oembed python:field.isOEmbedChapter(chapter)"> 
     205<tal:oembed condition="oembed"> 
     206<a href="" tal:attributes="href chapter/embed" class="oembed" content="chapter/embed">Embedded content</a> 
     207</tal:oembed> 
     208<tal:old_embed condition="not:oembed" replace="structure chapter/embed | python:''" /></div> 
    201209</metal:edit_view_embed_block> 
    202210 
     
    222230</tal:edit_text_block> 
    223231 
    224 <tal:edit_embed_block metal:define-macro="edit_embed_block">     
    225 <div class="formHelp" i18n:translate="embed_block_helptext">Paste embed code here.</div>       
    226 <textarea rows="3" style="width:95%" id="embed_textarea" name="embed_textarea" tal:content="chapter/embed | python:''"></textarea>     
     232<tal:edit_embed_block metal:define-macro="edit_embed_block"> 
     233<div class="editorPaddings" tal:define="oembed python:field.isOEmbedChapter(chapter) or not chapter['embed']">   
     234<div class="formHelp" i18n:translate="embed_field_help">Enter address for embedded content here. (for example http://www.youtube.com/watch?v=... )</div>       
     235<p> 
     236<input type="text" style="width:60%" id="embed_field" name="embed_field" tal:attributes="value python:test(oembed, chapter['embed'], '')" /> 
     237<input type="button" value="Test embedding" i18n:attributes="value python:Test embedding" onclick="$('#embed_test').oembed($('#embed_field').val());$('#old_embed').html('');" /></p> 
     238<div id="embed_test"> 
     239<a href="" tal:attributes="href chapter/embed" class="oembed" tal:condition="oembed" tal:content="chapter/embed">Embedded content</a></div>     
     240<tal:old_embed condition="not:oembed"> 
     241<div id="old_embed" tal:content="structure chapter/embed" /> 
     242<br/> 
     243<div class="formHelp" i18n:translate="embed_field_old_value_help">For safety reason we don't allow direct embed codes anymore. The embed code for this resource was:</div>       
     244 
     245<textarea readonly="1" rows="6" style="width:95%" id="embed_field_old" name="embed_field_old" tal:content="chapter/embed | python:''"></textarea>     
     246<div class="formHelp" i18n:translate="embed_field_old_value_help_2">If you want to update this embedded content, please use the webpage address (not the embed code) of the resource.</div> 
     247</tal:old_embed></div> 
    227248</tal:edit_embed_block> 
    228249 
Note: See TracChangeset for help on using the changeset viewer.