After Magento 1.9 SUPEE-9767 allow pdf upload not working - Invalid Mime Type - magento-1.9

I used this modification to allow upload of PDF files into magento
https://magento.stackexchange.com/a/155950/40025
After applying SUPEE-9767 Upload does not work anymore and got Message "Invalid Mime Type"
How to allow PDF upload after SUPEE-9767 Patch?

I created a module to help fix the problem. Hopefully, it helps others who come across this same issue.
Ash_PdfUploadAfterSupee9767 on Github
Overrides:
Mage_Core_Model_File_Validator_Image (skips validation if mime type is application/pdf)
Mage_Cms_Model_Wysiwyg_Images_Storage (skips resizing if mime type is application/pdf)
Adds pdf to array of allowed and image_allowed extensions from the Mage_Cms/etc/config.xml

Following Rakesh's Answer you could extend the validate() function in \app\code\local\Mage\Core\Model\File\Validator\Image.php from
imagedestroy($img);
imagedestroy($image);
return null;
} else {
throw Mage::exception('Mage_Core', Mage::helper('core')->__('Invalid image.'));
}
}
}
to
imagedestroy($img);
imagedestroy($image);
return null;
} else {
throw Mage::exception('Mage_Core', Mage::helper('core')->__('Invalid image.'));
}
}
} else {
if (mime_content_type($filePath)=='application/pdf') {
$fileType = IMAGETYPE_PNG;
return null;
}
throw Mage::exception('Mage_Core', Mage::helper('core')->__('Invalid MIME type.').' '.mime_content_type($filePath));
}
Tested in Magento CE 1.9.2.4. The extended answer in German you can find here.

There is a new validation added to uplaodeFile function (app/code/core/Mage/Cms/Model/Wysiwyg/Images/Storage.php) which doesn't allow PDF to get uploaded even after adding <pdf>1</pdf> to CMS Browsers extensions node.
Here is the new validation
$uploader->addValidateCallback(
Mage_Core_Model_File_Validator_Image::NAME,
Mage::getModel('core/file_validator_image'),
'validate'
);
This additional validation check for file types that are defined in class
Mage_Core_Model_File_Validator_Image
Below is the list of allowed images types that can be uploaded via WYSIWYG insert Image action.
IMAGETYPE_JPEG,IMAGETYPE_GIF,
IMAGETYPE_JPEG2000,
IMAGETYPE_PNG,
IMAGETYPE_ICO,
IMAGETYPE_TIFF_II,
IMAGETYPE_TIFF_MM
So, Basically in order to allow PDF upload
Extends Mage_Core_Model_File_Validator_Image::validate and add custom logic to allow PDF upload
Create a new extension that will allow PDF upload.

Related

Dart / flutter: download or read the contents of a Google Drive file

I have a public (anyone with the link can view) file on my Google Drive and I want to use the content of it in my Android app.
From what I could gather so far, I need the fileID, the OAuth token and the client ID - these I already got. But I can't figure out what is the exact methodology of authorising the app or fetching the file.
EDIT:
Simply reading it using file.readAsLines didn't work:
final file = new File(dogListTxt);
Future<List<String>> dogLinks = file.readAsLines();
return dogLinks;
The dogLinks variable isn't filled with any data, but I get no error messages.
The other method I tried was following this example but this is a web based application with explicit authorization request (and for some reason I was never able to import the dart:html library).
The best solution would be if it could be done seamlessly, as I would store the content in a List at the application launch, and re-read on manual refresh button press.
I found several old solutions here, but the methods described in those doesn't seem to work anymore (from 4-5 years ago).
Is there a good step-by-step tutorial about integrating the Drive API in a flutter application written in dart?
I had quite a bit of trouble with this, it seems much harder than it should be. Also this is for TXT files only. You need to use files.export() for other files.
First you need to get a list fo files.
ga.FileList textFileList = await drive.files.list(q: "'root' in parents");
Then you need to get those files based on ID (This is for TXT Files)
ga.Media response = await drive.files.get(filedId, downloadOptions: ga.DownloadOptions.FullMedia);
Next is the messy part, you need to convert your Media object stream into a File and then read the text from it. ( #Google, please make this easier.)
List<int> dataStore = [];
response.stream.listen((data) {
print("DataReceived: ${data.length}");
dataStore.insertAll(dataStore.length, data);
}, onDone: () async {
Directory tempDir = await getTemporaryDirectory(); //Get temp folder using Path Provider
String tempPath = tempDir.path; //Get path to that location
File file = File('$tempPath/test'); //Create a dummy file
await file.writeAsBytes(dataStore); //Write to that file from the datastore you created from the Media stream
String content = file.readAsStringSync(); // Read String from the file
print(content); //Finally you have your text
print("Task Done");
}, onError: (error) {
print("Some Error");
});
There currently is no good step-by-step tutorial, but using https://developers.google.com/drive/api/v3/manage-downloads as a reference guide for what methods to use in Dart/Flutter via https://pub.dev/packages/googleapis: to download or read the contents of a Google Drive file, you should be using googleapis/Drive v3, or specifically, the methods from the FilesResourceApi class.
drive.files.export(), if this is a Google document
/// Exports a Google Doc to the requested MIME type and returns the exported content. Please note that the exported content is limited to 10MB.
drive.files.get(), if this something else, a non-Gdoc file
/// Gets a file's metadata or content by ID.
Simplified example:
var drive = new DriveApi(http_client);
drive.files.get(fileId).then((file) {
// returns file
});
However, what I discovered was that this Dart-GoogleAPIs library seemed to be missing a method equivalent to executeMediaAndDownloadTo(outputStream). In the original Google Drive API v3, this method adds the alt=media URL parameter to the underlying HTTP request. Otherwise, you'll get the error, which is what I saw:
403, message: Export requires alt=media to download the exported
content.
And I wasn't able to find another way to insert that URL parameter into the current request (maybe someone else knows?). So as an alternative, you'll have to resort to implementing your own Dart API to do the same thing, as hinted by what this OP did over here https://github.com/dart-lang/googleapis/issues/78: CustomDriveApi
So you'll either:
do it through Dart with your own HttpClient implementation and try to closely follow the REST flow from Dart-GoogleAPIs, but remembering to include the alt=media
or implement and integrate your own native-Android/iOS code and use the original SDK's convenient executeMediaAndDownloadTo(outputStream)
(note, I didn't test googleapis/Drive v2, but a quick examination of the same methods looks like they are missing the same thing)
I wrote this function to get file content of a file using its file id. This is the simplest method I found to do it.
Future<String> _getFileContent(String fileId) async {
var response = await driveApi.files.get(fileId, downloadOptions: DownloadOptions.fullMedia);
if (response is! Media) throw Exception("invalid response");
return await utf8.decodeStream(response.stream);
}
Example usage:
// save file to app data folder with 150 "hello world"s
var content = utf8.encode("hello world" * 150);
driveApi.files
.create(File(name: fileName, parents: [appDataFolder]),
uploadMedia: Media(Stream.value(content), content.length))
.then((value) {
Log().i("finished uploading file ${value.id}");
var id = value.id;
if (id != null) {
// after successful upload, read the recently uploaded file content
_getFileContent(id).then((value) => Log().i("got content is $value"));
}
});

Google chrome extensions for managing Downloads

I am trying to create an extension which puts all the pdf files downloaded by user through browser into a separate directory. Any Api by which can do this or some help on how I can do it would be helpful.
While you cannot easily write to an arbitrary path, you can redirect all PDF files into a subfolder of Downloads folder.
Check out onDeterminingFilename event of chrome.downloads and Filename Controller sample extension. Since you can indicate a relative path instead of a plain filename, this should work.
Note that the file's MIME type should be available in onDeterminingFilename, you can use that.
Code example, as requested:
var folder = "PDF_downloads";
chrome.downloads.onDeterminingFilename.addListener(
function (item, suggest) {
if(isPDF(item)) suggest({filename: folder + "/" + item.filename});
else suggest();
}
);
function isPDF(item){
if(item.mime === "application/pdf") return true;
else if (item.filename.match(/\.pdf$/i)) return true;
else return false;
}
This will not override that the browser tries to open the PDF itself instead of downloading, but attempting to download will suggest that folder.

How to embed MediaWiki page content into my site?

Our corporate wiki is Mediawiki. I have no problem to put iframe into my site to refer for some article on wiki.
But my own site have a lot of widgets and own style. I don't want to include Mediawiki navigation/search/login widgets, logo image.
Is it possible and how to get Mediawiki page contents without widgets (only article body)?
Yes, it is. You'll probably want to use the action=render url parameter, for example: http://en.wikipedia.org/w/index.php?action=render&title=Main_Page. Note that the stylesheets from the wiki aren't included, so you'll need to copy the relevant rules to your site's css files. See also this.
Thank waldir for answer!
After asking question I perform own research and end with code:
window.onload = function() {
httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState !== 4) {
console.log("Not ready, code: %o", httpRequest.readyState);
return;
}
if (httpRequest.status !== 200) {
console.log("Server error: %o", httpRequest.status);
return;
}
var json = JSON.parse(httpRequest.responseText);
console.log("json: %o", json);
var wiki = json.query.pages["1"].revisions[0]["*"];
console.log("wiki: %o", wiki);
var html = InstaView.convert(wiki);
console.log("html: %o", html);
document.getElementById('area').innerHTML = html;
};
var url = 'https://wiki.evil-company.com/api.php?action=query&prop=revisions&format=json&titles=Main_page&rvprop=timestamp|user|comment|content';
httpRequest.open('GET', url, true);
httpRequest.send(null);
}
Here I use https://github.com/cscott/instaview/blob/master/main.js project which is enhanced http://en.wikipedia.org/wiki/User:Pilaf to transform json output to HTML on browser side.
The reason for this code because our wiki is old or misconfigured and action=render is not available. But I trap into cross-domain scripting issue so I think that iframe with action=render is better solution.
See also How do you grab an article including the links in a usable format?
Another suggestion to use action=parse (http://en.wikipedia.org/w/api.php?action=parse&title=Linux) lead to warning:
You are looking at the HTML representation of the XML format.
HTML is good for debugging, but is unsuitable for application use.
Specify the format parameter to change the output format.
UPDATE
Perfect solution just append query action=render to any valid wiki URL like:
http://en.wikipedia.org/wiki/Linux?action=render

How to browse mobile directory in flex?

I have captured 3 videos on my mobile which is by default stored on the phone gallery (Gallery/videos/). I have to play these 3 videos in one of my flex mobile application. How can I get the videos to the flex project? if I need to browse the mobile directory means kindly help me with some code to do so.
I too am looking for an answer to this question. Right now, based on other Stackoverflow discussions, exhaustive perusal of tutorials and Adobe documentation, and comments to both (often the more useful resource), I'm coming to the conclusion that it's not possible.
you can use CameraRoll.browseForImage() and open the iOS gallery of photos to see all entities of MediaType.IMAGE, but it will not show you MediaType.VIDEO
you can use CameraUI to launch the system camera by delegation and that returns a MediaPromise, but as far as I can tell, it does not save the video you capture anywhere, and I cannot find a way to access the captured video using the MediaPromise (at least using the Loader class)
Here's my code as a hint in that direction. The second code block is using the CameraRoll to browseForImage() but there is no browseForVideo() in the API.
if(CameraUI.isSupported)
{
camera = new CameraUI();
camera.addEventListener(MediaEvent.COMPLETE, videoMediaEventComplete);
camera.addEventListener(Event.CANCEL, cameraCanceled);
camera.addEventListener(ErrorEvent.ERROR, cameraError);
camera.launch(MediaType.VIDEO);
}
else
{
statusText.text = "Camera not supported on this device.";
startTimer();
}
if (CameraRoll.supportsBrowseForImage)
{
roll = new CameraRoll();
roll.addEventListener(MediaEvent.SELECT, cameraRollEventComplete);
roll.addEventListener(Event.CANCEL, cameraCanceled);
roll.addEventListener(ErrorEvent.ERROR, cameraError);
roll.browseForImage();
}
else
{
statusText.text = "Camera roll not supported on this device.";
startTimer();
}
I've since found that Videos captured using the delegated system camera are stored in a temporary storage location that iOS -DOES!- allow access to. (I was pleasantly shocked.)
The Captured video is not added to the device's Camera Roll as other videos captured using the iOS System Camera app, so it's not enough to capture video and expect to be able to access it later (if, for instance, CameraRoll.browseForVideo() is ever added to the API.
Therefore, you have to 'get while the getting is good' and move the file from the temporary storage location to some non-volatile location such as ApplicationStorageDirectory or the user's Documents directory (The only options in iOS I think).
The MediaPromise... I think... is completely useless for accessing the video via any direct progressive loader/streamer method, but still provides the location/url/path/filename of the temporary file so you can perform File operations on it.
Ironic that there are tutorials for getting around the lack of a file location/url/path/filename in the MediaPromise when using CameraRoll.browseForImage()... and that method is to use a loader class to load the image content (which you can then write out to a file), but when taking video, the video content is not accessible, and instead a file location/url/path/filename is provided. Ironic that there are nearly no resources I was able to find to help with this also. grumble
I'm going to include some code chunks w/o really editing them to strip out extraneous bits because it's way past when I need to be in bed, but I wanted you to have this. I may come clean it up later.
This section is in a Spark SkinnablePopUpContainer and I use the same click event for several buttons, thus the below 'case' is in the switch-case in that event handler function.
In case you are not familiar, the 'close(true, data)' is the method to close the SkinnablePopUpContainer, tell the parent/owner that the container was closed purposefully and that it should look for the data object being shared back (i.e., there are changes to be 'commit'ed).
case "cameraVideo":
{
if(CameraUI.isSupported)
{
camera = new CameraUI();
camera.addEventListener(MediaEvent.COMPLETE, videoMediaEventComplete);
camera.addEventListener(Event.CANCEL, cameraCanceled);
camera.addEventListener(ErrorEvent.ERROR, cameraError);
camera.launch(MediaType.VIDEO);
}
else
{
statusText.text = "Camera not supported on this device.";
startTimer();
}
break;
}
protected function cameraCanceled(event:Event):void
{
statusText.text = "Camera access canceled by user.";
startTimer();
}
protected function cameraError(event:ErrorEvent):void
{
statusText.text = "There was an error while trying to use the camera.";
startTimer();
}
protected function videoMediaEventComplete(event:MediaEvent):void
{
statusText.text="Preparing captured video...";
camera.removeEventListener(MediaEvent.COMPLETE, videoMediaEventComplete);
camera.removeEventListener(Event.CANCEL, cameraCanceled);
camera.removeEventListener(ErrorEvent.ERROR, cameraError);
var media:MediaPromise = event.data;
data.MediaType = MediaType.VIDEO;
data.MediaPromise = media;
data.source = "camera video";
close(true,data)
}
This section is the Actionscript in the close handler of the parent/owner of the SkinnablePopUpContainer (truncated once the useful code is included)
private function choosePictureLightboxClosed(event:PopUpEvent):void
{
imageButtonsActive = false;
if(event.commit)
{
this.data = event.data as Object;
filters = new Array();
selection = true;
switch(data.MediaType)
{
case MediaType.VIDEO:
{
mediaType = "video";
trace(data.MediaPromise.file.url + " - " + data.MediaPromise.relativePath + " - " +data.MediaPromise.mediaType);
var sourceFile:File = new File(data.MediaPromise.file.url);
var destinationFile:File = File.applicationStorageDirectory.resolvePath("User" +parentApplication.userid);
if(destinationFile.exists && !destinationFile.isDirectory)
{
destinationFile.deleteFile();
}
destinationFile.createDirectory();
destinationFile = destinationFile.resolvePath("Videos");
if(destinationFile.exists && !destinationFile.isDirectory)
{
destinationFile.deleteFile();
}
destinationFile.createDirectory();
destinationFile = destinationFile.resolvePath(parentApplication.userid+"Video"+new Date().getTime()+".mov");
trace(destinationFile.nativePath);
sourceFile.moveTo(destinationFile,true);
break;
}
I sure do hope this helps. This has been a very frustrating (and costly in terms of our project being government grant funded and having deadlines we utterly failed to meet), and I very much hope that these hard-won solutions might help others avoid the same experience.

Primefaces fileDownload non-english file names corrupt

I am using Primefaces 3.2. I've got problems with using primefaces fileDownload. I can upload the files and keep their non-english name on the server (in my case this is Russian). However, when I use p:fileDownload to download the uploaded files I cannot use Russian letters since they get corrupt. It seems that the DefaultStreamedContent class constructor accepts only Latin letters.
I am doing everything according to the showcase on the primefaces website as shown below.
public FileDownloadController() {
InputStream stream = ((ServletContext)FacesContext.getCurrentInstance().getExternalContext().getContext()).getResourceAsStream("/images/optimusprime.jpg");
file = new DefaultStreamedContent(stream, "image/jpg", "downloaded_optimus.jpg");
}
Any ideas how I can solve my problem?
Thanks, in advance.
This is fixed in the upcoming PrimeFaces 6.2, but for earlier versions the fix below needs to be applied. In a link in the comments below a reference to a PrimeFaces issue was posted which contains info that the fix below does work for Chrome, IE and Opera but not for FireFox (no version mentioned, nor is 'Edge' mentioned)
Workaround
Try to encode your file name in application/x-www-form-urlencoded MIME format (URLEncoder).
Example:
public StreamedContent getFileDown () {
// Get current position in file table
this.currentPosition();
attachments = getAttachments();
Attachment a = getAttachmentByPosition( pos, attachments );
FileNameMap fileNameMap = URLConnection.getFileNameMap();
// Detecting MIME type
String mimeType = fileNameMap.getContentTypeFor(a.getAttachmentName());
String escapedFilename = "Unrecognized!!!";
try {
// Encoding
escapedFilename = URLEncoder.encode(a.getAttachmentName(), "UTF-8").replaceAll(
"\\+", "%20");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
// Preparing streamed content
fileDown = new DefaultStreamedContent( new ByteArrayInputStream( a.getAttachment() ),
mimeType, escapedFilename);
return fileDown;
}