Browse files

initial commit

  • Loading branch information...
0 parents commit d420fd64397a54d268575dfe8d222faef353ce2f @shanev committed Mar 16, 2009
Showing with 20,775 additions and 0 deletions.
  1. +18 −0 .gitignore
  2. +3 −0 Capfile
  3. +43 −0 README
  4. +10 −0 Rakefile
  5. +11 −0 app/controllers/application.rb
  6. +50 −0 app/controllers/clips_controller.rb
  7. +50 −0 app/controllers/featured_clips_controller.rb
  8. +9 −0 app/controllers/homes_controller.rb
  9. +24 −0 app/controllers/playlists_controller.rb
  10. +30 −0 app/controllers/sessions_controller.rb
  11. +85 −0 app/controllers/tracks_controller.rb
  12. +26 −0 app/controllers/users_controller.rb
  13. +3 −0 app/helpers/application_helper.rb
  14. +2 −0 app/helpers/clips_helper.rb
  15. +2 −0 app/helpers/featured_clips_helper.rb
  16. +2 −0 app/helpers/home_helper.rb
  17. +7 −0 app/helpers/playlists_helper.rb
  18. +2 −0 app/helpers/sessions_helper.rb
  19. +2 −0 app/helpers/tracks_helper.rb
  20. +2 −0 app/helpers/users_helper.rb
  21. +25 −0 app/models/acquire_video.rb
  22. +42 −0 app/models/clip.rb
  23. +21 −0 app/models/playlist.rb
  24. +21 −0 app/models/track.rb
  25. +95 −0 app/models/user.rb
  26. +26 −0 app/models/user_notifier.rb
  27. +11 −0 app/models/user_observer.rb
  28. +26 −0 app/services/transcode.rb
  29. +27 −0 app/views/clips/edit.html.erb
  30. +18 −0 app/views/clips/index.html.erb
  31. +16 −0 app/views/clips/new.html.erb
  32. +18 −0 app/views/clips/show.html.erb
  33. +24 −0 app/views/featured_clips/index.html.erb
  34. +14 −0 app/views/generate_email/index.rhtml
  35. +7 −0 app/views/homes/show.html.erb
  36. +63 −0 app/views/layouts/application.rhtml
  37. +17 −0 app/views/layouts/tracks.html.erb
  38. +10 −0 app/views/playlists/show.html.erb
  39. +1 −0 app/views/playlists/show.xml.erb
  40. +16 −0 app/views/sessions/new.rhtml
  41. +12 −0 app/views/tracks/edit.html.erb
  42. +18 −0 app/views/tracks/index.html.erb
  43. +11 −0 app/views/tracks/new.html.erb
  44. +3 −0 app/views/tracks/show.html.erb
  45. +3 −0 app/views/user_notifier/activation.rhtml
  46. +8 −0 app/views/user_notifier/signup_notification.rhtml
  47. +16 −0 app/views/users/new.rhtml
  48. +45 −0 config/boot.rb
  49. +36 −0 config/database.yml.example
  50. +71 −0 config/environment.rb
  51. +22 −0 config/environments/development.rb
  52. +18 −0 config/environments/production.rb
  53. +20 −0 config/environments/test.rb
  54. +54 −0 config/lighttpd.conf
  55. +7 −0 config/mongrel_cluster.yml
  56. +16 −0 config/routes.rb
  57. +58 −0 db/development_structure.sql
  58. +14 −0 db/migrate/002_create_clips.rb
  59. +14 −0 db/migrate/003_create_playlists.rb
  60. +18 −0 db/migrate/004_create_tracks.rb
  61. +21 −0 db/migrate/006_create_users.rb
  62. +9 −0 db/migrate/007_add_playlist_to_users.rb
  63. +9 −0 db/migrate/008_add_featured_flag_to_clip.rb
  64. +48 −0 db/schema.rb
  65. +2 −0 doc/README_FOR_APP
  66. +120 −0 lib/authenticated_system.rb
  67. +113 −0 lib/authenticated_test_helper.rb
  68. +102 −0 lib/tasks/capistrano.rake
  69. +30 −0 public/404.html
  70. +30 −0 public/500.html
  71. +10 −0 public/dispatch.cgi
  72. +24 −0 public/dispatch.fcgi
  73. +10 −0 public/dispatch.rb
  74. 0 public/favicon.ico
  75. BIN public/images/rails.png
  76. +2 −0 public/javascripts/application.js
  77. +833 −0 public/javascripts/controls.js
  78. +942 −0 public/javascripts/dragdrop.js
  79. +1,088 −0 public/javascripts/effects.js
  80. +2,515 −0 public/javascripts/prototype.js
  81. +1 −0 public/playlist.xml
  82. +1 −0 public/robots.txt
  83. +103 −0 public/stylesheets/application.css
  84. +9 −0 public/stylesheets/reset-fonts-grids.css
  85. +74 −0 public/stylesheets/scaffold.css
  86. BIN public/swf/mediaplayer.swf
  87. +3 −0 script/about
  88. +3 −0 script/breakpointer
  89. +3 −0 script/console
  90. +3 −0 script/destroy
  91. +3 −0 script/generate
  92. +3 −0 script/performance/benchmarker
  93. +3 −0 script/performance/profiler
  94. +3 −0 script/plugin
  95. +3 −0 script/process/inspector
  96. +3 −0 script/process/reaper
  97. +3 −0 script/process/spawner
  98. +3 −0 script/runner
  99. +3 −0 script/server
  100. +100 −0 test/fixtures/acquire_video/fake_raw_email
  101. +2,022 −0 test/fixtures/acquire_video/test_video
  102. +16 −0 test/fixtures/clips.yml
  103. BIN test/fixtures/files/Angry.3gp
  104. BIN test/fixtures/files/Keechu.mpg
  105. BIN test/fixtures/files/andrew1.wmv
  106. BIN test/fixtures/files/dcha-preview.avi
  107. BIN test/fixtures/files/google2.mp4
  108. BIN test/fixtures/files/hardons.mp3
  109. BIN test/fixtures/files/jojomayermd2005.mov
  110. +13 −0 test/fixtures/playlists.yml
  111. +21 −0 test/fixtures/tracks.yml
  112. +17 −0 test/fixtures/users.yml
  113. +61 −0 test/functional/clips_controller_test.rb
  114. +18 −0 test/functional/featured_clips_controller_test.rb
  115. +20 −0 test/functional/homes_controller_test.rb
  116. +21 −0 test/functional/playlists_controller_test.rb
  117. +81 −0 test/functional/sessions_controller_test.rb
  118. +62 −0 test/functional/tracks_controller_test.rb
  119. +68 −0 test/functional/users_controller_test.rb
  120. +37 −0 test/test_helper.rb
  121. +39 −0 test/unit/acquire_video_test.rb
  122. +24 −0 test/unit/clip_test.rb
  123. +36 −0 test/unit/playlist_test.rb
  124. +55 −0 test/unit/service/transcoder_test.rb
  125. +21 −0 test/unit/track_test.rb
  126. +31 −0 test/unit/user_notifier_test.rb
  127. +98 −0 test/unit/user_test.rb
  128. +371 −0 vendor/gems/capistrano-1.99.1/CHANGELOG
  129. +20 −0 vendor/gems/capistrano-1.99.1/MIT-LICENSE
  130. +38 −0 vendor/gems/capistrano-1.99.1/README
  131. +4 −0 vendor/gems/capistrano-1.99.1/bin/cap
  132. +78 −0 vendor/gems/capistrano-1.99.1/bin/capify
  133. +14 −0 vendor/gems/capistrano-1.99.1/examples/sample.rb
  134. +2 −0 vendor/gems/capistrano-1.99.1/lib/capistrano.rb
  135. +41 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/callback.rb
  136. +46 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/cli.rb
  137. +82 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/cli/execute.rb
  138. +102 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/cli/help.rb
  139. +53 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/cli/help.txt
  140. +183 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/cli/options.rb
  141. +24 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/cli/ui.rb
  142. +141 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/command.rb
  143. +38 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/configuration.rb
  144. +37 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/configuration/actions/file_transfer.rb
  145. +46 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/configuration/actions/inspect.rb
  146. +94 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/configuration/actions/invocation.rb
  147. +144 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/configuration/callbacks.rb
  148. +111 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/configuration/connections.rb
  149. +126 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/configuration/execution.rb
  150. +112 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/configuration/loading.rb
  151. +190 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/configuration/namespaces.rb
  152. +52 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/configuration/roles.rb
  153. +69 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/configuration/servers.rb
  154. +111 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/configuration/variables.rb
  155. +12 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/errors.rb
  156. +57 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/extensions.rb
  157. +125 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/gateway.rb
  158. +59 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/logger.rb
  159. +32 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/compat.rb
  160. +456 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/deploy.rb
  161. +44 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/deploy/dependencies.rb
  162. +46 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/deploy/local_dependency.rb
  163. +65 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/deploy/remote_dependency.rb
  164. +19 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/deploy/scm.rb
  165. +180 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/deploy/scm/base.rb
  166. +86 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/deploy/scm/bzr.rb
  167. +85 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/deploy/scm/darcs.rb
  168. +126 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/deploy/scm/perforce.rb
  169. +103 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/deploy/scm/subversion.rb
  170. +19 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/deploy/strategy.rb
  171. +64 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/deploy/strategy/base.rb
  172. +20 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/deploy/strategy/checkout.rb
  173. +137 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/deploy/strategy/copy.rb
  174. +20 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/deploy/strategy/export.rb
  175. +52 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/deploy/strategy/remote.rb
  176. +41 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/deploy/strategy/remote_cache.rb
  177. +53 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/deploy/templates/maintenance.rhtml
  178. +35 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/standard.rb
  179. +53 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/templates/maintenance.rhtml
  180. +33 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/recipes/upgrade.rb
  181. +51 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/server_definition.rb
  182. +268 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/shell.rb
  183. +61 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/ssh.rb
  184. +61 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/task_definition.rb
  185. +129 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/upload.rb
  186. +22 −0 vendor/gems/capistrano-1.99.1/lib/capistrano/version.rb
  187. +131 −0 vendor/gems/capistrano-1.99.1/test/cli/execute_test.rb
  188. +139 −0 vendor/gems/capistrano-1.99.1/test/cli/help_test.rb
  189. +226 −0 vendor/gems/capistrano-1.99.1/test/cli/options_test.rb
  190. +28 −0 vendor/gems/capistrano-1.99.1/test/cli/ui_test.rb
  191. +17 −0 vendor/gems/capistrano-1.99.1/test/cli_test.rb
  192. +274 −0 vendor/gems/capistrano-1.99.1/test/command_test.rb
  193. +40 −0 vendor/gems/capistrano-1.99.1/test/configuration/actions/file_transfer_test.rb
  194. +62 −0 vendor/gems/capistrano-1.99.1/test/configuration/actions/inspect_test.rb
  195. +166 −0 vendor/gems/capistrano-1.99.1/test/configuration/actions/invocation_test.rb
  196. +207 −0 vendor/gems/capistrano-1.99.1/test/configuration/callbacks_test.rb
  197. +180 −0 vendor/gems/capistrano-1.99.1/test/configuration/connections_test.rb
  198. +159 −0 vendor/gems/capistrano-1.99.1/test/configuration/execution_test.rb
  199. +119 −0 vendor/gems/capistrano-1.99.1/test/configuration/loading_test.rb
  200. +283 −0 vendor/gems/capistrano-1.99.1/test/configuration/namespace_dsl_test.rb
  201. +48 −0 vendor/gems/capistrano-1.99.1/test/configuration/roles_test.rb
  202. +80 −0 vendor/gems/capistrano-1.99.1/test/configuration/servers_test.rb
  203. +180 −0 vendor/gems/capistrano-1.99.1/test/configuration/variables_test.rb
  204. +81 −0 vendor/gems/capistrano-1.99.1/test/configuration_test.rb
  205. +55 −0 vendor/gems/capistrano-1.99.1/test/deploy/scm/base_test.rb
  206. +124 −0 vendor/gems/capistrano-1.99.1/test/deploy/strategy/copy_test.rb
  207. +69 −0 vendor/gems/capistrano-1.99.1/test/extensions_test.rb
  208. +5 −0 vendor/gems/capistrano-1.99.1/test/fixtures/cli_integration.rb
  209. +5 −0 vendor/gems/capistrano-1.99.1/test/fixtures/config.rb
  210. +3 −0 vendor/gems/capistrano-1.99.1/test/fixtures/custom.rb
  211. +153 −0 vendor/gems/capistrano-1.99.1/test/gateway_test.rb
  212. +123 −0 vendor/gems/capistrano-1.99.1/test/logger_test.rb
  213. +108 −0 vendor/gems/capistrano-1.99.1/test/server_definition_test.rb
  214. +64 −0 vendor/gems/capistrano-1.99.1/test/shell_test.rb
  215. +91 −0 vendor/gems/capistrano-1.99.1/test/ssh_test.rb
  216. +93 −0 vendor/gems/capistrano-1.99.1/test/task_definition_test.rb
  217. +117 −0 vendor/gems/capistrano-1.99.1/test/upload_test.rb
  218. +42 −0 vendor/gems/capistrano-1.99.1/test/utils.rb
  219. +24 −0 vendor/gems/capistrano-1.99.1/test/version_test.rb
  220. +62 −0 vendor/gems/hpricot-0.6/CHANGELOG
  221. +18 −0 vendor/gems/hpricot-0.6/COPYING
  222. +284 −0 vendor/gems/hpricot-0.6/README
  223. +211 −0 vendor/gems/hpricot-0.6/Rakefile
  224. +1,340 −0 vendor/gems/hpricot-0.6/ext/hpricot_scan/HpricotScanService.java
  225. +6 −0 vendor/gems/hpricot-0.6/ext/hpricot_scan/extconf.rb
  226. +76 −0 vendor/gems/hpricot-0.6/ext/hpricot_scan/hpricot_common.rl
Sorry, we could not display the entire diff because too many files (367) changed.
18 .gitignore
@@ -0,0 +1,18 @@
+log/*.log
+tmp/**/*
+.DS_Store
+doc/api
+doc/app
+doc/guides/
+doc/plugins
+doc/models.svg
+doc/controllers.svg
+doc/machines.svg
+db/test.sqlite3
+db/development.sqlite3
+vendor/gems/*/doc/
+vendor/gems/*/rdoc/
+vendor/rails
+coverage
+tags
+config/database.yml
3 Capfile
@@ -0,0 +1,3 @@
+require 'capistrano/version'
+load 'deploy' if respond_to?(:namespace) # cap2 differentiator
+load 'config/deploy'
43 README
@@ -0,0 +1,43 @@
+YouCast™ is an open source Ruby on Rails video sharing application that you host on your own servers. It can be rebranded easily for your company or used as is. It is similar to a very simplified YouTube. Upload videos in any format and view them in the included Flash player. It doesn't do background processing of video yet.
+
+Main features:
+
+Upload videos, images, and music via web or mobile phone via SMS/MMS attachment
+Create a playlist of your videos, images, and music
+Play your media in a Flash player
+Get the code for the player to embed in any site (myspace, blog, etc)
+Generates thumbnails for videos
+Multi-user support with user login and user management
+Export your playlist in XSPF/Spiff format
+
+Tech specs:
+
+Ruby on Rails application designed with RESTful methodology
+Supports all major video and image formats, and mp3 for music
+Encodes all video to Flash
+Uses MMS2R for mobile media processing
+XSPF/Spiff format used for playlists for maximum portability
+
+What can you do with YouCast™?
+
+Create an internal video sharing site for your company or small business
+Use it as a base for your own video-related site
+Merge it with your existing site to add video and mobile media support
+Re-create YouTube to impress your friends
+
+How much does it cost?
+
+YouCast™ is free, but please consider donating to the project via GitHub.
+
+Installing ffmpeg
+-----------------
+http://www.thisismobility.com/blog/?p=156
+ffmpeg sources + AMR 3gpp files: /vendors/ffmpeg
+http://vexxhost.com/blog/2007/03/03/installing-ffmpeg-ffmpeg-php-mplayer-mencoder-flv2tool-lame-mp3-encoder-libogg-%E2%80%93-the-easy-way/
+
+# Install LAME
+# compile ffmpeg from source in vendor/ffmpeg
+# copy files for amr from 3gp site (included in vendor/ffmpeg)
+# copy amr files into libavcodec (included in vendor/ffmpeg)
+# compile with gmake
+# ./configure --enable-shared --enable-libmp3lame --enable-amr-nb --enable-amr-wb --extra-cflags=-I/usr/local/include --extra-ldflags=-L/usr/local/lib
10 Rakefile
@@ -0,0 +1,10 @@
+# Add your own tasks in files placed in lib/tasks ending in .rake,
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+
+require(File.join(File.dirname(__FILE__), 'config', 'boot'))
+
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+require 'tasks/rails'
11 app/controllers/application.rb
@@ -0,0 +1,11 @@
+# Filters added to this controller apply to all controllers in the application.
+# Likewise, all the methods added will be available for all controllers.
+
+class ApplicationController < ActionController::Base
+ include AuthenticatedSystem
+ before_filter :login_from_cookie
+
+ # Pick a unique cookie name to distinguish our session data from others'
+ session :session_key => '_upload2_session_id'
+
+end
50 app/controllers/clips_controller.rb
@@ -0,0 +1,50 @@
+class ClipsController < ApplicationController
+ before_filter :login_required
+ before_filter :find_playlist
+
+ # GET /clips
+ # GET /clips.xml
+ def index
+ @clips = Clip.find_all_by_user_id(current_user.id)
+
+ respond_to do |format|
+ format.html # index.html.erb
+ format.xml { render :xml => @clips }
+ end
+ end
+
+ # GET /clips/new
+ # GET /clips/new.xml
+ def new
+ @clip = Clip.new
+ @your_email = "#{current_user.login}@#{DOMAIN}"
+
+ respond_to do |format|
+ format.html # new.html.erb
+ format.xml { render :xml => @clip }
+ end
+ end
+
+ # POST /clips
+ # POST /clips.xml
+ def create
+ @clip = Clip.new(params[:clip])
+ @clip.user_id = current_user.id
+
+ respond_to do |format|
+ if @clip.save
+ flash[:notice] = 'Clip was successfully created.'
+ format.html { redirect_to home_url }
+ format.xml { render :xml => @clip, :status => :created, :location => @clip }
+ else
+ format.html { render :action => "new" }
+ format.xml { render :xml => @clip.errors }
+ end
+ end
+ end
+
+ def find_playlist
+ @playlist = Playlist.find_by_user_id(current_user.id)
+ end
+
+end
50 app/controllers/featured_clips_controller.rb
@@ -0,0 +1,50 @@
+class FeaturedClipsController < ApplicationController
+ before_filter :login_required
+ before_filter :find_playlist
+
+ # GET /clips
+ # GET /clips.xml
+ def index
+ @clips = Clip.find_all_by_user_id_and_featured(current_user.id, true)
+
+ respond_to do |format|
+ format.html # index.html.erb
+ format.xml { render :xml => @clips }
+ end
+ end
+
+ # GET /clips/new
+ # GET /clips/new.xml
+ def new
+ @clip = Clip.new
+ @your_email = "#{current_user.login}@filmprmail.com"
+
+ respond_to do |format|
+ format.html # new.html.erb
+ format.xml { render :xml => @clip }
+ end
+ end
+
+ # POST /clips
+ # POST /clips.xml
+ def create
+ @clip = Clip.new(params[:clip])
+ @clip.user_id = current_user.id
+
+ respond_to do |format|
+ if @clip.save
+ flash[:notice] = 'Clip was successfully created.'
+ format.html { redirect_to home_url }
+ format.xml { render :xml => @clip, :status => :created, :location => @clip }
+ else
+ format.html { render :action => "new" }
+ format.xml { render :xml => @clip.errors }
+ end
+ end
+ end
+
+ def find_playlist
+ @playlist = Playlist.find_by_user_id(current_user.id)
+ end
+
+end
9 app/controllers/homes_controller.rb
@@ -0,0 +1,9 @@
+class HomesController < ApplicationController
+ before_filter :login_required
+
+ # GET /home
+ def show
+ @url_for_media_player =
+ @playlist = Playlist.find_or_create_by_user_id(current_user.id)
+ end
+end
24 app/controllers/playlists_controller.rb
@@ -0,0 +1,24 @@
+class PlaylistsController < ApplicationController
+
+ # GET /clips/1
+ # GET /clips/1.xml
+ def show
+ @playlist = Playlist.find(params[:id])
+
+ respond_to do |format|
+ format.html # show.html.erb
+ format.xml { render :xml => @playlist }
+ end
+ end
+
+ # add a clip (:id) to a playlist as a track
+ # POST /playlist/add/:id
+ def add
+ clip = Clip.find(params[:id])
+ playlist = Playlist.find_by_user_id(current_user.id)
+ playlist.tracks << Track.create!(:title => clip.title, :location => clip.location)
+ flash[:notice] = 'Track was successfully created.'
+
+ redirect_to clips_url
+ end
+end
30 app/controllers/sessions_controller.rb
@@ -0,0 +1,30 @@
+# This controller handles the login/logout function of the site.
+class SessionsController < ApplicationController
+
+ # render new.rhtml
+ def new
+ end
+
+ def create
+ self.current_user = User.authenticate(params[:login], params[:password])
+ if logged_in?
+ if params[:remember_me] == "1"
+ self.current_user.remember_me
+ cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at }
+ end
+ redirect_back_or_default('/')
+ flash[:notice] = "Logged in successfully"
+ else
+ flash[:warn] = "Error logging in, check your password."
+ render :action => 'new'
+ end
+ end
+
+ def destroy
+ self.current_user.forget_me if logged_in?
+ cookies.delete :auth_token
+ reset_session
+ flash[:notice] = "You have been logged out."
+ redirect_back_or_default('/')
+ end
+end
85 app/controllers/tracks_controller.rb
@@ -0,0 +1,85 @@
+class TracksController < ApplicationController
+ # GET /tracks
+ # GET /tracks.xml
+ def index
+ @tracks = Track.find(:all)
+
+ respond_to do |format|
+ format.html # index.html.erb
+ format.xml { render :xml => @tracks }
+ end
+ end
+
+ # GET /tracks/1
+ # GET /tracks/1.xml
+ def show
+ @track = Track.find(params[:id])
+
+ respond_to do |format|
+ format.html # show.html.erb
+ format.xml { render :xml => @track }
+ end
+ end
+
+ # GET /tracks/new
+ # GET /tracks/new.xml
+ def new
+ @track = Track.new
+ @track.playlist = current_user.playlist
+
+ respond_to do |format|
+ format.html # new.html.erb
+ format.xml { render :xml => @track }
+ end
+ end
+
+ # GET /tracks/1/edit
+ def edit
+ @track = Track.find(params[:id])
+ end
+
+ # POST /playlist/1/tracks
+ def create
+ @track = Track.new(params[:track])
+
+ respond_to do |format|
+ if @track.save
+ flash[:notice] = 'Track was successfully created.'
+ format.html { redirect_to clips_url }
+ format.xml { render :xml => @track, :status => :created, :location => @track }
+ else
+ format.html { render :action => "new" }
+ format.xml { render :xml => @track.errors }
+ end
+ end
+ end
+
+ # PUT /tracks/1
+ # PUT /tracks/1.xml
+ def update
+ @track = Track.find(params[:id])
+
+ respond_to do |format|
+ if @track.update_attributes(params[:track])
+ flash[:notice] = 'Track was successfully updated.'
+ format.html { redirect_to playlist_track_url(@track.playlist.id, @track) }
+ format.xml { head :ok }
+ else
+ format.html { render :action => "edit" }
+ format.xml { render :xml => @track.errors }
+ end
+ end
+ end
+
+ # DELETE /tracks/1
+ # DELETE /tracks/1.xml
+ def destroy
+ @track = Track.find(params[:id])
+ @track.destroy
+
+ respond_to do |format|
+ format.html { redirect_to(tracks_url) }
+ format.xml { head :ok }
+ end
+ end
+end
26 app/controllers/users_controller.rb
@@ -0,0 +1,26 @@
+class UsersController < ApplicationController
+
+ # render new.rhtml
+ def new
+ end
+
+ def create
+ @user = User.new(params[:user])
+ @user.save!
+ self.current_user = @user
+ redirect_back_or_default('/')
+ flash[:notice] = "Thanks for signing up!"
+ rescue ActiveRecord::RecordInvalid
+ render :action => 'new'
+ end
+
+ def activate
+ self.current_user = User.find_by_activation_code(params[:id])
+ if logged_in? && !current_user.activated?
+ current_user.activate
+ flash[:notice] = "Signup complete!"
+ end
+ redirect_back_or_default('/')
+ end
+
+end
3 app/helpers/application_helper.rb
@@ -0,0 +1,3 @@
+# Methods added to this helper will be available to all templates in the application.
+module ApplicationHelper
+end
2 app/helpers/clips_helper.rb
@@ -0,0 +1,2 @@
+module ClipsHelper
+end
2 app/helpers/featured_clips_helper.rb
@@ -0,0 +1,2 @@
+module FeaturedClipsHelper
+end
2 app/helpers/home_helper.rb
@@ -0,0 +1,2 @@
+module HomeHelper
+end
7 app/helpers/playlists_helper.rb
@@ -0,0 +1,7 @@
+module PlaylistsHelper
+
+ def render_thumbnail(track)
+ thumb = File.basename(track.location, File.extname(track.location)).concat("_80x80.jpg")
+ image_tag(File.join("/clips", thumb))
+ end
+end
2 app/helpers/sessions_helper.rb
@@ -0,0 +1,2 @@
+module SessionsHelper
+end
2 app/helpers/tracks_helper.rb
@@ -0,0 +1,2 @@
+module TracksHelper
+end
2 app/helpers/users_helper.rb
@@ -0,0 +1,2 @@
+module UsersHelper
+end
25 app/models/acquire_video.rb
@@ -0,0 +1,25 @@
+require 'mms2r'
+require 'mms2r/media'
+require 'tmail'
+
+class AcquireVideo < ActionMailer::Base
+
+ def receive(email)
+ user = User.find_by_login(email.to.first.strip.split(/@/).first)
+
+ if user
+ begin
+ mms = MMS2R::Media.create(email, logger)
+ mms.process
+ title = mms.get_subject
+ title = "From my phone" if title.nil? || title.length == 0
+ logger.info("title: #{title}")
+ Clip.create!(:uploaded_data => mms.get_media, :user_id => user.id, :title => title)
+ rescue => e
+ logger.error("Error occurred: #{e.message}")
+ ensure
+ mms.purge
+ end
+ end
+ end
+end
42 app/models/clip.rb
@@ -0,0 +1,42 @@
+require 'transcode'
+require 'fileutils'
+
+class Clip < ActiveRecord::Base
+ include FileUtils
+
+ belongs_to :user
+ validates_presence_of :title, :location, :user_id
+
+ after_destroy do |clip|
+ Playlist.find(:all).each do |playlist|
+ playlist.tracks.delete_if { |track| track.title == clip.title }
+ end
+ end
+
+ def uploaded_data=(file)
+ begin
+ logger.info("original filename1: #{file.original_filename}")
+
+ tmp_file = File.join(RAILS_ROOT, "tmp", file.original_filename)
+ File.open(tmp_file, File::CREAT|File::TRUNC|File::WRONLY,0666){ |f| f.write(file.read) }
+
+ clips_dir = File.join(RAILS_ROOT, "public", "system")
+
+ case File.extname(tmp_file).sub!(/./, "").to_sym
+ when :mp3, :jpg, :png, :gif, :swf
+ cp tmp_file, clips_dir
+ logger.info("original filename2: #{file.original_filename}")
+
+ self.location = File.join(CLIPS_URL, file.original_filename)
+ else
+ basename = File.basename(tmp_file).split(/\.\w+$/).first
+ self.location = File.join(CLIPS_URL, new_filename = "#{basename}.flv")
+ Transcoder.process(tmp_file, File.join(clips_dir, new_filename), logger)
+ Transcoder.thumbnail(tmp_file, File.join(clips_dir, "#{basename}_80x80.jpg"), logger)
+ end
+ rescue => e
+ logger.error(e.message)
+ logger.error("Error occurred!!!!!!!!")
+ end
+ end
+end
21 app/models/playlist.rb
@@ -0,0 +1,21 @@
+class Playlist < ActiveRecord::Base
+ has_many :tracks
+ belongs_to :user
+
+ alias_method :base_to_xml, :to_xml
+
+ def to_xml(options={})
+ options.merge!(:skip_instruct => true, :include => :tracks, :except => [ :id, :user_id ])
+
+ substitutions = {
+ /tracks/ => "trackList",
+ /<playlist>/ => "<playlist version=\"1\" xmlns=\"http://xspf.org/ns/0/\">"
+ }
+
+ returning base_to_xml(options) do |xml|
+ substitutions.each do |k, v|
+ xml.gsub!(k, v)
+ end
+ end
+ end
+end
21 app/models/track.rb
@@ -0,0 +1,21 @@
+class Track < ActiveRecord::Base
+ belongs_to :playlist
+ has_one :clip
+
+ validates_presence_of :title, :location
+ # TODO: validate uniqueness of track id in playlist scope so dup tracks can't be created
+ # validates_uniqueness_of :id, :scope => :playlist ??
+
+ # this is needed because the column named 'type' is reserved in Rails
+ # so we make it called 'none' because single table inheritance is not being used
+ # a column named 'type' is needed because it is part of the XSPF standard
+ def self.inheritance_column
+ "none"
+ end
+
+ alias_method :base_to_xml, :to_xml
+ def to_xml(options={})
+ base_to_xml(options.merge(:except => [ :id, :playlist_id ]))
+ end
+
+end
95 app/models/user.rb
@@ -0,0 +1,95 @@
+require 'digest/sha1'
+class User < ActiveRecord::Base
+ has_one :playlist
+
+ # Virtual attribute for the unencrypted password
+ attr_accessor :password
+
+ validates_presence_of :login, :email
+ validates_presence_of :password, :if => :password_required?
+ validates_presence_of :password_confirmation, :if => :password_required?
+ validates_length_of :password, :within => 4..40, :if => :password_required?
+ validates_confirmation_of :password, :if => :password_required?
+ validates_length_of :login, :within => 3..40
+ validates_length_of :email, :within => 3..100
+ validates_uniqueness_of :login, :email, :case_sensitive => false
+ before_save :encrypt_password
+ before_create :make_activation_code
+
+ # Activates the user in the database.
+ def activate
+ @activated = true
+ self.attributes = {:activated_at => Time.now.utc, :activation_code => nil}
+ save(false)
+ end
+
+ def activated?
+ !! activation_code.nil?
+ end
+
+ # Returns true if the user has just been activated.
+ def recently_activated?
+ @activated
+ end
+ # Authenticates a user by their login name and unencrypted password. Returns the user or nil.
+ def self.authenticate(login, password)
+ u = find :first, :conditions => ['login = ?', login] # need to get the salt
+ u && u.authenticated?(password) ? u : nil
+ end
+
+ # Encrypts some data with the salt.
+ def self.encrypt(password, salt)
+ Digest::SHA1.hexdigest("--#{salt}--#{password}--")
+ end
+
+ # Encrypts the password with the user salt
+ def encrypt(password)
+ self.class.encrypt(password, salt)
+ end
+
+ def authenticated?(password)
+ crypted_password == encrypt(password)
+ end
+
+ def remember_token?
+ remember_token_expires_at && Time.now.utc < remember_token_expires_at
+ end
+
+ # These create and unset the fields required for remembering users between browser closes
+ def remember_me
+ remember_me_for 2.weeks
+ end
+
+ def remember_me_for(time)
+ remember_me_until time.from_now.utc
+ end
+
+ def remember_me_until(time)
+ self.remember_token_expires_at = time
+ self.remember_token = encrypt("#{email}--#{remember_token_expires_at}")
+ save(false)
+ end
+
+ def forget_me
+ self.remember_token_expires_at = nil
+ self.remember_token = nil
+ save(false)
+ end
+
+ protected
+ # before filter
+ def encrypt_password
+ return if password.blank?
+ self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if new_record?
+ self.crypted_password = encrypt(password)
+ end
+
+ def password_required?
+ crypted_password.blank? || !password.blank?
+ end
+
+
+ def make_activation_code
+ self.activation_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
+ end
+end
26 app/models/user_notifier.rb
@@ -0,0 +1,26 @@
+class UserNotifier < ActionMailer::Base
+ include ActionController::UrlWriter
+ default_url_options[:host] = 'CHANGE_THIS'
+
+ def signup_notification(user)
+ setup_email(user)
+ @subject += 'Please activate your new account'
+
+ @body[:url] = url_for(:controller => "users", :action => "activate") + "/#{user.activation_code}"
+ end
+
+ def activation(user)
+ setup_email(user)
+ @subject += 'Your account has been activated!'
+ @body[:url] = url_for(:controller => "homes", :action => "show")
+ end
+
+ protected
+ def setup_email(user)
+ @recipients = "#{user.email}"
+ @from = "video@filmprmail.com"
+ @subject = "[Video Upload] Welcome to our site"
+ @sent_on = Time.now
+ @body[:user] = user
+ end
+end
11 app/models/user_observer.rb
@@ -0,0 +1,11 @@
+class UserObserver < ActiveRecord::Observer
+ def after_create(user)
+ UserNotifier.deliver_signup_notification(user)
+ end
+
+ def after_save(user)
+
+ UserNotifier.deliver_activation(user) if user.recently_activated?
+
+ end
+end
26 app/services/transcode.rb
@@ -0,0 +1,26 @@
+class Transcoder
+ def self.process(input, output, logger=nil)
+ out = run_ffmpeg(input, output)
+ logger.info out if logger
+ out
+ end
+
+ def self.thumbnail(input, output, logger=nil)
+ out = run_ffmpeg(input, output, thumbnail_options)
+ logger.info out if logger
+ out
+ end
+
+ private
+ def self.run_ffmpeg(input, output, options=video_options)
+ `#{FFMPEG} -y -i #{input} #{options} #{output} 2>&1`
+ end
+
+ def self.video_options
+ "-s 320x240 -ar 22050 -r 24"
+ end
+
+ def self.thumbnail_options
+ "-vcodec mjpeg -vframes 1 -an -f rawvideo -s 80x80"
+ end
+end
27 app/views/clips/edit.html.erb
@@ -0,0 +1,27 @@
+<h1>Editing clip</h1>
+
+<%= error_messages_for :clip %>
+
+<% form_for(@clip) do |f| %>
+ <p>
+ <b>Title</b><br />
+ <%= f.text_field :title %>
+ </p>
+
+ <p>
+ <b>Location</b><br />
+ <%= f.text_field :location %>
+ </p>
+
+ <p>
+ <b>User</b><br />
+ <%= f.text_field :user_id %>
+ </p>
+
+ <p>
+ <%= f.submit "Update" %>
+ </p>
+<% end %>
+
+<%= link_to 'Show', @clip %> |
+<%= link_to 'Back', clips_path %>
18 app/views/clips/index.html.erb
@@ -0,0 +1,18 @@
+<h1>Listing clips</h1>
+
+<table>
+ <tr>
+ <th>Title</th>
+ </tr>
+
+<% for clip in @clips %>
+ <tr>
+ <td><%=h clip.title %></td>
+ <td><%= button_to 'Add to playlist', :controller => 'playlists', :action => 'add', :id => clip.id %></td>
+ <!-- <td><%#= link_to 'Edit', edit_clip_path(clip) %></td>
+ <td><%#= link_to 'Destroy', clip, :confirm => 'Are you sure?', :method => :delete %></td> -->
+ </tr>
+<% end %>
+</table>
+
+<br />
16 app/views/clips/new.html.erb
@@ -0,0 +1,16 @@
+<h1>New clip</h1>
+
+<%= error_messages_for :clip %>
+
+Email video to: <b><%= @your_email %></b> using your mobile phone,
+<br/>
+or upload:
+<% form_for Clip.new(:user_id => current_user.id), :html => { :multipart => true } do |f| -%>
+ <p>File: <%= f.file_field :uploaded_data %></p>
+ <p>Title: <%= f.text_field :title %></p>
+ <p><%= f.submit "Send" %>
+<% end %>
+
+<p>Note: It will take a few minutes after you upload for your video to show up in your playlist.</p>
+
+<%= link_to 'Back', { :controller => 'home', :action => 'index' } %>
18 app/views/clips/show.html.erb
@@ -0,0 +1,18 @@
+<p>
+ <b>Title:</b>
+ <%=h @clip.title %>
+</p>
+
+<p>
+ <b>Location:</b>
+ <%=h @clip.location %>
+</p>
+
+<p>
+ <b>User:</b>
+ <%=h @clip.user_id %>
+</p>
+
+
+<%= link_to 'Edit', edit_clip_path(@clip) %> |
+<%= link_to 'Back', clips_path %>
24 app/views/featured_clips/index.html.erb
@@ -0,0 +1,24 @@
+<h1>Listing clips</h1>
+
+<table>
+ <tr>
+ <th>Title</th>
+ <th>Location</th>
+ <th>User</th>
+ </tr>
+
+<% for clip in @clips %>
+ <tr>
+ <td><%=h clip.title %></td>
+ <td><%=h clip.location %></td>
+ <td><%=h clip.user_id %></td>
+ <td><%= link_to 'Show', clip %></td>
+ <td><%= link_to 'Edit', edit_clip_path(clip) %></td>
+ <td><%= link_to 'Destroy', clip, :confirm => 'Are you sure?', :method => :delete %></td>
+ </tr>
+<% end %>
+</table>
+
+<br />
+
+<%= link_to 'New clip', new_clip_path %>
14 app/views/generate_email/index.rhtml
@@ -0,0 +1,14 @@
+
+Email video to: <%= @your_email %>
+<br/>
+or upload:
+<%= form_tag({:action=>'save_video'}, :multipart => true)%>
+ <input type="file" name="video_file" />
+ <input type="submit" name="Upload" />
+</form>
+
+<embed src="/swf/mediaplayer.swf" width="320" height="340" allowfullscreen="true" flashvars="&displayheight=240&file=playlist.xml&height=340&width=320" />
+
+<p>
+<%= link_to "Logout", { :controller => "account", :action => "logout" } %>
+</p>
7 app/views/homes/show.html.erb
@@ -0,0 +1,7 @@
+<embed src="<%= SWF_URL %>/mediaplayer.swf" width="480" height="480" allowfullscreen="true" flashvars="&displayheight=380&file=<%= formatted_playlist_path(@playlist, :xml) %>&height=480&width=480" />
+
+<%= button_to "Upload new media", new_clip_path %><br/>
+
+<p>Code for this player: </p>
+<p><pre><small>&lt;embed src="<%= SWF_URL %>/mediaplayer.swf" width="480" height="480"<br/> allowfullscreen="true" flashvars="&displayheight=380<br/>&file=<%= formatted_playlist_url(@playlist, :xml).to_s %>&height=480&width=480" /&gt;
+</pre></small></p>
63 app/views/layouts/application.rhtml
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>YouCast</title>
+ <%= stylesheet_link_tag 'reset-fonts-grids', 'application' %>
+ <%= javascript_include_tag 'prototype' %>
+</head>
+
+<body>
+ <div id="doc" class="yui-t4">
+ <div id="hd">
+ <div class="yui-ge">
+ <div class="yui-u first">
+ <h1>YouCast</h1>
+ </div>
+ <div class="yui-u">
+ <% if logged_in? %>
+ <%= button_to "Logout", session_path, :confirm => "Are you sure?", :method => :delete %>
+ <% else %>
+ <ul>
+ <li><%= link_to "Sign up", new_user_path %></li>
+ <li><%= link_to "Log in", new_session_path %></li>
+ </ul>
+ <% end %>
+ </div>
+ </div>
+ <% if flash.any? %>
+ <div id="flash">
+ <p style="color: green"><%= flash[:notice] %></p>
+ <%= flash[:warn] %>
+ <%= flash[:error] %>
+ </div>
+ <% flash.clear %>
+ <% end %>
+
+ </div>
+
+ <div id="bd">
+ <div id="yui-main">
+ <div class="yui-b">
+ <div class="yui-g">
+ <%= yield %>
+ </div>
+ </div>
+ </div>
+ <% if logged_in? %>
+ <div class="yui-b" id="sidebar">
+ <ul>
+ <li class="navitem"><%= link_to_unless_current "My Player", home_path, :class => "raw" %></li>
+ <li class="navitem"><%= link_to_unless_current "My Playlist", playlist_path(@playlist), :class => "raw" %></li>
+ <li class="navitem"><%= link_to_unless_current "My Uploads", clips_path, :class => "raw" %></li>
+ <!-- <li class="navitem"><%#= link_to_unless_current "Featured Media", featured_clips_path, :class => "raw" %></li> -->
+ </ul>
+ </div>
+ <% end %>
+ </div>
+
+ <div id="ft">
+ </div>
+ </div>
+</body>
+</html>
17 app/views/layouts/tracks.html.erb
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
+ <title>Tracks: <%= controller.action_name %></title>
+ <%= stylesheet_link_tag 'scaffold' %>
+</head>
+<body>
+
+<p style="color: green"><%= flash[:notice] %></p>
+
+<%= yield %>
+
+</body>
+</html>
10 app/views/playlists/show.html.erb
@@ -0,0 +1,10 @@
+<h2>Playlist for <%= current_user.login %></h2>
+
+<% @playlist.tracks.each do |track| %>
+ <p>
+ <%= render_thumbnail(track) %> <%= track.title %>
+ <!-- <%#= link_to "Edit", edit_playlist_track_path(@playlist, track) %>
+ <%#= link_to "Delete", playlist_track_path(@playlist, track), :confirm => "Are you sure?", :method => :delete %> -->
+ </p>
+<% end %>
+
1 app/views/playlists/show.xml.erb
@@ -0,0 +1 @@
+@playlist.to_xml
16 app/views/sessions/new.rhtml
@@ -0,0 +1,16 @@
+<%= error_messages_for :session %>
+
+<% form_tag session_path do -%>
+<p><label for="login">Login</label><br/>
+<%= text_field_tag 'login' %></p>
+
+<p><label for="password">Password</label><br/>
+<%= password_field_tag 'password' %></p>
+
+<p><label for="remember_me">Remember me:</label>
+<%= check_box_tag 'remember_me' %></p>
+
+<p><%= submit_tag 'Log in' %></p>
+<% end -%>
+
+<p>Are you a new user? <%= link_to "Sign up", new_user_path %></p>
12 app/views/tracks/edit.html.erb
@@ -0,0 +1,12 @@
+<h1>Editing track</h1>
+
+<%= error_messages_for :track %>
+
+<% form_for [@track.playlist, @track] do |f| %>
+ <p>
+ <%= f.submit "Update" %>
+ </p>
+<% end %>
+
+<%= link_to 'Show', @track %> |
+<%= link_to 'Back', tracks_path %>
18 app/views/tracks/index.html.erb
@@ -0,0 +1,18 @@
+<h1>Listing tracks</h1>
+
+<table>
+ <tr>
+ </tr>
+
+<% for track in @tracks %>
+ <tr>
+ <td><%= link_to 'Show', track %></td>
+ <td><%= link_to 'Edit', playlist_edit_track_path(track.playlist, track) %></td>
+ <td><%= link_to 'Destroy', track, :confirm => 'Are you sure?', :method => :delete %></td>
+ </tr>
+<% end %>
+</table>
+
+<br />
+
+<%= link_to 'New track', playlist_new_track_path(@playlist) %>
11 app/views/tracks/new.html.erb
@@ -0,0 +1,11 @@
+<h1>New track</h1>
+
+<%= error_messages_for :track %>
+
+<% form_for([@track.playlist, @track]) do |f| %>
+ <p>
+ <%= f.submit "Create" %>
+ </p>
+<% end %>
+
+<%= link_to 'Back', playlist_tracks_path(@playlist) %>
3 app/views/tracks/show.html.erb
@@ -0,0 +1,3 @@
+
+<%= link_to 'Edit', playlist_edit_track_path(@track.playlist, @track) %> |
+<%= link_to 'Back', playlist_tracks_path(@track.playlist) %>
3 app/views/user_notifier/activation.rhtml
@@ -0,0 +1,3 @@
+<%= @user.login %>, your account has been activated. You may now start uploading your videos:
+
+ <%= @url %>
8 app/views/user_notifier/signup_notification.rhtml
@@ -0,0 +1,8 @@
+Your account has been created.
+
+ Username: <%= @user.login %>
+ Password: <%= @user.password %>
+
+Visit this url to activate your account:
+
+ <%= @url %>
16 app/views/users/new.rhtml
@@ -0,0 +1,16 @@
+<%= error_messages_for :user %>
+<% form_for :user, :url => users_path do |f| -%>
+<p><label for="login">Login</label><br/>
+<%= f.text_field :login %></p>
+
+<p><label for="email">Email</label><br/>
+<%= f.text_field :email %></p>
+
+<p><label for="password">Password</label><br/>
+<%= f.password_field :password %></p>
+
+<p><label for="password_confirmation">Confirm Password</label><br/>
+<%= f.password_field :password_confirmation %></p>
+
+<p><%= submit_tag 'Sign up' %></p>
+<% end -%>
45 config/boot.rb
@@ -0,0 +1,45 @@
+# Don't change this file. Configuration is done in config/environment.rb and config/environments/*.rb
+
+unless defined?(RAILS_ROOT)
+ root_path = File.join(File.dirname(__FILE__), '..')
+
+ unless RUBY_PLATFORM =~ /mswin32/
+ require 'pathname'
+ root_path = Pathname.new(root_path).cleanpath(true).to_s
+ end
+
+ RAILS_ROOT = root_path
+end
+
+unless defined?(Rails::Initializer)
+ if File.directory?("#{RAILS_ROOT}/vendor/rails")
+ require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
+ else
+ require 'rubygems'
+
+ environment_without_comments = IO.readlines(File.dirname(__FILE__) + '/environment.rb').reject { |l| l =~ /^#/ }.join
+ environment_without_comments =~ /[^#]RAILS_GEM_VERSION = '([\d.]+)'/
+ rails_gem_version = $1
+
+ if version = defined?(RAILS_GEM_VERSION) ? RAILS_GEM_VERSION : rails_gem_version
+ # Asking for 1.1.6 will give you 1.1.6.5206, if available -- makes it easier to use beta gems
+ rails_gem = Gem.cache.search('rails', "~>#{version}.0").sort_by { |g| g.version.version }.last
+
+ if rails_gem
+ gem "rails", "=#{rails_gem.version.version}"
+ require rails_gem.full_gem_path + '/lib/initializer'
+ else
+ STDERR.puts %(Cannot find gem for Rails ~>#{version}.0:
+ Install the missing gem with 'gem install -v=#{version} rails', or
+ change environment.rb to define RAILS_GEM_VERSION with your desired version.
+ )
+ exit 1
+ end
+ else
+ gem "rails"
+ require 'initializer'
+ end
+ end
+
+ Rails::Initializer.run(:set_load_path)
+end
36 config/database.yml.example
@@ -0,0 +1,36 @@
+# MySQL (default setup). Versions 4.1 and 5.0 are recommended.
+#
+# Install the MySQL driver:
+# gem install mysql
+# On MacOS X:
+# gem install mysql -- --include=/usr/local/lib
+# On Windows:
+# gem install mysql
+# Choose the win32 build.
+# Install MySQL and put its /bin directory on your path.
+#
+# And be sure to use new-style password hashing:
+# http://dev.mysql.com/doc/refman/5.0/en/old-client.html
+development:
+ adapter: mysql
+ database: upload_dev
+ username: root
+ password:
+ host: localhost
+
+# Warning: The database defined as 'test' will be erased and
+# re-generated from your development database when you run 'rake'.
+# Do not set this db to the same as development or production.
+test:
+ adapter: mysql
+ database: upload_test
+ username: root
+ password:
+ host: localhost
+
+production:
+ adapter: mysql
+ database: upload_prod
+ username: root
+ password:
+ host: localhost
71 config/environment.rb
@@ -0,0 +1,71 @@
+# Be sure to restart your web server when you modify this file.
+
+# Uncomment below to force Rails into production mode when
+# you don't control web/app server and can't set it the proper way
+# ENV['RAILS_ENV'] ||= 'production'
+
+# Specifies gem version of Rails to use when vendor/rails is not present
+RAILS_GEM_VERSION = '1.2.3' unless defined? RAILS_GEM_VERSION
+
+DOMAIN = "208.78.96.232"
+CLIPS_URL = "http://208.78.96.232/system"
+SWF_URL = "http://208.78.96.232/swf"
+FFMPEG = "/usr/bin/ffmpeg"
+
+# Bootstrap the Rails environment, frameworks, and dwefault configuration
+require File.join(File.dirname(__FILE__), 'boot')
+
+Rails::Initializer.run do |config|
+ # Settings in config/environments/* take precedence over those specified here
+
+ # Skip frameworks you're not going to use (only works if using vendor/rails)
+ config.frameworks -= [ :action_web_service, :active_resource ]
+
+ # Only load the plugins named here, by default all plugins in vendor/plugins are loaded
+ # config.plugins = %W( exception_notification ssl_requirement )
+
+ # Add additional load paths for your own custom dirs
+ config.load_paths += Dir["#{RAILS_ROOT}/vendor/gems/**"].map do |dir|
+ File.directory?(lib = "#{dir}/lib") ? lib : dir
+ end
+ config.load_paths += Dir["#{RAILS_ROOT}/app/services"]
+
+ # Force all environments to use the same logger level
+ # (by default production uses :info, the others :debug)
+ config.log_level = :debug
+
+ # Use the database for sessions instead of the file system
+ # (create the session table with 'rake db:sessions:create')
+ # config.action_controller.session_store = :active_record_store
+ config.action_controller.session = { :secret => "asdjfhasdjkfaslfjkhadslfkjhadsfljkahsdfljkadshf" }
+
+ # Use SQL instead of Active Record's schema dumper when creating the test database.
+ # This is necessary if your schema can't be completely dumped by the schema dumper,
+ # like if you have constraints or database-specific column types
+ # config.active_record.schema_format = :sql
+
+ # Activate observers that should always be running
+ # config.active_record.observers = :cacher, :garbage_collector
+ config.active_record.observers = :user_observer
+
+ # Make Active Record use UTC-base instead of local time
+ # config.active_record.default_timezone = :utc
+
+ # See Rails::Configuration for more options
+end
+
+# Add new inflection rules using the following format
+# (all these examples are active by default):
+# Inflector.inflections do |inflect|
+# inflect.plural /^(ox)$/i, '\1en'
+# inflect.singular /^(ox)en/i, '\1'
+# inflect.irregular 'person', 'people'
+# inflect.uncountable %w( fish sheep )
+# end
+
+# Add new mime types for use in respond_to blocks:
+# Mime::Type.register "text/richtext", :rtf
+# Mime::Type.register "application/x-mobile", :mobile
+
+# Include your application configuration below
+require 'pp'
22 config/environments/development.rb
@@ -0,0 +1,22 @@
+# Settings specified here will take precedence over those in config/environment.rb
+FFMPEG = "/usr/local/bin/ffmpeg"
+
+# In the development environment your application's code is reloaded on
+# every request. This slows down response time but is perfect for development
+# since you don't have to restart the webserver when you make code changes.
+config.cache_classes = false
+
+# Log error messages when you accidentally call methods on nil.
+config.whiny_nils = true
+
+# Enable the breakpoint server that script/breakpointer connects to
+config.breakpoint_server = true
+
+# Show full error reports and disable caching
+config.action_controller.consider_all_requests_local = true
+config.action_controller.perform_caching = false
+config.action_view.cache_template_extensions = false
+config.action_view.debug_rjs = true
+
+# Don't care if the mailer can't send
+config.action_mailer.raise_delivery_errors = false
18 config/environments/production.rb
@@ -0,0 +1,18 @@
+# Settings specified here will take precedence over those in config/environment.rb
+
+# The production environment is meant for finished, "live" apps.
+# Code is not reloaded between requests
+config.cache_classes = true
+
+# Use a different logger for distributed setups
+# config.logger = SyslogLogger.new
+
+# Full error reports are disabled and caching is turned on
+config.action_controller.consider_all_requests_local = false
+config.action_controller.perform_caching = true
+
+# Enable serving of images, stylesheets, and javascripts from an asset server
+# config.action_controller.asset_host = "http://assets.example.com"
+
+# Disable delivery errors, bad email addresses will be ignored
+# config.action_mailer.raise_delivery_errors = false
20 config/environments/test.rb
@@ -0,0 +1,20 @@
+# Settings specified here will take precedence over those in config/environment.rb
+FFMPEG = "/usr/local/bin/ffmpeg"
+
+# The test environment is used exclusively to run your application's
+# test suite. You never need to work with it otherwise. Remember that
+# your test database is "scratch space" for the test suite and is wiped
+# and recreated between test runs. Don't rely on the data there!
+config.cache_classes = true
+
+# Log error messages when you accidentally call methods on nil.
+config.whiny_nils = true
+
+# Show full error reports and disable caching
+config.action_controller.consider_all_requests_local = true
+config.action_controller.perform_caching = false
+
+# Tell ActionMailer not to deliver emails to the real world.
+# The :test delivery method accumulates sent emails in the
+# ActionMailer::Base.deliveries array.
+config.action_mailer.delivery_method = :test
54 config/lighttpd.conf
@@ -0,0 +1,54 @@
+# Default configuration file for the lighttpd web server
+# Start using ./script/server lighttpd
+
+server.bind = "0.0.0.0"
+server.port = 3000
+
+server.modules = ( "mod_rewrite", "mod_accesslog", "mod_fastcgi", "mod_compress", "mod_expire" )
+
+server.error-handler-404 = "/dispatch.fcgi"
+server.pid-file = CWD + "/tmp/pids/lighttpd.pid"
+server.document-root = CWD + "/public/"
+
+server.errorlog = CWD + "/log/lighttpd.error.log"
+accesslog.filename = CWD + "/log/lighttpd.access.log"
+
+url.rewrite = ( "^/$" => "index.html", "^([^.]+)$" => "$1.html" )
+
+compress.filetype = ( "text/plain", "text/html", "text/css", "text/javascript" )
+compress.cache-dir = CWD + "/tmp/cache"
+
+expire.url = ( "/favicon.ico" => "access 3 days",
+ "/images/" => "access 3 days",
+ "/stylesheets/" => "access 3 days",
+ "/javascripts/" => "access 3 days" )
+
+
+# Change *-procs to 2 if you need to use Upload Progress or other tasks that
+# *need* to execute a second request while the first is still pending.
+fastcgi.server = ( ".fcgi" => ( "localhost" => (
+ "min-procs" => 1,
+ "max-procs" => 1,
+ "socket" => CWD + "/tmp/sockets/fcgi.socket",
+ "bin-path" => CWD + "/public/dispatch.fcgi",
+ "bin-environment" => ( "RAILS_ENV" => "development" )
+) ) )
+
+mimetype.assign = (
+ ".css" => "text/css",
+ ".gif" => "image/gif",
+ ".htm" => "text/html",
+ ".html" => "text/html",
+ ".jpeg" => "image/jpeg",
+ ".jpg" => "image/jpeg",
+ ".js" => "text/javascript",
+ ".png" => "image/png",
+ ".swf" => "application/x-shockwave-flash",
+ ".txt" => "text/plain"
+)
+
+# Making sure file uploads above 64k always work when using IE or Safari
+# For more information, see http://trac.lighttpd.net/trac/ticket/360
+$HTTP["useragent"] =~ "^(.*MSIE.*)|(.*AppleWebKit.*)$" {
+ server.max-keep-alive-requests = 0
+}
7 config/mongrel_cluster.yml
@@ -0,0 +1,7 @@
+---
+cwd: /usr/local/www/upload.shanesbrain.net/current
+port: 1024
+environment: production
+address: 127.0.0.1
+pid_file: log/mongrel.pid
+servers: 2
16 config/routes.rb
@@ -0,0 +1,16 @@
+ActionController::Routing::Routes.draw do |map|
+
+ map.activate '/activate/:activation_code', :controller => 'users', :action => 'activate'
+
+ map.resources :clips
+ map.resources :featured_clips
+ map.resource :home
+ map.resources :playlists, :has_many => [ :tracks ]
+ map.resources :users
+ map.resource :session
+
+ map.connect '', :controller => "homes", :action => 'show'
+
+ map.connect ':controller/:action/:id.:format'
+ map.connect ':controller/:action/:id'
+end
58 db/development_structure.sql
@@ -0,0 +1,58 @@
+CREATE TABLE `clips` (
+ `id` int(11) NOT NULL auto_increment,
+ `title` varchar(255) default NULL,
+ `location` varchar(255) default NULL,
+ `creator` varchar(255) default NULL,
+ `user_id` int(11) default NULL,
+ `created_at` datetime default NULL,
+ `updated_at` datetime default NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+CREATE TABLE `playlists` (
+ `id` int(11) NOT NULL auto_increment,
+ `user_id` int(11) default NULL,
+ `title` varchar(255) default NULL,
+ `info` varchar(255) default NULL,
+ `annotation` varchar(255) default NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+CREATE TABLE `schema_info` (
+ `version` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+CREATE TABLE `tracklists` (
+ `id` int(11) NOT NULL auto_increment,
+ `playlist_id` int(11) default NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+CREATE TABLE `tracks` (
+ `id` int(11) NOT NULL auto_increment,
+ `playlist_id` int(11) default NULL,
+ `title` varchar(255) default NULL,
+ `creator` varchar(255) default NULL,
+ `location` varchar(255) default NULL,
+ `info` varchar(255) default NULL,
+ `image` varchar(255) default NULL,
+ `identifier` varchar(255) default NULL,
+ `album` varchar(255) default NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+CREATE TABLE `users` (
+ `id` int(11) NOT NULL auto_increment,
+ `login` varchar(255) default NULL,
+ `email` varchar(255) default NULL,
+ `crypted_password` varchar(40) default NULL,
+ `salt` varchar(40) default NULL,
+ `created_at` datetime default NULL,
+ `updated_at` datetime default NULL,
+ `remember_token` varchar(255) default NULL,
+ `remember_token_expires_at` datetime default NULL,
+ `playlist_id` int(11) default NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+INSERT INTO schema_info (version) VALUES (6)
14 db/migrate/002_create_clips.rb
@@ -0,0 +1,14 @@
+class CreateClips < ActiveRecord::Migration
+ def self.up
+ create_table :clips do |t|
+ t.string :title
+ t.string :location
+ t.integer :user_id
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :clips
+ end
+end
14 db/migrate/003_create_playlists.rb
@@ -0,0 +1,14 @@
+class CreatePlaylists < ActiveRecord::Migration
+ def self.up
+ create_table :playlists do |t|
+ t.integer :user_id
+ t.string :title
+ t.string :info
+ t.string :annotation
+ end
+ end
+
+ def self.down
+ drop_table :playlists
+ end
+end
18 db/migrate/004_create_tracks.rb
@@ -0,0 +1,18 @@
+class CreateTracks < ActiveRecord::Migration
+ def self.up
+ create_table :tracks do |t|
+ t.integer :playlist_id
+ t.string :title
+ t.string :creator
+ t.string :location
+ t.string :info
+ t.string :image
+ t.string :identifier
+ t.string :album
+ end
+ end
+
+ def self.down
+ drop_table :tracks
+ end
+end
21 db/migrate/006_create_users.rb
@@ -0,0 +1,21 @@
+class CreateUsers < ActiveRecord::Migration
+ def self.up
+ create_table "users", :force => true do |t|
+ t.column :login, :string
+ t.column :email, :string
+ t.column :crypted_password, :string, :limit => 40
+ t.column :salt, :string, :limit => 40
+ t.column :created_at, :datetime
+ t.column :updated_at, :datetime
+ t.column :remember_token, :string
+ t.column :remember_token_expires_at, :datetime
+
+ t.column :activation_code, :string, :limit => 40
+ t.column :activated_at, :datetime
+ end
+ end
+
+ def self.down
+ drop_table "users"
+ end
+end
9 db/migrate/007_add_playlist_to_users.rb
@@ -0,0 +1,9 @@
+class AddPlaylistToUsers < ActiveRecord::Migration
+ def self.up
+ add_column :users, :playlist_id, :integer
+ end
+
+ def self.down
+ remove_column :users, :playlist_id
+ end
+end
9 db/migrate/008_add_featured_flag_to_clip.rb
@@ -0,0 +1,9 @@
+class AddFeaturedFlagToClip < ActiveRecord::Migration
+ def self.up
+ add_column :clips, :featured, :boolean, :default => 0
+ end
+
+ def self.down
+ remove_column :clips, :featured
+ end
+end
48 db/schema.rb
@@ -0,0 +1,48 @@
+# This file is autogenerated. Instead of editing this file, please use the
+# migrations feature of ActiveRecord to incrementally modify your database, and
+# then regenerate this schema definition.
+
+ActiveRecord::Schema.define(:version => 8) do
+
+ create_table "clips", :force => true do |t|
+ t.string "title"
+ t.string "location"
+ t.integer "user_id"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.boolean "featured", :default => false
+ end
+
+ create_table "playlists", :force => true do |t|
+ t.integer "user_id"
+ t.string "title"
+ t.string "info"
+ t.string "annotation"
+ end
+
+ create_table "tracks", :force => true do |t|
+ t.integer "playlist_id"
+ t.string "title"
+ t.string "creator"
+ t.string "location"
+ t.string "info"
+ t.string "image"
+ t.string "identifier"
+ t.string "album"
+ end
+
+ create_table "users", :force => true do |t|
+ t.string "login"
+ t.string "email"
+ t.string "crypted_password", :limit => 40
+ t.string "salt", :limit => 40
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.string "remember_token"
+ t.datetime "remember_token_expires_at"
+ t.string "activation_code", :limit => 40
+ t.datetime "activated_at"
+ t.integer "playlist_id"
+ end
+
+end
2 doc/README_FOR_APP
@@ -0,0 +1,2 @@
+Use this README file to introduce your application and point to useful places in the API for learning more.
+Run "rake appdoc" to generate API documentation for your models and controllers.
120 lib/authenticated_system.rb
@@ -0,0 +1,120 @@
+module AuthenticatedSystem
+ protected
+ # Returns true or false if the user is logged in.
+ # Preloads @current_user with the user model if they're logged in.
+ def logged_in?
+ current_user != :false
+ end
+
+ # Accesses the current user from the session.
+ def current_user
+ @current_user ||= (session[:user] && User.find_by_id(session[:user])) || :false
+ end
+
+ # Store the given user in the session.
+ def current_user=(new_user)
+ session[:user] = (new_user.nil? || new_user.is_a?(Symbol)) ? nil : new_user.id
+ @current_user = new_user
+ end
+
+ # Check if the user is authorized.
+ #
+ # Override this method in your controllers if you want to restrict access
+ # to only a few actions or if you want to check if the user
+ # has the correct rights.
+ #
+ # Example:
+ #
+ # # only allow nonbobs
+ # def authorize?
+ # current_user.login != "bob"
+ # end
+ def authorized?
+ true
+ end
+
+ # Filter method to enforce a login requirement.
+ #
+ # To require logins for all actions, use this in your controllers:
+ #
+ # before_filter :login_required
+ #
+ # To require logins for specific actions, use this in your controllers:
+ #
+ # before_filter :login_required, :only => [ :edit, :update ]
+ #
+ # To skip this in a subclassed controller:
+ #
+ # skip_before_filter :login_required
+ #
+ def login_required
+ username, passwd = get_auth_data
+ self.current_user ||= User.authenticate(username, passwd) || :false if username && passwd
+ logged_in? && authorized? ? true : access_denied
+ end
+
+ # Redirect as appropriate when an access request fails.
+ #
+ # The default action is to redirect to the login screen.
+ #
+ # Override this method in your controllers if you want to have special
+ # behavior in case the user is not authorized
+ # to access the requested action. For example, a popup window might
+ # simply close itself.
+ def access_denied
+ respond_to do |accepts|
+ accepts.html do
+ store_location
+ redirect_to :controller => 'sessions', :action => 'new'
+ end
+ accepts.xml do
+ headers["Status"] = "Unauthorized"
+ headers["WWW-Authenticate"] = %(Basic realm="Web Password")
+ render :text => "Could't authenticate you", :status => '401 Unauthorized'
+ end
+ end
+ false
+ end
+
+ # Store the URI of the current request in the session.
+ #
+ # We can return to this location by calling #redirect_back_or_default.
+ def store_location
+ session[:return_to] = request.request_uri
+ end
+
+ # Redirect to the URI stored by the most recent store_location call or
+ # to the passed default.
+ def redirect_back_or_default(default)
+ session[:return_to] ? redirect_to(session[:return_to]) : redirect_to(default)
+ session[:return_to] = nil
+ end
+
+ # Inclusion hook to make #current_user and #logged_in?
+ # available as ActionView helper methods.
+ def self.included(base)
+ base.send :helper_method, :current_user, :logged_in?
+ end
+
+ # When called with before_filter :login_from_cookie will check for an :auth_token
+ # cookie and log the user back in if apropriate
+ def login_from_cookie
+ return unless cookies[:auth_token] && !logged_in?
+ user = User.find_by_remember_token(cookies[:auth_token])
+ if user && user.remember_token?
+ user.remember_me
+ self.current_user = user
+ cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at }
+ flash[:notice] = "Logged in successfully"
+ end
+ end
+
+ private
+ @@http_auth_headers = %w(X-HTTP_AUTHORIZATION HTTP_AUTHORIZATION Authorization)
+ # gets BASIC auth info
+ def get_auth_data
+ auth_key = @@http_auth_headers.detect { |h| request.env.has_key?(h) }
+ auth_data = request.env[auth_key].to_s.split unless auth_key.blank?
+ return auth_data && auth_data[0] == 'Basic' ? Base64.decode64(auth_data[1]).split(':')[0..1] : [nil, nil]
+ end
+end
113 lib/authenticated_test_helper.rb
@@ -0,0 +1,113 @@
+module AuthenticatedTestHelper
+ # Sets the current user in the session from the user fixtures.
+ def login_as(user)
+ @request.session[:user] = user ? users(user).id : nil
+ end
+
+ def content_type(type)
+ @request.env['Content-Type'] = type
+ end
+
+ def accept(accept)
+ @request.env["HTTP_ACCEPT"] = accept
+ end
+
+ def authorize_as(user)
+ if user
+ @request.env["HTTP_AUTHORIZATION"] = "Basic #{Base64.encode64("#{users(user).login}:test")}"
+ accept 'application/xml'
+ content_type 'application/xml'
+ else
+ @request.env["HTTP_AUTHORIZATION"] = nil
+ accept nil
+ content_type nil
+ end
+ end
+
+ # http://project.ioni.st/post/217#post-217
+ #
+ # def test_new_publication
+ # assert_difference(Publication, :count) do
+ # post :create, :publication => {...}
+ # # ...
+ # end
+ # end
+ #
+ # def assert_difference(object, method = nil, difference = 1)
+ # initial_value = object.send(method)
+ # yield
+ # assert_equal initial_value + difference, object.send(method), "#{object}##{method}"
+ # end
+ #
+ # def assert_no_difference(object, method, &block)
+ # assert_difference object, method, 0, &block
+ # end
+
+ # Assert the block redirects to the login
+ #
+ # assert_requires_login(:bob) { |c| c.get :edit, :id => 1 }
+ #
+ def assert_requires_login(login = nil)
+ yield HttpLoginProxy.new(self, login)
+ end
+
+ def assert_http_authentication_required(login = nil)
+ yield XmlLoginProxy.new(self, login)
+ end
+
+ def reset!(*instance_vars)
+ instance_vars = [:controller, :request, :response] unless instance_vars.any?
+ instance_vars.collect! { |v| "@#{v}".to_sym }
+ instance_vars.each do |var|
+ instance_variable_set(var, instance_variable_get(var).class.new)
+ end
+ end
+end
+
+class BaseLoginProxy
+ attr_reader :controller
+ attr_reader :options
+ def initialize(controller, login)
+ @controller = controller
+ @login = login
+ end
+
+ private
+ def authenticated
+ raise NotImplementedError
+ end
+
+ def check
+ raise NotImplementedError
+ end
+
+ def method_missing(method, *args)
+ @controller.reset!
+ authenticate
+ @controller.send(method, *args)
+ check
+ end
+end
+
+class HttpLoginProxy < BaseLoginProxy
+ protected
+ def authenticate
+ @controller.login_as @login if @login
+ end
+
+ def check
+ @controller.assert_redirected_to :controller => 'sessions', :action => 'new'
+ end
+end
+
+class XmlLoginProxy < BaseLoginProxy
+ protected
+ def authenticate
+ @controller.accept 'application/xml'
+ @controller.authorize_as @login if @login
+ end
+
+ def check
+ @controller.assert_response 401
+ end
+end
102 lib/tasks/capistrano.rake
@@ -0,0 +1,102 @@
+# =============================================================================
+# A set of rake tasks for invoking the Capistrano automation utility.
+# =============================================================================
+
+# Invoke the given actions via Capistrano
+def cap(*parameters)
+ begin
+ require 'rubygems'
+ rescue LoadError
+ # no rubygems to load, so we fail silently
+ end
+
+ require 'capistrano/cli'
+
+ STDERR.puts "Capistrano/Rake integration is deprecated."