Update with requested changes
This commit is contained in:
parent
f12af86757
commit
04cf33a1d0
@ -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
|
||||||
|
29
README.md
29
README.md
@ -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 ###
|
||||||
|
Loading…
Reference in New Issue
Block a user