Update with requested changes
This commit is contained in:
parent
f12af86757
commit
04cf33a1d0
@ -27,6 +27,7 @@ import select
|
||||
import socket
|
||||
import sys
|
||||
from time import time
|
||||
from unicodedata import normalize
|
||||
|
||||
|
||||
#
|
||||
@ -336,43 +337,27 @@ class AnkiNoteParams:
|
||||
#
|
||||
|
||||
class AnkiBridge:
|
||||
def getFilePath(self, filename):
|
||||
mediaFolder = self.collection().media.dir()
|
||||
filePath = os.path.normpath(os.path.join(mediaFolder, filename))
|
||||
# catch attempts to write outside the media folder
|
||||
if os.path.commonprefix([mediaFolder, filePath]) != mediaFolder:
|
||||
return False
|
||||
|
||||
return filePath
|
||||
def storeMediaFile(self, filename, data):
|
||||
self.deleteMediaFile(filename)
|
||||
self.media().writeData(filename, base64.b64decode(data))
|
||||
|
||||
|
||||
def storeFile(self, filename, data):
|
||||
filePath = self.getFilePath(filename)
|
||||
if filePath:
|
||||
with open(filePath, 'wb') as file:
|
||||
file.write(base64.b64decode(data))
|
||||
return True
|
||||
def retrieveMediaFile(self, filename):
|
||||
# based on writeData from anki/media.py
|
||||
filename = os.path.basename(filename)
|
||||
filename = normalize("NFC", filename)
|
||||
filename = self.media().stripIllegal(filename)
|
||||
|
||||
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
|
||||
|
||||
|
||||
def retrieveFile(self, filename):
|
||||
filePath = self.getFilePath(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 deleteMediaFile(self, filename):
|
||||
self.media().syncDelete(filename)
|
||||
|
||||
|
||||
def addNote(self, params):
|
||||
@ -922,18 +907,18 @@ class AnkiConnect:
|
||||
|
||||
|
||||
@webApi
|
||||
def storeFile(self, filename, data):
|
||||
return self.anki.storeFile(filename, data)
|
||||
def storeMediaFile(self, filename, data):
|
||||
return self.anki.storeMediaFile(filename, data)
|
||||
|
||||
|
||||
@webApi
|
||||
def retrieveFile(self, filename):
|
||||
return self.anki.retrieveFile(filename)
|
||||
def retrieveMediaFile(self, filename):
|
||||
return self.anki.retrieveMediaFile(filename)
|
||||
|
||||
|
||||
@webApi
|
||||
def deleteFile(self, filename):
|
||||
return self.anki.deleteFile(filename)
|
||||
def deleteMediaFile(self, filename):
|
||||
return self.anki.deleteMediaFile(filename)
|
||||
|
||||
|
||||
@webApi
|
||||
|
29
README.md
29
README.md
@ -95,7 +95,7 @@ Categories:
|
||||
* [Card Suspension](#card-suspension)
|
||||
* [Card Intervals](#card-intervals)
|
||||
* [Finding Notes and Cards](#finding-notes-and-cards)
|
||||
* [File Storage](#file-storage)
|
||||
* [Media File Storage](#media-file-storage)
|
||||
* [Graphical](#graphical)
|
||||
|
||||
### 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
|
||||
`false` if attempting to write a file outside the media folder.
|
||||
Stores a file with the specified base64-encoded contents inside the media folder.
|
||||
|
||||
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.
|
||||
@ -866,7 +865,7 @@ Categories:
|
||||
*Sample request*:
|
||||
```
|
||||
{
|
||||
"action": "storeFile",
|
||||
"action": "storeMediaFile",
|
||||
"params": {
|
||||
"filename": "_hello.txt",
|
||||
"data": "SGVsbG8sIHdvcmxkIQ=="
|
||||
@ -876,7 +875,7 @@ Categories:
|
||||
|
||||
*Sample response*:
|
||||
```
|
||||
true
|
||||
null
|
||||
```
|
||||
|
||||
*Content of `_hello.txt`*:
|
||||
@ -884,15 +883,14 @@ Categories:
|
||||
Hello world!
|
||||
```
|
||||
|
||||
* **retrieveFile**
|
||||
* **retrieveMediaFile**
|
||||
|
||||
Retrieves the base64-encoded contents of the specified file, returning `false` if the file does not exist or if
|
||||
attempting to read a file outside the media folder.
|
||||
Retrieves the base64-encoded contents of the specified file, returning `false` if the file does not exist.
|
||||
|
||||
*Sample request*:
|
||||
```
|
||||
{
|
||||
"action": "retrieveFile",
|
||||
"action": "retrieveMediaFile",
|
||||
"params": {
|
||||
"filename": "_hello.txt"
|
||||
}
|
||||
@ -904,15 +902,14 @@ Categories:
|
||||
"SGVsbG8sIHdvcmxkIQ=="
|
||||
```
|
||||
|
||||
* **deleteFile**
|
||||
* **deleteMediaFile**
|
||||
|
||||
Deletes the specified file inside the media folder, returning `true` if successful, or `false` if the file does not
|
||||
exist or if attempting to delete a file outside the media folder.
|
||||
Deletes the specified file inside the media folder.
|
||||
|
||||
*Sample request*:
|
||||
```
|
||||
{
|
||||
"action": "deleteFile",
|
||||
"action": "deleteMediaFile",
|
||||
"params": {
|
||||
"filename": "_hello.txt"
|
||||
}
|
||||
@ -921,7 +918,7 @@ Categories:
|
||||
|
||||
*Sample response*:
|
||||
```
|
||||
true
|
||||
null
|
||||
```
|
||||
|
||||
### Graphical ###
|
||||
|
Loading…
Reference in New Issue
Block a user