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( '