private synchronized void trim() { for (int i = 0; i < 3; ++i) { if (maxSize == 0 || size <= maxSize) return; LinkedList<String> files = database.getFilesForTrim(size - maxSize); while (size > maxSize) { File oldest = null; for (ListIterator<String> it = files.listIterator(); it.hasNext(); ) { File file = pathToFile(it.next()); if (isPageFile(file) && pagesSize < maxPagesSize) continue; it.remove(); oldest = file; break; } if (oldest == null) { Logger.e(TAG, "No files to trim"); break; } else { Logger.d(TAG, "Deleting " + oldest.getPath()); if (!delete(oldest)) { Logger.e(TAG, "Cannot delete cache file: " + oldest.getPath()); break; } } } } }
private void makeDir() { if (!directory.exists()) { if (!directory.mkdirs()) { Logger.e(TAG, "Unable to create file cache dir " + directory.getPath()); } } }
private void makeNomedia() { try { pathToFile(NOMEDIA).createNewFile(); } catch (Exception e) { Logger.e(TAG, "couldn't create .nomedia file", e); } }
private View instantiate(String name, Context context, AttributeSet attrs) { try { Constructor<? extends View> constructor = CONSTRUCTOR_MAP.get(name); if (constructor == null) { Class<? extends View> clazz = null; if (name.indexOf('.') != -1) { clazz = context.getClassLoader().loadClass(name).asSubclass(View.class); } else { for (String prefix : CLASS_PREFIX_LIST) { try { clazz = context.getClassLoader().loadClass(prefix + name).asSubclass(View.class); break; } catch (ClassNotFoundException e) { } } if (clazz == null) throw new ClassNotFoundException("couldn't find class: " + name); } constructor = clazz.getConstructor(CONSTRUCTOR_SIGNATURE); CONSTRUCTOR_MAP.put(name, constructor); } Object[] args = constructorArgs; args[0] = context; args[1] = attrs; constructor.setAccessible(true); View view = constructor.newInstance(args); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && view instanceof ViewStub) CompatibilityImpl.setLayoutInflater((ViewStub) view, inflater.cloneInContext(context)); return view; } catch (Exception e) { Logger.e(TAG, "couldn't instantiate class " + name, e); return null; } }
public static void setCustomTheme(Context context, SparseIntArray customAttrs) { if (customAttrs == null || customAttrs.size() == 0) { currentInstance = null; return; } TypedValue tmp = new TypedValue(); context.getTheme().resolveAttribute(android.R.attr.textColorPrimary, tmp, true); int textColorPrimaryOriginal = (tmp.type >= TypedValue.TYPE_FIRST_COLOR_INT && tmp.type <= TypedValue.TYPE_LAST_COLOR_INT) ? tmp.data : Color.TRANSPARENT; int textColorPrimaryOverridden = customAttrs.get(android.R.attr.textColorPrimary, textColorPrimaryOriginal); try { processWindow(context, customAttrs, textColorPrimaryOriginal, textColorPrimaryOverridden); } catch (Exception e) { Logger.e(TAG, e); } currentInstance = new CustomThemeHelper( context, customAttrs, textColorPrimaryOriginal, textColorPrimaryOverridden); }
public SendPostModel deserializeDraft(String hash) { try { return deserialize(FileCache.PREFIX_DRAFTS + hash, SendPostModel.class); } catch (Exception e) { Logger.e(TAG, e); return null; } }
public SerializableBoardsList deserializeBoardsList(String hash) { try { return deserialize(FileCache.PREFIX_BOARDS + hash, SerializableBoardsList.class); } catch (Exception e) { Logger.e(TAG, e); return null; } }
public SerializablePage deserializePage(String hash) { try { return deserialize(FileCache.PREFIX_PAGES + hash, SerializablePage.class); } catch (Exception e) { Logger.e(TAG, e); return null; } }
private void ensureInitialized() { if (initialized) return; synchronized (initLock) { while (!initialized) { try { initLock.wait(); } catch (Exception e) { Logger.e(TAG, e); } } } }
private <T> T deserialize(File file, Class<T> type) { if (file == null || !file.exists()) { return null; } synchronized (serializeLock) { Input input = null; try { input = new Input(new FileInputStream(file)); return kryo.readObject(input, type); } catch (Exception e) { Logger.e(TAG, e); } catch (OutOfMemoryError oom) { MainApplication.freeMemory(); Logger.e(TAG, oom); } finally { IOUtils.closeQuietly(input); } } return null; }
@Override public void run() { synchronized (serializeLock) { File file = fileCache.create(filename); Output output = null; try { output = isHoneycomb() ? new KryoOutputHC(new FileOutputStream(file)) : new Output(new FileOutputStream(file)); kryo.writeObject(output, obj); } catch (Exception e) { Logger.e(TAG, e); } catch (OutOfMemoryError oom) { MainApplication.freeMemory(); Logger.e(TAG, oom); } finally { IOUtils.closeQuietly(output); } fileCache.put(file); } }
public TabsState deserializeTabsState() { File file1 = fileCache.getImmediately(FileCache.TABS_FILENAME); File file2 = fileCache.getImmediately(FileCache.TABS_FILENAME_2); File[] files; if (file1 == null && file2 == null) files = new File[0]; else if (file1 == null) files = new File[] {file2}; else if (file2 == null) files = new File[] {file1}; else files = file1.lastModified() > file2.lastModified() ? new File[] {file2, file1} : new File[] {file1, file2}; for (File file : files) { try { TabsState obj = deserialize(file, TabsState.class); if (obj != null && obj.tabsArray != null && obj.tabsIdStack != null) return obj; } catch (Exception e) { Logger.e(TAG, e); } } return TabsState.obtainDefault(); }
private static void setLollipopMenuOverflowIconColor(final ViewGroup toolbar, final int color) { try { // for API 23 (Android 6): at this point method Toolbar.setOverflowIcon(Drawable) has no // effect toolbar.getClass().getMethod("getMenu").invoke(toolbar); AppearanceUtils.callWhenLoaded( toolbar, new Runnable() { @Override public void run() { try { final ViewGroup actionMenuView = (ViewGroup) findViewByClassName(toolbar, "android.widget.ActionMenuView"); Runnable setOverflowIcon = new Runnable() { @Override public void run() { try { Class<?> toolbarClass = toolbar.getClass(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { Drawable overflowIcon = (Drawable) toolbarClass.getMethod("getOverflowIcon").invoke(toolbar); setColorFilter(overflowIcon); toolbarClass .getMethod("setOverflowIcon", Drawable.class) .invoke(toolbar, overflowIcon); } else { ImageView overflowButton = (ImageView) findViewByClassName( actionMenuView, "android.widget.ActionMenuPresenter$OverflowMenuButton"); if (overflowButton != null) { Drawable overflowIcon = overflowButton.getDrawable(); setColorFilter(overflowIcon); overflowButton.setImageDrawable(overflowIcon); } } } catch (Exception e) { Logger.e(TAG, e); } } private void setColorFilter(Drawable overflowIcon) { overflowIcon.setColorFilter(color, PorterDuff.Mode.SRC_ATOP); } }; if (actionMenuView.getChildCount() == 0) { AppearanceUtils.callWhenLoaded( actionMenuView == null ? toolbar : actionMenuView, setOverflowIcon); } else { setOverflowIcon.run(); } } catch (Exception e) { Logger.e(TAG, e); } } private View findViewByClassName(ViewGroup group, String className) { for (int i = 0, size = group.getChildCount(); i < size; ++i) { View child = group.getChildAt(i); if (child.getClass().getName().equals(className)) { return child; } } return null; } }); } catch (Exception e) { Logger.e(TAG, e); } }
private static void processWindow( Context context, SparseIntArray attrs, int textColorPrimaryOriginal, int textColorPrimaryOverridden) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) return; boolean isLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; int materialPrimaryIndex = attrs.indexOfKey(R.attr.materialPrimary); int materialPrimaryDarkIndex = attrs.indexOfKey(R.attr.materialPrimaryDark); int materialNavigationBarIndex = attrs.indexOfKey(R.attr.materialNavigationBar); boolean overrideActionbarColor = materialPrimaryIndex >= 0; boolean overridePanelsColor = Math.max(materialPrimaryDarkIndex, materialNavigationBarIndex) >= 0; boolean overrideTextColor = textColorPrimaryOriginal != textColorPrimaryOverridden; if (!overrideTextColor && !overrideActionbarColor && !overridePanelsColor) return; Window window = ((Activity) context).getWindow(); final View decorView = window.getDecorView(); Resources resources = context.getResources(); if (overrideActionbarColor) { try { Drawable background = new ColorDrawable(attrs.valueAt(materialPrimaryIndex)); Object actionBar = context.getClass().getMethod("getActionBar").invoke(context); actionBar .getClass() .getMethod("setBackgroundDrawable", Drawable.class) .invoke(actionBar, background); } catch (Exception e) { Logger.e(TAG, e); } } if (overrideTextColor) { int id = resources.getIdentifier("action_bar_title", "id", "android"); if (id != 0) { View v = decorView.findViewById(id); if (v instanceof TextView) ((TextView) v).setTextColor(textColorPrimaryOverridden); } } if (isLollipop && overrideTextColor) { try { int id = resources.getIdentifier("action_bar", "id", "android"); if (id == 0) throw new Exception("'android:id/action_bar' identifier not found"); View v = decorView.findViewById(id); if (v == null) throw new Exception("view with id 'android:id/action_bar' not found"); Class<?> toolbarClass = Class.forName("android.widget.Toolbar"); if (!toolbarClass.isInstance(v)) throw new Exception( "view 'android:id/action_bar' is not instance of android.widget.Toolbar"); toolbarClass .getMethod("setTitleTextColor", int.class) .invoke(v, textColorPrimaryOverridden); setLollipopMenuOverflowIconColor((ViewGroup) v, textColorPrimaryOverridden); } catch (Exception e) { Logger.e(TAG, e); } } if (isLollipop && overridePanelsColor) { try { if (materialPrimaryDarkIndex >= 0) { window .getClass() .getMethod("setStatusBarColor", int.class) .invoke(window, attrs.valueAt(materialPrimaryDarkIndex)); } if (materialNavigationBarIndex >= 0) { window .getClass() .getMethod("setNavigationBarColor", int.class) .invoke(window, attrs.valueAt(materialNavigationBarIndex)); } } catch (Exception e) { Logger.e(TAG, e); } } }
@Override public View onCreateView(View parent, String name, Context context, AttributeSet attrs) { int mappingCount = 0; if (attrs != null) { for (int i = 0, size = attrs.getAttributeCount(); i < size; ++i) { String value = attrs.getAttributeValue(i); if (!value.startsWith("?")) continue; int attrId = resources.getIdentifier( value.substring(1), null, null); // Integer.parseInt(value.substring(1)); if (attrId == 0) { Logger.e(TAG, "couldn't get id for attribute: " + value); continue; } int index = customAttrs.indexOfKey(attrId); if (index >= 0) { mappingKeys[mappingCount] = attrs.getAttributeNameResource(i); mappingValues[mappingCount] = customAttrs.valueAt(index); ++mappingCount; } } } if (mappingCount == 0 && textColorPrimaryOverridden == textColorPrimaryOriginal) return null; View view = instantiate(name, context, attrs); if (view == null) return null; boolean shouldOverrideTextColor = textColorPrimaryOverridden != textColorPrimaryOriginal && view instanceof TextView; for (int i = 0; i < mappingCount; ++i) { switch (mappingKeys[i]) { case android.R.attr.background: view.setBackgroundColor(mappingValues[i]); break; case android.R.attr.textColor: if (view instanceof TextView) { ((TextView) view).setTextColor(mappingValues[i]); shouldOverrideTextColor = false; } else { Logger.e( TAG, "couldn't apply attribute 'textColor' on class " + name + " (not instance of TextView)"); } break; case android.R.attr.divider: if (view instanceof ListView) { ListView listView = (ListView) view; int dividerHeight = listView.getDividerHeight(); listView.setDivider(new ColorDrawable(mappingValues[i])); listView.setDividerHeight(dividerHeight); } else { Logger.e( TAG, "couldn't apply attribute 'divider' on class " + name + " (not instance of ListView)"); } break; default: String attrResName = null; try { attrResName = resources.getResourceName(mappingKeys[i]); } catch (Exception e) { attrResName = Integer.toString(mappingKeys[i]); } Logger.e(TAG, "couldn't apply attribure '" + attrResName + "' on class " + name); } } if (shouldOverrideTextColor) { TextView tv = (TextView) view; if (tv.getCurrentTextColor() == textColorPrimaryOriginal) { tv.setTextColor(textColorPrimaryOverridden); } } return view; }
@Override public void handle(final Activity activity, final CancellableTask task, final Callback callback) { try { final HttpClient httpClient = MainApplication.getInstance().getChanModule(chanName).getHttpClient(); final String usingURL = scheme + RECAPTCHA_FALLBACK_URL + publicKey; Header[] customHeaders = new Header[] {new BasicHeader(HttpHeaders.REFERER, usingURL)}; String htmlChallenge = HttpStreamer.getInstance() .getStringFromUrl( usingURL, HttpRequestModel.builder().setGET().setCustomHeaders(customHeaders).build(), httpClient, null, task, false); Matcher challengeMatcher = Pattern.compile("name=\"c\" value=\"([\\w-]+)").matcher(htmlChallenge); if (challengeMatcher.find()) { final String challenge = challengeMatcher.group(1); HttpResponseModel responseModel = HttpStreamer.getInstance() .getFromUrl( scheme + RECAPTCHA_IMAGE_URL + challenge + "&k=" + publicKey, HttpRequestModel.builder().setGET().build(), httpClient, null, task); try { InputStream imageStream = responseModel.stream; final Bitmap challengeBitmap = BitmapFactory.decodeStream(imageStream); final String message; Matcher messageMatcher = Pattern.compile("imageselect-message(?:.*?)>(.*?)</div>").matcher(htmlChallenge); if (messageMatcher.find()) message = messageMatcher.group(1).replaceAll("<[^>]*>", ""); else message = null; final Bitmap candidateBitmap; Matcher candidateMatcher = Pattern.compile( "fbc-imageselect-candidates(?:.*?)src=\"data:image/(?:.*?);base64,([^\"]*)\"") .matcher(htmlChallenge); if (candidateMatcher.find()) { Bitmap bmp = null; try { byte[] imgData = Base64.decode(candidateMatcher.group(1), Base64.DEFAULT); bmp = BitmapFactory.decodeByteArray(imgData, 0, imgData.length); } catch (Exception e) { } candidateBitmap = bmp; } else candidateBitmap = null; activity.runOnUiThread( new Runnable() { final int maxX = 3; final int maxY = 3; final boolean[] isSelected = new boolean[maxX * maxY]; @SuppressLint("InlinedApi") @Override public void run() { LinearLayout rootLayout = new LinearLayout(activity); rootLayout.setOrientation(LinearLayout.VERTICAL); if (candidateBitmap != null) { ImageView candidateView = new ImageView(activity); candidateView.setImageBitmap(candidateBitmap); int picSize = (int) (activity.getResources().getDisplayMetrics().density * 50 + 0.5f); candidateView.setLayoutParams(new LinearLayout.LayoutParams(picSize, picSize)); candidateView.setScaleType(ImageView.ScaleType.FIT_XY); rootLayout.addView(candidateView); } if (message != null) { TextView textView = new TextView(activity); textView.setText(message); textView.setTextAppearance(activity, android.R.style.TextAppearance); textView.setLayoutParams( new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); rootLayout.addView(textView); } FrameLayout frame = new FrameLayout(activity); frame.setLayoutParams( new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); final ImageView imageView = new ImageView(activity); imageView.setLayoutParams( new FrameLayout.LayoutParams( FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)); imageView.setScaleType(ImageView.ScaleType.FIT_XY); imageView.setImageBitmap(challengeBitmap); frame.addView(imageView); final LinearLayout selector = new LinearLayout(activity); selector.setLayoutParams( new FrameLayout.LayoutParams( FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)); AppearanceUtils.callWhenLoaded( imageView, new Runnable() { @Override public void run() { selector.setLayoutParams( new FrameLayout.LayoutParams( imageView.getWidth(), imageView.getHeight())); } }); selector.setOrientation(LinearLayout.VERTICAL); selector.setWeightSum(maxY); for (int y = 0; y < maxY; ++y) { LinearLayout subSelector = new LinearLayout(activity); subSelector.setLayoutParams( new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, 0, 1f)); subSelector.setOrientation(LinearLayout.HORIZONTAL); subSelector.setWeightSum(maxX); for (int x = 0; x < maxX; ++x) { FrameLayout switcher = new FrameLayout(activity); switcher.setLayoutParams( new LinearLayout.LayoutParams( 0, LinearLayout.LayoutParams.MATCH_PARENT, 1f)); switcher.setTag(new int[] {x, y}); switcher.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { int[] coord = (int[]) v.getTag(); int index = coord[1] * maxX + coord[0]; isSelected[index] = !isSelected[index]; v.setBackgroundColor( isSelected[index] ? Color.argb(128, 0, 255, 0) : Color.TRANSPARENT); } }); subSelector.addView(switcher); } selector.addView(subSelector); } frame.addView(selector); rootLayout.addView(frame); Button checkButton = new Button(activity); checkButton.setLayoutParams( new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); checkButton.setText(android.R.string.ok); rootLayout.addView(checkButton); ScrollView dlgView = new ScrollView(activity); dlgView.addView(rootLayout); final Dialog dialog = new Dialog(activity); dialog.setTitle("Recaptcha"); dialog.setContentView(dlgView); dialog.setCanceledOnTouchOutside(false); dialog.setOnCancelListener( new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { if (!task.isCancelled()) { callback.onError("Cancelled"); } } }); dialog .getWindow() .setLayout( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); dialog.show(); checkButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); if (task.isCancelled()) return; PriorityThreadFactory.LOW_PRIORITY_FACTORY .newThread( new Runnable() { @Override public void run() { try { List<NameValuePair> pairs = new ArrayList<NameValuePair>(); pairs.add(new BasicNameValuePair("c", challenge)); for (int i = 0; i < isSelected.length; ++i) if (isSelected[i]) pairs.add( new BasicNameValuePair( "response", Integer.toString(i))); HttpRequestModel request = HttpRequestModel.builder() .setPOST( new UrlEncodedFormEntityHC4(pairs, "UTF-8")) .setCustomHeaders( new Header[] { new BasicHeader(HttpHeaders.REFERER, usingURL) }) .build(); String response = HttpStreamer.getInstance() .getStringFromUrl( usingURL, request, httpClient, null, task, false); String hash = ""; Matcher matcher = Pattern.compile( "fbc-verification-token(?:.*?)<textarea[^>]*>([^<]*)<", Pattern.DOTALL) .matcher(response); if (matcher.find()) hash = matcher.group(1); if (hash.length() > 0) { Recaptcha2solved.push(publicKey, hash); activity.runOnUiThread( new Runnable() { @Override public void run() { callback.onSuccess(); } }); } else { throw new RecaptchaException( "incorrect answer (hash is empty)"); } } catch (final Exception e) { Logger.e(TAG, e); if (task.isCancelled()) return; handle(activity, task, callback); } } }) .start(); } }); } }); } finally { responseModel.release(); } } else throw new Exception("can't parse recaptcha challenge answer"); } catch (final Exception e) { Logger.e(TAG, e); if (!task.isCancelled()) { activity.runOnUiThread( new Runnable() { @Override public void run() { callback.onError(e.getMessage() != null ? e.getMessage() : e.toString()); } }); } } }