uploader 0.1.16 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. data/.gitignore +5 -0
  2. data/VERSION +1 -1
  3. data/app/controllers/uploader/uploads_controller.rb +1 -1
  4. data/uploader.gemspec +4 -31
  5. metadata +3 -30
  6. data/rdoc/classes/ActionController/Routing/RouteSet.html +0 -148
  7. data/rdoc/classes/ActionController/Routing.html +0 -107
  8. data/rdoc/classes/ActionController.html +0 -107
  9. data/rdoc/classes/ActiveRecord/Acts/UploaderUpload/ClassMethods.html +0 -183
  10. data/rdoc/classes/ActiveRecord/Acts/UploaderUpload/InstanceMethods.html +0 -750
  11. data/rdoc/classes/ActiveRecord/Acts/UploaderUpload/SingletonMethods.html +0 -111
  12. data/rdoc/classes/ActiveRecord.html +0 -105
  13. data/rdoc/classes/Uploader/Exceptions/MissingTemplateError.html +0 -111
  14. data/rdoc/classes/Uploader/Exceptions.html +0 -111
  15. data/rdoc/classes/Uploader/FlashSessionCookieMiddleware.html +0 -177
  16. data/rdoc/classes/Uploader/MimeTypeGroups.html +0 -143
  17. data/rdoc/classes/Uploader/Tasks.html +0 -146
  18. data/rdoc/classes/Uploader.html +0 -126
  19. data/rdoc/created.rid +0 -1
  20. data/rdoc/files/README_rdoc.html +0 -515
  21. data/rdoc/files/lib/active_record/acts/uploader_upload_rb.html +0 -101
  22. data/rdoc/files/lib/daemons/amazonaws_rb.html +0 -107
  23. data/rdoc/files/lib/uploader/exceptions_rb.html +0 -101
  24. data/rdoc/files/lib/uploader/initialize_routes_rb.html +0 -101
  25. data/rdoc/files/lib/uploader/middleware/flash_session_cookie_middleware_rb.html +0 -108
  26. data/rdoc/files/lib/uploader/mime_type_groups_rb.html +0 -101
  27. data/rdoc/files/lib/uploader/tasks_rb.html +0 -110
  28. data/rdoc/files/lib/uploader_rb.html +0 -111
  29. data/rdoc/fr_class_index.html +0 -39
  30. data/rdoc/fr_file_index.html +0 -35
  31. data/rdoc/fr_method_index.html +0 -54
  32. data/rdoc/index.html +0 -24
  33. data/rdoc/rdoc-style.css +0 -208
@@ -1,515 +0,0 @@
1
- <?xml version="1.0" encoding="iso-8859-1"?>
2
- <!DOCTYPE html
3
- PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5
-
6
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
7
- <head>
8
- <title>File: README.rdoc</title>
9
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
10
- <meta http-equiv="Content-Script-Type" content="text/javascript" />
11
- <link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
12
- <script type="text/javascript">
13
- // <![CDATA[
14
-
15
- function popupCode( url ) {
16
- window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
17
- }
18
-
19
- function toggleCode( id ) {
20
- if ( document.getElementById )
21
- elem = document.getElementById( id );
22
- else if ( document.all )
23
- elem = eval( "document.all." + id );
24
- else
25
- return false;
26
-
27
- elemStyle = elem.style;
28
-
29
- if ( elemStyle.display != "block" ) {
30
- elemStyle.display = "block"
31
- } else {
32
- elemStyle.display = "none"
33
- }
34
-
35
- return true;
36
- }
37
-
38
- // Make codeblocks hidden by default
39
- document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
40
-
41
- // ]]>
42
- </script>
43
-
44
- </head>
45
- <body>
46
-
47
-
48
-
49
- <div id="fileHeader">
50
- <h1>README.rdoc</h1>
51
- <table class="header-table">
52
- <tr class="top-aligned-row">
53
- <td><strong>Path:</strong></td>
54
- <td>README.rdoc
55
- </td>
56
- </tr>
57
- <tr class="top-aligned-row">
58
- <td><strong>Last Update:</strong></td>
59
- <td>Thu Jun 04 15:26:03 -0600 2009</td>
60
- </tr>
61
- </table>
62
- </div>
63
- <!-- banner header -->
64
-
65
- <div id="bodyContent">
66
-
67
-
68
-
69
- <div id="contextContent">
70
-
71
- <div id="description">
72
- <h1><a href="../classes/Uploader.html">Uploader</a></h1>
73
- <p>
74
- <a href="../classes/Uploader.html">Uploader</a> makes it easy to integrate
75
- multiple file uploads into your application using SWFUpload
76
- </p>
77
- <h2>Installation</h2>
78
- <h3>Install the gem:</h3>
79
- <p>
80
- sudo gem install uploader
81
- </p>
82
- <p>
83
- Installing uploader should also install mime-types and rack. If for some
84
- reason it does not then manually install it: sudo gem install mime-types
85
- sudo gem install rack
86
- </p>
87
- <h3>Add the gem to environment.rb</h3>
88
- <p>
89
- config.gem &#8216;uploader&#8216;
90
- </p>
91
- <h3>Install jQuery</h3>
92
- <p>
93
- uploader uses jQuery. You&#8216;ll need to include it in your application.
94
- Download it here: <a href="http://jquery.com">jquery.com</a>/
95
- </p>
96
- <p>
97
- Then include it in your layout:
98
- </p>
99
- <pre>
100
- &lt;%= javascript_include_tag 'jquery/jquery.js' %&gt;
101
- </pre>
102
- <p>
103
- Another option is to use jRails <a
104
- href="http://ennerchi.com/projects/jrails">ennerchi.com/projects/jrails</a>
105
- </p>
106
- <h3>Create a model for uploads.</h3>
107
- <p>
108
- We recommend creating a model called upload.rb. acts_as_uploader accepts
109
- all valid options for paperclip via :has_attached_file =&gt; {}
110
- </p>
111
- <pre>
112
- class Upload &lt; ActiveRecord::Base
113
-
114
- acts_as_uploader :enable_s3 =&gt; false,
115
- :has_attached_file =&gt; {
116
- :url =&gt; &quot;/system/:attachment/:id_partition/:style/:basename.:extension&quot;,
117
- :path =&gt; &quot;:rails_root/public/system/:attachment/:id_partition/:style/:basename.:extension&quot;,
118
- :styles =&gt; { :icon =&gt; &quot;30x30!&quot;,
119
- :thumb =&gt; &quot;100&gt;&quot;,
120
- :small =&gt; &quot;150&gt;&quot;,
121
- :medium =&gt; &quot;300&gt;&quot;,
122
- :large =&gt; &quot;660&gt;&quot; },
123
- :default_url =&gt; &quot;/images/profile_default.jpg&quot;,
124
- :storage =&gt; :s3,
125
- :s3_credentials =&gt; AMAZON_S3_CREDENTIALS,
126
- :bucket =&gt; &quot;assets.example.com&quot;,
127
- :s3_host_alias =&gt; &quot;assets.example.com&quot;,
128
- :convert_options =&gt; {
129
- :all =&gt; '-quality 80'
130
- }
131
- },
132
- :s3_path =&gt; ':id_partition/:style/:basename.:extension'
133
-
134
- # only allow images:
135
- # validates_attachment_content_type :file, :content_type =&gt; ['image/jpeg', 'image/pjpeg', 'image/jpg']
136
-
137
- # limit uploads to 10 MB
138
- # validates_attachment_size :local, :less_than =&gt; 10.megabytes
139
-
140
- # The following method is implemented in 'acts_as_uploader'. This is the method destroy will check to see if
141
- # the user has permission to delete the object. Add additional logic as needed or if the existing logic
142
- # looks fine then feel free to delete this comment and the can_edit? method.
143
- def can_edit?(check_user)
144
- return false if user.blank?
145
- check_user == self.user
146
- end
147
-
148
- end
149
- </pre>
150
- <h3>Add multiple file uploads to one of your models</h3>
151
- <p>
152
- Your uploads will need a parent object to attach to. For example, a user
153
- might have many files:
154
- </p>
155
- <pre>
156
- class User &lt; ActiveRecord::Base
157
- has_many :uploads, :as =&gt; :uploadable, :order =&gt; 'created_at desc', :dependent =&gt; :destroy
158
-
159
- def can_upload?(check_user)
160
- self == check_user
161
- end
162
- end
163
- </pre>
164
- <p>
165
- or a photo album might have many photos
166
- </p>
167
- <pre>
168
- class PhotoAlbum &lt; ActiveRecord::Base
169
- has_many :photos, :as =&gt; :uploadable, :order =&gt; 'created_at desc', :dependent =&gt; :destroy
170
-
171
- def can_upload?(check_user)
172
- self.editors.include?(check_user)
173
- end
174
- end
175
- </pre>
176
- <p>
177
- Note that in both examples there is an implementation of
178
- &#8216;can_upload?&#8217;. This method must be included in any parent
179
- object and will control who has permission to upload files.
180
- </p>
181
- <h3>The application controller</h3>
182
- <p>
183
- Be sure you have turned on protect from forgery. This is required for
184
- uploader to get the appropriate tokens from your Rails application. It is
185
- also a good idea and is the default in new Rails applications.
186
- </p>
187
- <pre>
188
- protect_from_forgery # See ActionController::RequestForgeryProtection for details
189
- </pre>
190
- <h3>The uploads controller</h3>
191
- <p>
192
- You can modify the upload controller behavior by inheriting from the
193
- uploader controller. For example, you might want to require that users be
194
- logged in to upload a file. There are a number of methods in the uploads
195
- controller that contain default functionality that you may consider
196
- overriding.
197
- </p>
198
- <p>
199
- Be sure to modify your routes file. Add the following line to ensure that
200
- your application uses the new uploads controller instead of directly using
201
- the one inside the gem:
202
- </p>
203
- <pre>
204
- map.resources :uploads, :collection =&gt; { :swfupload =&gt; :post }
205
-
206
- class UploadsController &lt; Uploader::UploadsController
207
-
208
- prepend_before_filter :login_required
209
-
210
- protected
211
-
212
- # The default 'get_upload_text' method throws an exception. You must override this method in your controller. It
213
- # is used by the swf upload call to generate the html to be returned to the client.
214
- # Here's an example:
215
- def get_upload_text(upload)
216
- render_to_string( :partial =&gt; 'uploads/upload_row', :object =&gt; upload, :locals =&gt; { :parent =&gt; @parent } )
217
- end
218
-
219
- # The existing method will handle most cases but you might choose a different message or a different redirect:
220
- def permission_denied
221
- message = t(&quot;uploader.permission_denied&quot;)
222
- respond_to do |format|
223
- format.html do
224
- flash[:notice] = message
225
- redirect_to get_redirect
226
- end
227
- format.js { render :text =&gt; message }
228
- format.json { render :json =&gt; { :success =&gt; false, :message =&gt; message } }
229
- end
230
- end
231
-
232
- # Simply attempts to redirect to the parent object. You might want to build something more sophisticated that
233
- # redirect to different areas of you site depending on the type of object that was uploaded or on based on the parent.
234
- # source can be :destroy_success, :create_success, :create_failure, :permission_denied
235
- def get_redirect
236
- @parent
237
- end
238
-
239
- # The default action is to call 'can_upload?' on the parent object. Be sure to implement 'can_upload?(check_user) on
240
- # your parent objects
241
- def has_permission_to_upload(user, upload_parent)
242
- upload_parent.can_upload?(user)
243
- end
244
-
245
- # By default the controller will use a model named 'Upload' to do a destroy. If you want to use a different model
246
- # you'll need to override 'set_upload_for_destroy in your controller to find the object using a different object.
247
- # For example:
248
- def set_upload_for_destroy
249
- @upload = Photo.find(params[:id])
250
- end
251
-
252
- end
253
- </pre>
254
- <h3>Configure your views.</h3>
255
- <p>
256
- You&#8216;ll need something like this in your layout so that uploader can
257
- add in the required css and javascript files.
258
- </p>
259
- <p>
260
- &lt;%= yield :head -%&gt;
261
- </p>
262
- <p>
263
- Then to add an upload form: &lt;%= upload_form(parent_object) %&gt;
264
- parent_object should be the object which owns the uploads. ie a user,
265
- photo_album, etc.
266
- </p>
267
- <h3>Rake Tasks</h3>
268
- <p>
269
- Add the rake tasks for uploader to your project. You will need to add the
270
- following to your applications&#8216;s Rakefile
271
- </p>
272
- <pre>
273
- require 'uploader'
274
- require 'uploader/tasks'
275
- </pre>
276
- <p>
277
- Then run:
278
- </p>
279
- <pre>
280
- rake uploader:sync
281
- </pre>
282
- <p>
283
- Last run:
284
- </p>
285
- <pre>
286
- rake db:migrate
287
- </pre>
288
- <p>
289
- This will create an uploads table for you. If you selected a different name
290
- for your model you will need to modify the migration accordingly.
291
- </p>
292
- <h2>WARNING</h2>
293
- <p>
294
- The migration will drop any existing &#8216;uploads&#8217; table you have
295
- in place
296
- </p>
297
- <p>
298
- That will copy all the required javascript and asset files into your
299
- project
300
- </p>
301
- <h2>Amazon s3</h2>
302
- <p>
303
- If you&#8216;d like to store your uploads on Amazon&#8216;s S3 service
304
- there are a few extra steps involved. See the example file above to view
305
- the options in context.
306
- </p>
307
- <h3>Turn on s3</h3>
308
- <p>
309
- Set the enable_s3 option to true in acts_as_uploader
310
- </p>
311
- <pre>
312
- :enable_s3 =&gt; true
313
- </pre>
314
- <p>
315
- Pass your s3 credentials into acts_as_uploader
316
- </p>
317
- <pre>
318
- :has_attached_file =&gt; { :s3_credentials =&gt; File.join(RAILS_ROOT, 'config', 's3.yml') }
319
- </pre>
320
- <h3>Setup your credentials</h3>
321
- <p>
322
- Create a file named s3.yml in your configuration directory and add the
323
- following lines:
324
- </p>
325
- <pre>
326
- access_key_id: PUT YOUR KEY HERE
327
- secret_access_key: PUT YOUR SECRET ACCESS KEY HERE
328
- </pre>
329
- <h3>Turn on the Daemon process</h3>
330
- <p>
331
- There are a number of timing issues that you will run into if you attempt
332
- to upload files directly to s3. To overcome that problem uploader includes
333
- a daemon process which will send the files to Amazon asynchronously. Note
334
- that the uploader will leave your local copy in place.
335
- </p>
336
- <p>
337
- Add the daemons gem and plugin:
338
- </p>
339
- <pre>
340
- sudo gem install daemons
341
- </pre>
342
- <p>
343
- Then inside your Rails project:
344
- </p>
345
- <pre>
346
- script/plugin install git://github.com/dougal/daemon_generator.git
347
- script/generate daemon amazonaws
348
-
349
- RAILS_ENV=development lib/daemons/mailer_ctl start
350
- </pre>
351
- <p>
352
- Learn more about the custom daemon gem with Ryan Bates screencast:
353
- </p>
354
- <pre>
355
- http://railscasts.com/episodes/129-custom-daemon
356
- </pre>
357
- <h2>Use Rake to send files to s3</h2>
358
- <p>
359
- uploader includes a task capable of sending files to s3 but it makes an
360
- assumption that the model you are interacting with is named
361
- &#8216;Upload&#8217;.
362
- </p>
363
- <pre>
364
- rake uploader:upload_to_s3
365
- </pre>
366
- <p>
367
- If you want to use a different model or several models just add a rake task
368
- to your project:
369
- </p>
370
- <pre>
371
- desc 'Send all uploads to S3. (Will only send uploads from a model named Upload)'
372
- task :upload_to_s3 do
373
-
374
- uploads = Upload.pending_s3_migration
375
- uploads.each do |upload|
376
- upload.remote = upload.local
377
- upload.save!
378
- end
379
-
380
- photos = Photo.pending_s3_migration
381
- photos.each do |photo|
382
- photo.remote = photo.local
383
- photo.save!
384
- end
385
-
386
- end
387
- </pre>
388
- <h2>Setup Domains</h2>
389
- <p>
390
- If you use Amazon&#8216;s S3 service you can setup a cname to clean up your
391
- urls. Configure your s3 bucket as above:
392
- </p>
393
- <pre>
394
- :bucket =&gt; &quot;assets.example.com&quot;
395
- :s3_host_alias =&gt; &quot;assets.example.com&quot;
396
- </pre>
397
- <p>
398
- Your assets will be available at assets.example.com.s3.amazon.com. You can
399
- then create a CNAME in your DNS entries to point
400
- &quot;assets.example.com&quot; to
401
- &quot;assets.example.com.s3.amazon.com&quot;. Your assets will then appear
402
- to be be served from assets.example.com even though they are loaded from
403
- Amazon.
404
- </p>
405
- <h2>Other Stuff</h2>
406
- <p>
407
- If you&#8216;d like to add an ajax delete to your uploads page this code
408
- might come in handy.
409
- </p>
410
- <p>
411
- Say you have chosen to display your upload in a table. Your code might look
412
- like the following. Note that there are a number of assumptions made in
413
- this code. Modify it to suite your needs.
414
- </p>
415
- <pre>
416
- &lt;tr id=&quot;&lt;%= upload_row.dom_id %&gt;&quot; class=&quot;delete-container &lt;%= cycle('odd', 'even') %&gt;&quot; &lt;%=style-%&gt; &gt;
417
- &lt;td&gt;&lt;div class=&quot;file-icon&quot;&gt;&lt;%= image_tag upload_row.icon -%&gt;&lt;/div&gt;&lt;/td&gt;
418
- &lt;td&gt;&lt;a href=&quot;&lt;%=upload_row.file.url%&gt;&quot;&gt;&lt;%= truncate(sanitize(upload_row.file_name), 100) %&gt;&lt;/a&gt;&lt;/td&gt;
419
- &lt;td&gt;&lt;%= upload_row.created_at.to_s(:long) -%&gt;&lt;/td&gt;
420
- &lt;td&gt;
421
- &lt;% if parent.can_edit?(current_user) -%&gt;
422
- &lt;% form_for(:upload, :url =&gt; upload_path(upload_row.id), :html =&gt; { :class =&gt; &quot;delete-form&quot;, :method =&gt; :delete} ) do |f| -%&gt;
423
- &lt;%= image_submit_tag '/images/icons/delete.png', {:id =&gt; 'submit-comment', :title =&gt; t('general.delete_file'), :class =&gt; 'submit-delete', :width =&gt; '12', :height =&gt; '12', :alt =&gt; t('general.delete_file') } %&gt;
424
- &lt;% end -%&gt;
425
- &lt;% if !style.empty? -%&gt;
426
- &lt;script type=&quot;text/javascript&quot; language=&quot;JavaScript&quot;&gt;
427
- jQuery(&quot;#&lt;%= upload_row.dom_id %&gt;&quot;).fadeIn(&quot;slow&quot;);
428
- &lt;/script&gt;
429
- &lt;% end -%&gt;
430
- &lt;% end -%&gt;
431
- &lt;/td&gt;
432
- &lt;/tr&gt;
433
- </pre>
434
- <p>
435
- I put the following in my main upload view
436
- </p>
437
- <pre>
438
- &lt;% content_for :javascript do -%&gt;
439
-
440
- setup_submit_delete();
441
-
442
- function upload_completed_callback(data){
443
- jQuery('#upload-list').prepend(data);
444
- setup_submit_delete();
445
- }
446
- &lt;% end -%&gt;
447
- </pre>
448
- <p>
449
- The following jQuery code will do an ajax delete for you
450
- </p>
451
- <pre>
452
- function setup_submit_delete(){
453
- jQuery(&quot;.submit-delete&quot;).click(function() {
454
- // if(!confirm(&quot;Are you sure?&quot;)){
455
- // return false;
456
- // }
457
- jQuery(this).parents('.delete-container').fadeOut();
458
- var form = jQuery(this).parents('form');
459
- jQuery.post(form.attr('action') + '.json', form.serialize(),
460
- function(data){
461
- var json = eval('(' + data + ')');
462
- if(!json.success){
463
- jQuery.jGrowl.info(json.message);
464
- }
465
- });
466
- return false;
467
- });
468
- }
469
- </pre>
470
- <h3>Testing</h3>
471
- <p>
472
- If you intend to develop code and wish to run the tests you may do so using
473
- rake test. However, note that you will need to install the gem first using
474
- rake install since the embedded test application will use the gem that is
475
- install and not the current code from the project. This is a limitation I
476
- attempted to overcome using a special initializer in
477
- rails_root/config/initializers/uploader.rb but I didn&#8216;t have any
478
- success getting it working.
479
- </p>
480
- <p>
481
- Copyright (c) 2009 Justin Ball, released under the MIT license
482
- </p>
483
-
484
- </div>
485
-
486
-
487
- </div>
488
-
489
-
490
- </div>
491
-
492
-
493
- <!-- if includes -->
494
-
495
- <div id="section">
496
-
497
-
498
-
499
-
500
-
501
-
502
-
503
-
504
- <!-- if method_list -->
505
-
506
-
507
- </div>
508
-
509
-
510
- <div id="validator-badges">
511
- <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
512
- </div>
513
-
514
- </body>
515
- </html>
@@ -1,101 +0,0 @@
1
- <?xml version="1.0" encoding="iso-8859-1"?>
2
- <!DOCTYPE html
3
- PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5
-
6
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
7
- <head>
8
- <title>File: uploader_upload.rb</title>
9
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
10
- <meta http-equiv="Content-Script-Type" content="text/javascript" />
11
- <link rel="stylesheet" href="../../../.././rdoc-style.css" type="text/css" media="screen" />
12
- <script type="text/javascript">
13
- // <![CDATA[
14
-
15
- function popupCode( url ) {
16
- window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
17
- }
18
-
19
- function toggleCode( id ) {
20
- if ( document.getElementById )
21
- elem = document.getElementById( id );
22
- else if ( document.all )
23
- elem = eval( "document.all." + id );
24
- else
25
- return false;
26
-
27
- elemStyle = elem.style;
28
-
29
- if ( elemStyle.display != "block" ) {
30
- elemStyle.display = "block"
31
- } else {
32
- elemStyle.display = "none"
33
- }
34
-
35
- return true;
36
- }
37
-
38
- // Make codeblocks hidden by default
39
- document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
40
-
41
- // ]]>
42
- </script>
43
-
44
- </head>
45
- <body>
46
-
47
-
48
-
49
- <div id="fileHeader">
50
- <h1>uploader_upload.rb</h1>
51
- <table class="header-table">
52
- <tr class="top-aligned-row">
53
- <td><strong>Path:</strong></td>
54
- <td>lib/active_record/acts/uploader_upload.rb
55
- </td>
56
- </tr>
57
- <tr class="top-aligned-row">
58
- <td><strong>Last Update:</strong></td>
59
- <td>Thu Jun 04 15:35:52 -0600 2009</td>
60
- </tr>
61
- </table>
62
- </div>
63
- <!-- banner header -->
64
-
65
- <div id="bodyContent">
66
-
67
-
68
-
69
- <div id="contextContent">
70
-
71
-
72
-
73
- </div>
74
-
75
-
76
- </div>
77
-
78
-
79
- <!-- if includes -->
80
-
81
- <div id="section">
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
- <!-- if method_list -->
91
-
92
-
93
- </div>
94
-
95
-
96
- <div id="validator-badges">
97
- <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
98
- </div>
99
-
100
- </body>
101
- </html>