Silverstripe 3.1.5 - Upload Error SyntaxError: Unexpected token < - silverstripe

I need to Upload .svg files. To do that I added 'svg' to my config.yml, to the allowed extensions on upload field an to the .htacces in assets/. Also all my assets directories have CHMOD 777.
The File gets uploaded but not attached. Instead of that I receive this error in my upload field SyntaxError: Unexpected token <
File:
allowed_extensions:
- svg
Image:
allowed_extensions:
- svg
$logo->setAllowedExtensions(array('jpg', 'jpeg', 'png', 'gif', 'svg'));
Deny from all
<FilesMatch "\.(?i:html|htm|xhtml|js|css|bmp|png|gif|jpg|jpeg|ico|pcx|tif|tiff|au|mid|midi|mpa|mp3|ogg|m4a|ra|wma|wav|cda|avi|mpg|mpeg|asf|wmv|m4v|mov|mkv|mp4|ogv|webm|swf|flv|ram|rm|doc|docx|txt|rtf|xls|xlsx|pages|ppt|pptx|pps|csv|cab|arj|tar|zip|zipx|sit|sitx|gz|tgz|bz2|ace|arc|pkg|dmg|hqx|jar|xml|pdf|gpx|kml|svg)$">
Allow from all
</FilesMatch>

Silverstripe (3.1) will not allow you to save a svg file as an Image data type.
It may be to do with the PHP GD library (I'm not sure), which the Silverstripe Image class uses.
Instead, you can save a svg file as a File data type.
To do this all you need is to add the svg file type to the File allowed_extensions in your yml config file (as you posted in your questions):
File:
allowed_extensions:
- svg
In your Page or DataObject class add the File relation and set your UploadField:
private static $has_one = array(
'SVGFile' => 'File'
);
public function getCMSFields()
{
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.SVG', UploadField::create('SVGFile', 'SVG File'));
return $fields;
}
In your page template you can use the file URL to load the svg as you like.

Here's a module to have SVG work as images in SilverStripe: https://github.com/micschk/silverstripe-svg-images/
See the README for general pointers on how to set up SVG-as-image if you don't want to require the module.

The problem "SyntaxError: Unexpected token <" is caused by an error being returned via HTML instead of a data stream in my experience. So I'd look at the contents of the network tab response and expect to see a stack trace with an error.

Related

Pyexcel, loading a file to create a book in memory

This is solved; thanks to #vmontco's solution: I was missing MEDIA_URL, now it works perfectly.
----------original question below-----------
I welcome suggestions from every angle; I am fairly new to Django and Python. I'm sure I am missing something simple.
Using a Model Form, with a FileField, I upload and save an Excel file to a folder structure under MEDIA_ROOT. This works.
I want to read that same file later to perform operations using Pyexcel. This is where I am stuck. I am attempting to upload the file using the FileField stored in the DB.
This is where I have problems, and I am not sure if am misunderstanding MEDIA_ROOT, or some other aspect of Django.
When I pass the pk to the 2nd view, I then instantiate an object based on the Model. It has the FileField 'docfile', which I am trying to use to access the file to do some operations using Pyexcel,
here is the FileField declaration from models.py:
docfile = models.FileField(
verbose_name="Choose file to upload:",
upload_to='Excel_CSV_Assets/%Y/%m/%d')
EDIT: If I hard-code the pth to the file like this, everything works, including operations afterwards:
thedocfile='site_static/site/original_assets/Excel_CSV_Assets/2016/04/23/Animals_oglc4DV.xlsx'
book=pyexcel.get_book(file_name=thedocfile)
:END OF EDIT
Here is the code from the 2nd view, where I attempt to read the file into memory, and make a 'book' class object using Pyexcel. I am stuck here:
asset = Excel_CSV_Asset.objects.get(id=assetid)
book=pyexcel.get_book(file_name=asset.docfile)
Here is my error description:
Here is the info right at where my code breaks:
Although it says "Wrong filename", I can see the file is in the folder:
I'm able to open the file by double-clicking; the file is not corrupted.
EDIT:
If I cast the 'asset.docfile' to str, like so:
asset = Excel_CSV_Asset.objects.get(id=assetid)
book=pyexcel.get_book(file_name=str(asset.docfile))
I get a different error:
[Errno 2] No such file or directory: 'Excel_CSV_Assets/2016/04/23/Animals_oglc4DV.xlsx'
...but this is the correct directory, located beneath the MEDIA_ROOT file structure.
Here is settings.py MEDIA_ROOT:
MEDIA_ROOT = 'site_static/site/original_assets/'
Here is urls.py:
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^e/', include('excel_to_mongo.urls')),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Here is the url.py of that app:
url(r'^efactory/(?P<assetid>\d+)/$', 'display_sheet_column_choices', {}),
I think your problem is that you don't fully understand the media files management with Django.
What are media files?
Media files are all the files that are user-uploaded (at running time).
You must not mistake them with Static files that are assets needed by your project to work and that you add at development time (CSS, background picture and JS files for instance).
You shouldn't mix them because they are managed differently by the server and that it could lead to security problems (cf. the warning here):
Static files management :
You put your static files as a part of the code either in one static subdirectory from the installed django applications, either in one of the locations you added to STATICFILES_DIRS.
Static files have to be gathered before starting the server by calling ./manage.py collectstatic, this command will collect (copy) the static files into the a directory (STATIC_ROOT's value).
You then have to set STATIC_URL to choose with wich url you should serve your static files. An usual choice would be /static/. To access the static file you should then try to reach /static/path/to/static/file/in/static_root/dir.
Media files management :
Your media files are added at running time. They are stored in the MEDIA_ROOT location that has to be an absolute path. Hence the fact I suggested you to join the BASE_DIR value (an absolute path) and the subdir you would choose with something like :
MEDIA_ROOT = os.path.join(BASE_DIR, "/media/subdir")
You then have to set an URL for your media files, by using the MEDIA_URL variable. To access your media files, the urls will start with the value you choose :
MEDIA_URL = '/media/'
Then, add this to your urls.py file :
if settings.DEBUG:
urlpatterns = urlpatterns + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
With the current example, your mymediafile.txt will be located at /path/to/your/project/media/subdir/path/in/media/root/mymediafile.txt and served at http://127.0.0.1:8000/media/path/in/media/root/mymediafile.txt.
But this is suitable only for a development use as told here. And this would work only for DEBUG == TRUE
For a production use, you should consider deploying your media files with your http server (apache for instance).
Conclusion :
Take the time to understand this. Because I suspect you don't really understood what you did and this lack of understanding could lead to future bugs and errors.

WordPress Comment Image plugin doesn't save uploaded image when Apache Requires are used

I've got an Apache 2.4.7 box with a WordPress 4.1 installation and a plugin added which allows users to add images to comments on pages/posts (https://wordpress.org/plugins/comment-images/). The image upload feature isn't working when Require statements are added to restrict access to the site (it's a development environment so limited access is required).
The image upload actually works with or without Require directives but when the directives are added, the reference to the uploaded image doesn't get saved to WordPress properly.
The error from the log is:
PHP Warning: preg_match_all() expects parameter 2 to be string, object given in /var/www/html/wp-content/plugins/comment-images/class-comment-image.php on line 480
I dumped the object being passed into a file (serialized):
O:8:"WP_Error":2:{s:16:"^#WP_Error^#errors";a:1:{s:8:"http_404";a:1:{i:0;s:12:"Unauthorized";}}s:20:"^#WP_Error^#error_data";a:0:{}}
I outputted the print_debug_backtrace() as well to show the calls. I've had to delete the comment data from the arrays for privacy reasons:
#0 Comment_Image->save_comment_image(63)
#1 call_user_func_array(Array ([0] => Comment_Image Object ([] => 5000000,[] => ,[] => ),[1] => save_comment_image), Array ([0] => 63)) called at [/var/www/html/wp-includes/plugin.php:496]
#2 do_action(wp_insert_comment, 63, stdClass Object ()) called at [/var/www/html/wp-includes/comment.php:1941]
#3 wp_insert_comment(Array ()) called at [/var/www/html/wp-includes/comment.php:2083]
#4 wp_new_comment(Array ()) called at [/var/www/html/wp-comments-post.php:137]
The directives for the <Directory> with the WP install in are (with IPs obfuscated):
AllowOverride All
<RequireAny>
AuthType Basic
AuthName "Restricted Access"
AuthBasicProvider file
AuthUserFile /var/www/.htpasswd
Require valid-user
Require user dev www-data
Require ip xx.xx.xx.xx/xx
Require ip xx.xx.xx.xx
Require local
</RequireAny>
If I add Require all granted (or just remove the Require directives), then the feature works as expected and uploaded images show up. Note Require local is there which as I understand it should cover everything for the local box.
Things I've checked:
Revised the configs in light of Apache 2.4 changes to auth modules and ordering importance etc.
WordPress install folder is recursively chown'ed correctly
Permissions on upload folder are 777'd, but shouldn't matter as the upload always succeeds
Where does this issue lie??
Looks like the plugin does not handle well the fact that your server is unable to download an image on itself.
The warning (class-comment-image.php on line 480) corresponds to this snippet:
$img_url = media_sideload_image( $comment_image_file['url'], $post_id );
preg_match_all( "#[^<img src='](.*)[^'alt='' />]#", $img_url, $matches );
$comment_image_file['url'] = $matches[0][0];
The WP media_sideload_image function uses curl to get the image, and because of your restrictions it does not succeed, and then returns an error object that the preg_match_all function cannot handle.
The data is saved later in the metas; it explains why the reference is not saved even if the upload worked.
Require local probably does not work on your dev server, you may try to replace it with its local address.
I tried adding Require ip <local-ip-of-box> as per johansatge's suggestion. Whilst this didn't doesn't work, it made me think..
The box is in Azure which assigns a floating public IP. Annoyingly, the cURL request was bouncing out and using that public IP - because the domain used for the box wasn't added to the hosts file.
The solution was to add <domain-of-website-on-box> to the loopback (127.0.0.1) entry in /etc/hosts.

Get mime type with Gaufrette and Vich uploader on Symfony2

I have a problem. I use gaufrette with Vich uploader and add a $file attribute to my entity that is VichUploadable.
I did the configuration and the upload of files works well.
But when I want to get the mime type of the file (via the entity after the file has been uploaded) I get an error due to the file name format that Gaufrette use.
When I try to do "$myEntity->getFile()->getMimeType()" where the getFile return the File object that is Vichuploadable, I get this error : " Unable to find the wrapper \"gaufrette\" - did you forget to enable it when you configured PHP?"
Do you have any idea on how I can have the mime type ?
thank you
Gaufrette stream wrappers must be enabled for this to work:
knp_gaufrette:
stream_wrapper: ~
# ...

How should I protect a static Wordpress file directory from the outside world?

I'm taking over the admin of a WP site that serves static docs from a dedicated directory. The current directory resides on the top level (/public_html/docs) which seems susceptible to snooping. The site sits behind a login firewall.
The file directory contains >500 individual files, so uploading and hand-editing individual links seems absurd. (At least to me.)
Should I move this directory to a more secure location within the WP directory? Or, what is the preferred way to configure .htaccess?
At a minimum I would disable Directory Listing by using an .htaccess file that sits inside your /public_html/docs directory.
IndexIgnore *
Possibly a more secure method would be to move the docs directory outside your public_html directory. Then use a PHP script that can serve your document by passing a variable, such as www.site.com/serve_doc.php?name=xxxx.pdf.
Here is some code to accomplish this:
// get the file name
$file = $_GET['name'];
$dir = "/home/xxxx/docs/";
$fp = fopen($dir.$file, 'rb');
if(!$fp) { exit; }
// open the file
$finfo = finfo_open();
$filetype = finfo_file($finfo, $file, FILEINFO_MIME);
finfo_close($finfo);
$filename = $file;
// send the right headers
header("Cache-Control: ");// leave blank to avoid IE errors
header("Pragma: ");// leave blank to avoid IE errors
header("Content-Type: " .$filetype );
header('Content-Disposition: attachment; filename="'.$filename.'"');
header("Content-Length: " . filesize($dir.$file));
// dump the file and stop the script
fpassthru($fp);
exit();
Of course you'll want to add some authentication to validate whether the user should be able to call this PHP script. One possible way would be to call the Wordpress function is_user_logged_in in that script before serving the file.

nodejs read image headers

I'm writing a script to download files from urls in a list. The problem I'm having is that the urls don't just point to static files, like file.jpg, they tend to point to servlets that return a file.
What I want to do is download the file for each url and save it with a generic name, then read its headers and rename it with the appropriate extension. (Unless there's a better way)
How could I do that?
I've tried using mime-magic, but it tells me that the extension-less files are directories.
It should work using mime-magic. Are you sure the path is correct and the path is not pointing to a directory?
Otherwise you could use the command line tool file --mime /path/to/file
Here is how to detect an extension of a file using mime-magic:
mime('/path/to/foo.pdf', function (err, type) {
if (err) {
console.error(err.message);
// ERROR: cannot open `/path/to/foo.pdf' (No such file or directory)
} else {
console.log('Detected mime type: %s', type);
// application/pdf
}
});
Note: Added sled's comment as an answer under community-wiki.

Resources