Update with requested changes

This commit is contained in:
David Bailey 2017-08-22 20:05:12 +01:00
parent f12af86757
commit 04cf33a1d0
2 changed files with 35 additions and 53 deletions

View File

@ -27,6 +27,7 @@ import select
import socket import socket
import sys import sys
from time import time from time import time
from unicodedata import normalize
# #
@ -336,43 +337,27 @@ class AnkiNoteParams:
# #
class AnkiBridge: class AnkiBridge:
def getFilePath(self, filename): def storeMediaFile(self, filename, data):
mediaFolder = self.collection().media.dir() self.deleteMediaFile(filename)
filePath = os.path.normpath(os.path.join(mediaFolder, filename)) self.media().writeData(filename, base64.b64decode(data))
# catch attempts to write outside the media folder
if os.path.commonprefix([mediaFolder, filePath]) != mediaFolder:
return False
return filePath
def storeFile(self, filename, data): def retrieveMediaFile(self, filename):
filePath = self.getFilePath(filename) # based on writeData from anki/media.py
if filePath: filename = os.path.basename(filename)
with open(filePath, 'wb') as file: filename = normalize("NFC", filename)
file.write(base64.b64decode(data)) filename = self.media().stripIllegal(filename)
return True
path = os.path.join(self.media().dir(), filename)
if os.path.exists(path):
with open(path, 'rb') as file:
return base64.b64encode(file.read()).decode('ascii')
return False return False
def retrieveFile(self, filename): def deleteMediaFile(self, filename):
filePath = self.getFilePath(filename) self.media().syncDelete(filename)
if filePath and os.path.isfile(filePath):
with open(filePath, 'rb') as file:
data = base64.b64encode(file.read())
return data.decode('ascii')
return False
def deleteFile(self, filename):
filePath = self.getFilePath(filename)
if filePath and os.path.isfile(filePath):
os.remove(filePath)
return True
return False
def addNote(self, params): def addNote(self, params):
@ -922,18 +907,18 @@ class AnkiConnect:
@webApi @webApi
def storeFile(self, filename, data): def storeMediaFile(self, filename, data):
return self.anki.storeFile(filename, data) return self.anki.storeMediaFile(filename, data)
@webApi @webApi
def retrieveFile(self, filename): def retrieveMediaFile(self, filename):
return self.anki.retrieveFile(filename) return self.anki.retrieveMediaFile(filename)
@webApi @webApi
def deleteFile(self, filename): def deleteMediaFile(self, filename):
return self.anki.deleteFile(filename) return self.anki.deleteMediaFile(filename)
@webApi @webApi

View File

@ -95,7 +95,7 @@ Categories:
* [Card Suspension](#card-suspension) * [Card Suspension](#card-suspension)
* [Card Intervals](#card-intervals) * [Card Intervals](#card-intervals)
* [Finding Notes and Cards](#finding-notes-and-cards) * [Finding Notes and Cards](#finding-notes-and-cards)
* [File Storage](#file-storage) * [Media File Storage](#media-file-storage)
* [Graphical](#graphical) * [Graphical](#graphical)
### Miscellaneous ### ### Miscellaneous ###
@ -853,12 +853,11 @@ Categories:
] ]
``` ```
### File Storage ### ### Media File Storage ###
* **storeFile** * **storeMediaFile**
Stores a file with the specified base64-encoded contents inside the media folder. Returns `true` upon success or Stores a file with the specified base64-encoded contents inside the media folder.
`false` if attempting to write a file outside the media folder.
Note: to prevent Anki from removing files not used by any cards (e.g. for configuration files), prefix the filename Note: to prevent Anki from removing files not used by any cards (e.g. for configuration files), prefix the filename
with an underscore. These files are still synchronized to AnkiWeb. with an underscore. These files are still synchronized to AnkiWeb.
@ -866,7 +865,7 @@ Categories:
*Sample request*: *Sample request*:
``` ```
{ {
"action": "storeFile", "action": "storeMediaFile",
"params": { "params": {
"filename": "_hello.txt", "filename": "_hello.txt",
"data": "SGVsbG8sIHdvcmxkIQ==" "data": "SGVsbG8sIHdvcmxkIQ=="
@ -876,7 +875,7 @@ Categories:
*Sample response*: *Sample response*:
``` ```
true null
``` ```
*Content of `_hello.txt`*: *Content of `_hello.txt`*:
@ -884,15 +883,14 @@ Categories:
Hello world! Hello world!
``` ```
* **retrieveFile** * **retrieveMediaFile**
Retrieves the base64-encoded contents of the specified file, returning `false` if the file does not exist or if Retrieves the base64-encoded contents of the specified file, returning `false` if the file does not exist.
attempting to read a file outside the media folder.
*Sample request*: *Sample request*:
``` ```
{ {
"action": "retrieveFile", "action": "retrieveMediaFile",
"params": { "params": {
"filename": "_hello.txt" "filename": "_hello.txt"
} }
@ -904,15 +902,14 @@ Categories:
"SGVsbG8sIHdvcmxkIQ==" "SGVsbG8sIHdvcmxkIQ=="
``` ```
* **deleteFile** * **deleteMediaFile**
Deletes the specified file inside the media folder, returning `true` if successful, or `false` if the file does not Deletes the specified file inside the media folder.
exist or if attempting to delete a file outside the media folder.
*Sample request*: *Sample request*:
``` ```
{ {
"action": "deleteFile", "action": "deleteMediaFile",
"params": { "params": {
"filename": "_hello.txt" "filename": "_hello.txt"
} }
@ -921,7 +918,7 @@ Categories:
*Sample response*: *Sample response*:
``` ```
true null
``` ```
### Graphical ### ### Graphical ###