use of com.ichi2.utils.JSONObject in project AnkiChinaAndroid by ankichinateam.
the class Media method addFilesFromZip.
/**
* Extract zip data; return the number of files extracted. Unlike the python version, this method consumes a
* ZipFile stored on disk instead of a String buffer. Holding the entire downloaded data in memory is not feasible
* since some devices can have very limited heap space.
* <p>
* This method closes the file before it returns.
*/
public int addFilesFromZip(ZipFile z) throws IOException {
try {
List<Object[]> media = new ArrayList<>();
// get meta info first
JSONObject meta = new JSONObject(Utils.convertStreamToString(z.getInputStream(z.getEntry("_meta"))));
// then loop through all files
int cnt = 0;
for (ZipEntry i : Collections.list(z.entries())) {
if ("_meta".equals(i.getName())) {
// ignore previously-retrieved meta
continue;
} else {
String name = meta.getString(i.getName());
// normalize name for platform
name = Utils.nfcNormalized(name);
// save file
String destPath = dir().concat(File.separator).concat(name);
try (InputStream zipInputStream = z.getInputStream(i)) {
Utils.writeToFile(zipInputStream, destPath);
}
String csum = Utils.fileChecksum(destPath);
// update db
media.add(new Object[] { name, csum, _mtime(destPath), 0 });
cnt += 1;
}
}
if (media.size() > 0) {
mDb.executeMany("insert or replace into media values (?,?,?,?)", media);
}
return cnt;
} finally {
z.close();
}
}
use of com.ichi2.utils.JSONObject in project AnkiChinaAndroid by ankichinateam.
the class Media method filesInStr.
/**
* Extract media filenames from an HTML string.
*
* @param string The string to scan for media filenames ([sound:...] or <img...>).
* @param includeRemote If true will also include external http/https/ftp urls.
* @return A list containing all the sound and image filenames found in the input string.
*/
public static List<String> filesInStr(Collection mCol, Long mid, String string, boolean includeRemote) {
List<String> l = new ArrayList<>();
JSONObject model = mCol.getModels().get(mid);
List<String> strings = new ArrayList<>();
if (model.getInt("type") == Consts.MODEL_CLOZE && string.contains("{{c")) {
// if the field has clozes in it, we'll need to expand the
// possibilities so we can render latex
strings = _expandClozes(string);
} else {
strings.add(string);
}
for (String s : strings) {
// handle latex
s = LaTeX.mungeQA(s, mCol, model);
// extract filenames
Matcher m;
for (Pattern p : mRegexps) {
// NOTE: python uses the named group 'fname'. Java doesn't have named groups, so we have to determine
// the index based on which pattern we are using
int fnameIdx = p.equals(fSoundRegexps) ? 2 : p.equals(fImgRegExpU) ? 2 : 3;
m = p.matcher(s);
while (m.find()) {
String fname = m.group(fnameIdx);
boolean isLocal = !fRemotePattern.matcher(fname.toLowerCase(Locale.US)).find();
if (isLocal || includeRemote) {
l.add(fname);
}
}
}
}
return l;
}
use of com.ichi2.utils.JSONObject in project AnkiChinaAndroid by ankichinateam.
the class Collection method basicCheck.
/**
* DB maintenance *********************************************************** ************************************
*/
/*
* Basic integrity check for syncing. True if ok.
*/
public boolean basicCheck() {
// cards without notes
if (mDb.queryScalar("select 1 from cards where nid not in (select id from notes) limit 1") > 0) {
return false;
}
boolean badNotes = mDb.queryScalar("select 1 from notes where id not in (select distinct nid from cards) " + "or mid not in " + Utils.ids2str(getModels().ids()) + " limit 1") > 0;
// notes without cards or models
if (badNotes) {
return false;
}
// invalid ords
for (JSONObject m : getModels().all()) {
// ignore clozes
if (m.getInt("type") != Consts.MODEL_STD) {
continue;
}
// Make a list of valid ords for this model
JSONArray tmpls = m.getJSONArray("tmpls");
boolean badOrd = mDb.queryScalar("select 1 from cards where (ord < 0 or ord >= ?) and nid in ( " + "select id from notes where mid = ?) limit 1", tmpls.length(), m.getLong("id")) > 0;
if (badOrd) {
return false;
}
}
return true;
}
use of com.ichi2.utils.JSONObject in project AnkiChinaAndroid by ankichinateam.
the class Collection method load.
/**
* DB-related *************************************************************** ********************************
*/
public void load() {
Cursor cursor = null;
String deckConf = "";
try {
// Read in deck table columns
cursor = mDb.query("SELECT crt, mod, scm, dty, usn, ls, " + "conf, dconf, tags,ver FROM col");
if (!cursor.moveToFirst()) {
return;
}
mCrt = cursor.getLong(0);
mMod = cursor.getLong(1);
mScm = cursor.getLong(2);
// No longer used
mDty = cursor.getInt(3) == 1;
mUsn = cursor.getInt(4);
mLs = cursor.getLong(5);
mConf = new JSONObject(cursor.getString(6));
deckConf = cursor.getString(7);
mTagsJson = cursor.getString(8);
mTags.load(mTagsJson);
mVer = cursor.getInt(9);
} finally {
if (cursor != null) {
cursor.close();
}
}
// getModels().load(loadColumn("models")); This code has been
// moved to `CollectionHelper::loadLazyCollection` for
// efficiency Models are loaded lazily on demand. The
// application layer can asynchronously pre-fetch those parts;
// otherwise they get loaded when required.
Timber.i("load new collection");
mDecks.load(loadColumn("decks"), deckConf);
}
use of com.ichi2.utils.JSONObject in project AnkiChinaAndroid by ankichinateam.
the class Collection method deleteNotesWithWrongFieldCounts.
private ArrayList<String> deleteNotesWithWrongFieldCounts(Runnable notifyProgress, JSONObject m) throws JSONException {
Timber.d("deleteNotesWithWrongFieldCounts");
ArrayList<String> problems = new ArrayList<>();
// notes with invalid field counts
ArrayList<Long> ids;
ids = new ArrayList<>();
Cursor cur = null;
try {
notifyProgress.run();
cur = mDb.getDatabase().query("select id, flds from notes where mid = " + m.getLong("id"), null);
Timber.i("cursor size: %d", cur.getCount());
int currentRow = 0;
// Since we loop through all rows, we only want one exception
@Nullable Exception firstException = null;
while (cur.moveToNext()) {
try {
String flds = cur.getString(1);
long id = cur.getLong(0);
int fldsCount = 0;
for (int i = 0; i < flds.length(); i++) {
if (flds.charAt(i) == 0x1f) {
fldsCount++;
}
}
if (fldsCount + 1 != m.getJSONArray("flds").length()) {
ids.add(id);
}
} catch (IllegalStateException ex) {
// DEFECT: Theory that is this an OOM is discussed in #5852
// We store one exception to stop excessive logging
Timber.i(ex, "deleteNotesWithWrongFieldCounts - Exception on row %d. Columns: %d", currentRow, cur.getColumnCount());
if (firstException == null) {
String details = String.format(Locale.ROOT, "deleteNotesWithWrongFieldCounts row: %d col: %d", currentRow, cur.getColumnCount());
AnkiDroidApp.sendExceptionReport(ex, details);
firstException = ex;
}
}
currentRow++;
}
Timber.i("deleteNotesWithWrongFieldCounts - completed successfully");
notifyProgress.run();
if (ids.size() > 0) {
problems.add("Deleted " + ids.size() + " note(s) with wrong field count.");
_remNotes(ids);
}
} finally {
if (cur != null && !cur.isClosed()) {
cur.close();
}
}
return problems;
}
Aggregations