From 3ce7dc87991d9fa404430665b7c663b9dd34c78e Mon Sep 17 00:00:00 2001 From: Michael Moen Date: Mon, 12 Sep 2005 01:09:33 +0000 Subject: [PATCH] Initial revision --- trunk/README_FCKeditor | 42 +++++ trunk/app/controllers/fckeditor_controller.rb | 152 ++++++++++++++++ trunk/app/helpers/fckeditor_helper.rb | 39 ++++ trunk/app/views/fckeditor/connector.rhtml | 2 + trunk/app/views/fckeditor/create_folder.rxml | 7 + .../views/fckeditor/files_and_folders.rxml | 18 ++ trunk/app/views/fckeditor/index.rhtml | 41 +++++ trunk/app/views/fckeditor/upload_file.rhtml | 2 + trunk/config/environment.rb.fck_settings | 34 ++++ trunk/public/UserFiles/File/.keep | 0 trunk/public/UserFiles/Flash/.keep | 0 trunk/public/UserFiles/Image/.keep | 0 trunk/public/UserFiles/Media/.keep | 0 .../public/fckeditor/fckeditor.js.patched.js | 171 ++++++++++++++++++ trunk/public/javascripts/fckconfig_custom.js | 6 + .../functional/fckeditor_controller_test.rb | 18 ++ 16 files changed, 532 insertions(+) create mode 100644 trunk/README_FCKeditor create mode 100644 trunk/app/controllers/fckeditor_controller.rb create mode 100644 trunk/app/helpers/fckeditor_helper.rb create mode 100644 trunk/app/views/fckeditor/connector.rhtml create mode 100644 trunk/app/views/fckeditor/create_folder.rxml create mode 100644 trunk/app/views/fckeditor/files_and_folders.rxml create mode 100644 trunk/app/views/fckeditor/index.rhtml create mode 100644 trunk/app/views/fckeditor/upload_file.rhtml create mode 100644 trunk/config/environment.rb.fck_settings create mode 100644 trunk/public/UserFiles/File/.keep create mode 100644 trunk/public/UserFiles/Flash/.keep create mode 100644 trunk/public/UserFiles/Image/.keep create mode 100644 trunk/public/UserFiles/Media/.keep create mode 100644 trunk/public/fckeditor/fckeditor.js.patched.js create mode 100644 trunk/public/javascripts/fckconfig_custom.js create mode 100644 trunk/test/functional/fckeditor_controller_test.rb diff --git a/trunk/README_FCKeditor b/trunk/README_FCKeditor new file mode 100644 index 0000000..b1eab76 --- /dev/null +++ b/trunk/README_FCKeditor @@ -0,0 +1,42 @@ +README for FCKeditor on Rails + +To install: + install FCKeditor into your app under public/fckeditor + + extract fckeditor_on_rails into your app + + add the environment settings found in + config/environment.rb.fck_settings + to config/environment.rb + + if you want to use a different base dir than /fckeditor/ + you will need to use the included patched fckeditor.js + + copy the fckeditor() helper into app/helpers/application_helper.rb + or add helper :fckeditor into the controller(s) you want access from + + startup the server and go to /fckeditor where you will find a test page + this page has been configured to display nothing if in any + environment other than development + +Useage: + In the simplest case useage would be + <%= fckeditor(:object, :param, {:width => '600px', :height => '500px'}) -%> + + See index.rhtml for other options + +TODO: + - Learn Ruby and fix the code up + - Add command support for the mcpuk file browser + (http://mcpuk.net/) + - Figure out how to make this a gem + - Fix bugs as reported + - Better docs + +Contact: + Michael Moen + mi-rails@underpantsgnome.com + +History: + 2005-09-11 (0.01) - Initial + diff --git a/trunk/app/controllers/fckeditor_controller.rb b/trunk/app/controllers/fckeditor_controller.rb new file mode 100644 index 0000000..bd5b67c --- /dev/null +++ b/trunk/app/controllers/fckeditor_controller.rb @@ -0,0 +1,152 @@ +class FckeditorController < ApplicationController + # this may not be very Rubyesque, it's my first run at Ruby code + # I'm sure it will get better over time + # feel free to point out better ways to do thigs in Ruby + # if you can do it without being abusive ;) + + def index + if RAILS_ENV != 'development' + render(:nothing => true) + end + end + + # figure out who needs to handle this request + def connector + if params[:Command] == 'GetFoldersAndFiles' || params[:Command] == 'GetFolders' + get_folders_and_files(params) + elsif params[:Command] == 'CreateFolder' + create_folder(params) + elsif params[:Command] == 'FileUpload' + upload_file(params) + end + end + + # generate a directory listing + def get_folders_and_files(params) + params = appendParams(params) + @files = Array.new + @dirs = Array.new + d = Dir.new(params[:dir]) + f_count = 0 + d_count = 0 + + d.each { |x| + # skip . and .. I'm sure there's a better way to handle this + if x != '.' && x != '..' + # actual file system path + full_path = "#{params[:dir]}/#{x}"; + + # found a directory add it to the list + if File.directory?(full_path) + @dirs[d_count] = x + d_count = d_count.next + #if we only want directories, skip the files + elsif params[:Command] == 'GetFoldersAndFiles' && File.file?(full_path) + size = File.size(full_path) + + if size != 0 && size < 1024 + size = 1 + else + size = File.size(full_path) / 1024 + end + + @files[f_count] = { :name => x, :size => size }; + f_count = f_count.next + end + end + } + + render(:template => 'fckeditor/files_and_folders', :layout => false) + + rescue + render(:template => 'fckeditor/files_and_folders', :layout => false) + + end + + # create a new directory + def create_folder(params) + params = appendParams(params) + new_dir = params[:dir] + params[:NewFolderName] + d = Dir.mkdir(new_dir) + + render(:template => 'fckeditor/create_folder', :layout => false) + + rescue Errno::EEXIST + # directory already exists + @error = 101 + render(:template => 'fckeditor/create_folder', :layout => false) + rescue Errno::EACCES + # permission denied + @error = 103 + render(:template => 'fckeditor/create_folder', :layout => false) + rescue + # any other error + @error = 110 + render(:template => 'fckeditor/create_folder', :layout => false) + + end + + # upload a new file + # currently the FCKeditor docs only allow for 2 errors here + # file renamed and invalid file name + # not sure how to catch invalid file name yet + # I'm thinking there should be a permission denied error as well + def upload_file(params) + params = appendParams(params) + counter = 1 + @file_name = params[:NewFile].original_filename + path = nil + ext = nil + + # break it up into file and extension + # we need this to check the types and to build new names if necessary + /^(.*)(\..*)$/.match(@file_name) + path = Regexp.last_match(1) + ext = Regexp.last_match(2) + + # check to make sure this extension isn't in deny and is in allow + if ! in_array(FCKEDITOR_FILE_TYPES[params[:Type]]['deny'], ext) && + in_array(FCKEDITOR_FILE_TYPES[params[:Type]]['allow'], ext) + + while File.exist?("#{params[:dir]}#{@file_name}") + @file_name = "#{path}(#{counter})#{ext}" + params[:error] = 201 + counter = counter.next + end + + File.open("#{params[:dir]}#{@file_name}", 'w') { |f| f.write(params[:NewFile].read) } + else + # invalid file type + params[:error] = 202 + end + + render(:template => 'fckeditor/upload_file', :layout => false) + end + + # helper to setup pathing info that is common to all methods + # is there is a more Rubyesque way to do this? + # somebody let me know + def appendParams(params) + params[:error] = 0 + params[:base_dir] = FCKEDITOR_UPLOADS || 'UserFiles' + params[:url] = "#{params[:base_dir]}#{params[:Type]}#{params[:CurrentFolder]}".gsub(/\/+/, '/') + params[:dir] = "#{RAILS_ROOT}/public#{params[:url]}" + + return params + end + + # helper to see if a value exists in an array + # I'm sure there is a more Rubyesque way to do this + # somebody let me know + def in_array(haystack, needle) + if haystack != nil && needle != nil + haystack.each { |val| + if val == needle + return true + end + } + end + + return false + end +end diff --git a/trunk/app/helpers/fckeditor_helper.rb b/trunk/app/helpers/fckeditor_helper.rb new file mode 100644 index 0000000..134f130 --- /dev/null +++ b/trunk/app/helpers/fckeditor_helper.rb @@ -0,0 +1,39 @@ +module FckeditorHelper + def fckeditor( object, method, params = { }, options = { } ) + # setup params to be passed to js constructor + width = params[:width] != nil ? "'" + params[:width] + "'" : 'null' + height = params[:height] != nil ? "'" + params[:height] + "'" : 'null' + toolbarSet = params[:toolbarSet] != nil ? "'" + params[:toolbarSet] + "'" : 'null' + value = params[:value] != nil ? "'" + params[:value] + "'" : 'null' + + browser = params[:browser] || FCKEDITOR_BROWSER + basePath = params[:base_path] || FCKEDITOR_BASE + + # setup the file browser + custom_conf = "oFCKeditor.Config['ImageBrowserURL'] = " + + "'#{basePath}editor/filemanager/browser/#{browser}/browser.html?Type=Image&Connector=/fckeditor/connector';" + + "oFCKeditor.Config['LinkBrowserURL'] = " + + "'#{basePath}editor/filemanager/browser/#{browser}/browser.html?Connector=/fckeditor/connector';" + + # quote this for the js tag + basePath = "'#{basePath}'" + + # add custom config if there is one + if params[:custom_config] != nil + custom_conf += "oFCKeditor.Config['CustomConfigurationsPath'] = '" + params[:custom_config] + "';" + end + + # set file path for browser if there is one, otherwise it will be + # the FCKeditor mandated default of UserFiles + if params[:user_files_dir] != nil + custom_conf += "oFCKeditor.Config['UserFilesPath'] = '" + params[:user_files_dir] + "';" + end + + # write it out to the browser + text_area( object, method, options ) + + javascript_tag("var oFCKeditor = new FCKeditor('#{object.to_s}[#{method.to_s}]', #{width}, #{height}, #{toolbarSet}, #{value}, #{basePath});" + + custom_conf + + 'oFCKeditor.ReplaceTextarea();' + ) + end +end diff --git a/trunk/app/views/fckeditor/connector.rhtml b/trunk/app/views/fckeditor/connector.rhtml new file mode 100644 index 0000000..5a92a50 --- /dev/null +++ b/trunk/app/views/fckeditor/connector.rhtml @@ -0,0 +1,2 @@ +

Fckeditor#connector

+

Find me in app/views/fckeditor/connector.rhtml

diff --git a/trunk/app/views/fckeditor/create_folder.rxml b/trunk/app/views/fckeditor/create_folder.rxml new file mode 100644 index 0000000..4fb32e1 --- /dev/null +++ b/trunk/app/views/fckeditor/create_folder.rxml @@ -0,0 +1,7 @@ +xml.instruct! + +xml.Connector( "command" => params[:Command], "resourceType" => params[:Type] ) do + xml.CurrentFolder( "path" => params[:CurrentFolder], "url" => @url ) + xml.Error( "number" => @error ) +end + diff --git a/trunk/app/views/fckeditor/files_and_folders.rxml b/trunk/app/views/fckeditor/files_and_folders.rxml new file mode 100644 index 0000000..52735d4 --- /dev/null +++ b/trunk/app/views/fckeditor/files_and_folders.rxml @@ -0,0 +1,18 @@ +xml.instruct! + +xml.Connector( "command" => params[:Command], "resourceType" => params[:Type] ) do + xml.CurrentFolder( "path" => params[:CurrentFolder], "url" => params[:url] ) + + xml.Folders do + @dirs.each do |dir| + xml.Folder("name" => dir) + end + end + + xml.Files do + @files.each do |file| + xml.File("name" => file[:name], "size" => file[:size] ) + end + end +end + diff --git a/trunk/app/views/fckeditor/index.rhtml b/trunk/app/views/fckeditor/index.rhtml new file mode 100644 index 0000000..60c54d5 --- /dev/null +++ b/trunk/app/views/fckeditor/index.rhtml @@ -0,0 +1,41 @@ + + +<%= javascript_include_tag "#{FCKEDITOR_BASE}fckeditor" %> + + + +<%= + fckeditor( :object, :value, { + :width => '600px', + :height => '500px', + + # only need this if it's different than the global + # or the default file browser, currently only default is supported + #:browser => 'mcpuk', + + # don't need to pass this, it should be set in environment.rb + # in fact passing this in is currenty ignored + #:base_path => "#{FCKEDITOR_BASE}", + + # don't need to pass this, it should be set in environment.rb + # in fact passing this in is currenty ignored + #:user_files_dir => "#{FCKEDITOR_UPLOADS}", + + :custom_config => '/javascripts/fckconfig_custom.js' + } + ) +-%> + +

+Use these to debug +

+ + +
+

+ +Test Folder and Files +
Test Folder + + + diff --git a/trunk/app/views/fckeditor/upload_file.rhtml b/trunk/app/views/fckeditor/upload_file.rhtml new file mode 100644 index 0000000..ab9592b --- /dev/null +++ b/trunk/app/views/fckeditor/upload_file.rhtml @@ -0,0 +1,2 @@ +<%= javascript_tag("window.parent.frames['frmUpload'].OnUploadCompleted(#{params[:error]}, '#{@file_name}');") -%> + diff --git a/trunk/config/environment.rb.fck_settings b/trunk/config/environment.rb.fck_settings new file mode 100644 index 0000000..fc030a0 --- /dev/null +++ b/trunk/config/environment.rb.fck_settings @@ -0,0 +1,34 @@ + +# fckeditor settings +# base URI for your fckeditor install +FCKEDITOR_BASE = '/fckeditor/' + +# which File Browser should we use +# if it's not set here or in the fckeditor() call +# it will defaul to the default file browser +# only default is supported currently, need to implemnt actions for mcpuk +FCKEDITOR_BROWSER = 'default' + +# where you want the file browser to look for files +# this path starts at public/ so your settings should account for that +FCKEDITOR_UPLOADS = '/UserFiles/' + +# this controls what files are allowed to be uploaded for defferent "Types" +# if there is only a deny anything other than those listed would be allowed +# if there is only an allow only those listed would be allowed +# the settings here are just a starting point, pay special attention to +# File => deny and add anything you don't want anybody to be able ot upload +FCKEDITOR_FILE_TYPES = { + 'File' => { + 'deny' => ['.rb','.php','.asp','.aspx','.ascx','.jsp','.cfm','.cfc','.pl','.bat','.cmd','.exe','.dll','.reg'] + }, + 'Image' => { + 'allow' => ['.jpg','.gif','.jpeg','.png'] + }, + 'Flash' => { + 'allow' => ['.swf','.fla'] + }, + 'Media' => { + 'allow' => ['.swf','.fla','.jpg','.gif','.jpeg','.png','.avi','.mpg','.mpeg'] + } +} diff --git a/trunk/public/UserFiles/File/.keep b/trunk/public/UserFiles/File/.keep new file mode 100644 index 0000000..e69de29 diff --git a/trunk/public/UserFiles/Flash/.keep b/trunk/public/UserFiles/Flash/.keep new file mode 100644 index 0000000..e69de29 diff --git a/trunk/public/UserFiles/Image/.keep b/trunk/public/UserFiles/Image/.keep new file mode 100644 index 0000000..e69de29 diff --git a/trunk/public/UserFiles/Media/.keep b/trunk/public/UserFiles/Media/.keep new file mode 100644 index 0000000..e69de29 diff --git a/trunk/public/fckeditor/fckeditor.js.patched.js b/trunk/public/fckeditor/fckeditor.js.patched.js new file mode 100644 index 0000000..46f5fc5 --- /dev/null +++ b/trunk/public/fckeditor/fckeditor.js.patched.js @@ -0,0 +1,171 @@ +/* + * FCKeditor - The text editor for internet + * Copyright (C) 2003-2005 Frederico Caldeira Knabben + * + * Licensed under the terms of the GNU Lesser General Public License: + * http://www.opensource.org/licenses/lgpl-license.php + * + * For further information visit: + * http://www.fckeditor.net/ + * + * File Name: fckeditor.js + * This is the integration file for JavaScript. + * + * It defines the FCKeditor class that can be used to create editor + * instances in a HTML page in the client side. For server side + * operations, use the specific integration system. + * + * File Authors: + * Frederico Caldeira Knabben (fredck@fckeditor.net) + */ + +// FCKeditor Class +var FCKeditor = function( instanceName, width, height, toolbarSet, value, basePath ) +{ + // Properties + this.InstanceName = instanceName ; + this.Width = width || '100%' ; + this.Height = height || '200' ; + this.ToolbarSet = toolbarSet || 'Default' ; + this.Value = value || '' ; + this.BasePath = basePath || '/fckeditor/' ; + this.CheckBrowser = true ; + this.DisplayErrors = true ; + this.EnableSafari = false ; // This is a temporary property, while Safari support is under development. + + this.Config = new Object() ; + + // Events + this.OnError = null ; // function( source, errorNumber, errorDescription ) +} + +FCKeditor.prototype.Create = function() +{ + // Check for errors + if ( !this.InstanceName || this.InstanceName.length == 0 ) + { + this._ThrowError( 701, 'You must specify a instance name.' ) ; + return ; + } + + document.write( '
' ) ; + + if ( !this.CheckBrowser || this._IsCompatibleBrowser() ) + { + document.write( '' ) ; + document.write( this._GetConfigHtml() ) ; + document.write( this._GetIFrameHtml() ) ; + } + else + { + var sWidth = this.Width.toString().indexOf('%') > 0 ? this.Width : this.Width + 'px' ; + var sHeight = this.Height.toString().indexOf('%') > 0 ? this.Height : this.Height + 'px' ; + document.write('