Merge pull request
3
.gitmodules
vendored
|
@ -7,9 +7,6 @@
|
|||
[submodule "ShowcaseView"]
|
||||
path = ShowcaseView
|
||||
url = https://github.com/amlcurran/ShowcaseView.git
|
||||
[submodule "android-HoloCircularProgressBar"]
|
||||
path = android-HoloCircularProgressBar
|
||||
url = https://github.com/passsy/android-HoloCircularProgressBar.git
|
||||
[submodule "custom-tabs-client"]
|
||||
path = custom-tabs-client
|
||||
url = https://github.com/GoogleChrome/custom-tabs-client
|
||||
|
|
|
@ -38,37 +38,29 @@ android {
|
|||
}
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy {
|
||||
force 'com.android.support:support-v4:22.2.0'
|
||||
force 'com.android.support:appcompat-v7:22.2.0'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// core android studio module
|
||||
//compile project(':core')
|
||||
|
||||
// You must install or update the Google Repository through the SDK manager to use this dependency.
|
||||
// The Google Repository (separate from the corresponding library) can be found in the Extras category.
|
||||
// compile 'com.google.android.gms:play-services:4.2.42'
|
||||
compile files('src/main/libs/gson-2.2.4.jar')
|
||||
compile files('src/main/libs/jsoup-1.7.2.jar')
|
||||
compile project(':Changeloglib:ChangeLogLibrary')
|
||||
compile project(':ownCloud-Account-Importer')
|
||||
compile project(':ShowcaseView:library')
|
||||
compile project(':android-HoloCircularProgressBar:library')
|
||||
compile project(':customtabs')
|
||||
compile 'com.android.support:support-v4:22.2.0'
|
||||
compile 'com.android.support:appcompat-v7:22.2.0'
|
||||
compile 'com.android.support:design:22.2.0'
|
||||
compile 'de.mrmaffen:holocircularprogressbar:1.0.1'
|
||||
compile 'com.google.code.gson:gson:2.3.1'
|
||||
compile 'com.jakewharton:butterknife:5.1.+'
|
||||
compile 'com.squareup.picasso:picasso:2.3.1@jar'
|
||||
compile 'com.sothree.slidinguppanel:library:+'
|
||||
compile 'de.greenrobot:eventbus:2.2.1'
|
||||
compile 'de.greenrobot:greendao:1.3.7@jar'
|
||||
compile 'de.greenrobot:greendao-generator:1.3.1@jar'
|
||||
compile 'org.freemarker:freemarker:2.3.18@jar'
|
||||
|
||||
|
||||
compile 'org.apache.commons:commons-lang3:3.4'
|
||||
|
||||
testCompile 'org.robolectric:robolectric:3.0-rc3'
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
package de.luhmer.owncloudnewsreader.ListView;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
@ -551,6 +552,7 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter
|
|||
}
|
||||
|
||||
|
||||
@SuppressLint("NewApi") // wrongly reports setSelectionFromTop is only available in lollipop
|
||||
public void notifyCountDataSetChanged(SparseArray<String> unreadCountFolders, SparseArray<String> unreadCountFeeds, SparseArray<String> urlsToFavIcons, SparseArray<String> starredCountFeeds) {
|
||||
this.unreadCountFolders = unreadCountFolders;
|
||||
this.unreadCountFeeds = unreadCountFeeds;
|
||||
|
@ -585,4 +587,4 @@ public class SubscriptionExpandableListAdapter extends BaseExpandableListAdapter
|
|||
if(eListTextClickHandler != null)
|
||||
eListTextClickHandler.onTextClicked(idFeed, context, isFolder, optional_folder_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
package de.luhmer.owncloudnewsreader;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.SharedPreferences;
|
||||
|
@ -35,6 +36,8 @@ import android.text.InputType;
|
|||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
|
@ -46,14 +49,12 @@ import java.net.URL;
|
|||
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.InjectView;
|
||||
import butterknife.OnClick;
|
||||
import de.luhmer.owncloud.accountimporter.ImportAccountsDialogFragment;
|
||||
import de.luhmer.owncloud.accountimporter.helper.AccountImporter;
|
||||
import de.luhmer.owncloud.accountimporter.helper.OwnCloudAccount;
|
||||
import de.luhmer.owncloud.accountimporter.interfaces.IAccountImport;
|
||||
import de.luhmer.owncloudnewsreader.authentication.AuthenticatorActivity;
|
||||
import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm;
|
||||
import de.luhmer.owncloudnewsreader.helper.FontHelper;
|
||||
import de.luhmer.owncloudnewsreader.reader.owncloud.OwnCloudReaderMethods;
|
||||
|
||||
/**
|
||||
|
@ -81,6 +82,7 @@ public class LoginDialogFragment extends DialogFragment implements IAccountImpor
|
|||
private String mPassword;
|
||||
private String mOc_root_path;
|
||||
private boolean mCbDisableHostnameVerification;
|
||||
private boolean showImportAccountButton;
|
||||
|
||||
// UI references.
|
||||
@InjectView(R.id.username) EditText mUsernameView;
|
||||
|
@ -122,6 +124,7 @@ public class LoginDialogFragment extends DialogFragment implements IAccountImpor
|
|||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
showImportAccountButton = AccountImporter.findAccounts(getActivity()).size() > 0;
|
||||
|
||||
//setRetainInstance(true);
|
||||
|
||||
|
@ -131,11 +134,14 @@ public class LoginDialogFragment extends DialogFragment implements IAccountImpor
|
|||
View view = inflater.inflate(R.layout.dialog_signin, null);
|
||||
ButterKnife.inject(this, view);
|
||||
|
||||
builder.setView(view).setTitle(getString(R.string.action_sign_in_short));
|
||||
builder.setView(view);
|
||||
builder.setTitle(getString(R.string.action_sign_in_short));
|
||||
|
||||
FontHelper fHelper = new FontHelper(getActivity());
|
||||
fHelper.setFontForAllChildren(view, fHelper.getFont());
|
||||
builder.setPositiveButton(getString(R.string.action_sign_in_short), null);
|
||||
|
||||
if(showImportAccountButton) {
|
||||
builder.setNeutralButton(getString(R.string.import_account), null);
|
||||
}
|
||||
|
||||
mImageViewShowPwd.setOnClickListener(ImgViewShowPasswordListener);
|
||||
|
||||
|
@ -161,22 +167,46 @@ public class LoginDialogFragment extends DialogFragment implements IAccountImpor
|
|||
}
|
||||
});
|
||||
|
||||
AlertDialog dialog = builder.create();
|
||||
// Set dialog to resize when soft keyboard pops up
|
||||
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
|
||||
|
||||
view.findViewById(R.id.btn_importAccount).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
ImportAccountsDialogFragment.show(getActivity(), LoginDialogFragment.this);
|
||||
}
|
||||
});
|
||||
|
||||
if(AccountImporter.findAccounts(getActivity()).size() <= 0) {
|
||||
view.findViewById(R.id.btn_importAccount).setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
return builder.create();
|
||||
return dialog;
|
||||
}
|
||||
|
||||
private View.OnClickListener ImgViewShowPasswordListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
final AlertDialog dialog = (AlertDialog) getDialog();
|
||||
// Override the onClickListeners, as the default implementation would dismiss the dialog
|
||||
if (dialog != null) {
|
||||
if (showImportAccountButton) {
|
||||
Button neutralButton = dialog.getButton(DialogInterface.BUTTON_NEUTRAL);
|
||||
neutralButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
ImportAccountsDialogFragment.show(getActivity(), LoginDialogFragment.this);
|
||||
}
|
||||
});
|
||||
}
|
||||
Button positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
|
||||
positiveButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
attemptLogin();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
super.onCancel(dialog);
|
||||
if(mActivity instanceof AuthenticatorActivity)
|
||||
mActivity.finish();
|
||||
}
|
||||
|
||||
private View.OnClickListener ImgViewShowPasswordListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mPasswordVisible = !mPasswordVisible;
|
||||
|
@ -189,17 +219,6 @@ public class LoginDialogFragment extends DialogFragment implements IAccountImpor
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
@OnClick(R.id.btn_signin) void SignIn() {
|
||||
attemptLogin();
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_cancel) void Cancel() {
|
||||
LoginDialogFragment.this.getDialog().cancel();
|
||||
if(mActivity instanceof AuthenticatorActivity)
|
||||
mActivity.finish();
|
||||
}
|
||||
|
||||
private ProgressDialog BuildPendingDialogWhileLoggingIn()
|
||||
{
|
||||
ProgressDialog pDialog = new ProgressDialog(getActivity());
|
||||
|
|
|
@ -452,7 +452,7 @@ public class NewsDetailActivity extends PodcastFragmentActivity {
|
|||
|
||||
case R.id.action_tts:
|
||||
TTSItem ttsItem = new TTSItem(rssItem.getId(), rssItem.getTitle(), rssItem.getTitle() + "\n\n " + Html.fromHtml(rssItem.getBody()).toString(), rssItem.getFeed().getFaviconUrl());
|
||||
mPodcastPlaybackService.openTtsFeed(ttsItem);
|
||||
openTTSItem(ttsItem);
|
||||
break;
|
||||
|
||||
case R.id.action_ShareItem:
|
||||
|
|
|
@ -14,7 +14,6 @@ import android.os.Build;
|
|||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.SurfaceView;
|
||||
|
@ -44,6 +43,7 @@ import de.luhmer.owncloudnewsreader.helper.ImageHandler;
|
|||
import de.luhmer.owncloudnewsreader.helper.SizeAnimator;
|
||||
import de.luhmer.owncloudnewsreader.interfaces.IPlayPausePodcastClicked;
|
||||
import de.luhmer.owncloudnewsreader.model.PodcastItem;
|
||||
import de.luhmer.owncloudnewsreader.model.TTSItem;
|
||||
import de.luhmer.owncloudnewsreader.services.PodcastDownloadService;
|
||||
import de.luhmer.owncloudnewsreader.services.PodcastPlaybackService;
|
||||
import de.luhmer.owncloudnewsreader.view.PodcastSlidingUpPanelLayout;
|
||||
|
@ -110,13 +110,6 @@ public class PodcastFragmentActivity extends AppCompatActivity implements IPlayP
|
|||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
// Bind to LocalService
|
||||
Intent intent = new Intent(this, PodcastPlaybackService.class);
|
||||
if(!isMyServiceRunning(PodcastPlaybackService.class)) {
|
||||
startService(intent);
|
||||
}
|
||||
|
||||
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -551,6 +544,34 @@ public class PodcastFragmentActivity extends AppCompatActivity implements IPlayP
|
|||
return px;
|
||||
}
|
||||
|
||||
private void openPodcast(PodcastItem podcastItem) {
|
||||
// Bind to LocalService
|
||||
Intent intent = new Intent(this, PodcastPlaybackService.class);
|
||||
if(!isMyServiceRunning(PodcastPlaybackService.class)) {
|
||||
intent.putExtra(PodcastPlaybackService.PODCAST_ITEM, podcastItem);
|
||||
startService(intent);
|
||||
} else {
|
||||
mPodcastPlaybackService.openFile(podcastItem);
|
||||
loadPodcastFavIcon();
|
||||
}
|
||||
|
||||
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
protected void openTTSItem(TTSItem ttsItem) {
|
||||
// Bind to LocalService
|
||||
Intent intent = new Intent(this, PodcastPlaybackService.class);
|
||||
if(!isMyServiceRunning(PodcastPlaybackService.class)) {
|
||||
intent.putExtra(PodcastPlaybackService.TTS_ITEM, ttsItem);
|
||||
startService(intent);
|
||||
} else {
|
||||
mPodcastPlaybackService.openTtsFeed(ttsItem);
|
||||
loadPodcastFavIcon();
|
||||
}
|
||||
|
||||
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openPodcast(final RssItem rssItem) {
|
||||
final PodcastItem podcastItem = DatabaseConnectionOrm.ParsePodcastItemFromRssItem(this, rssItem);
|
||||
|
@ -559,8 +580,7 @@ public class PodcastFragmentActivity extends AppCompatActivity implements IPlayP
|
|||
if(file.exists()) {
|
||||
podcastItem.link = file.getAbsolutePath();
|
||||
|
||||
mPodcastPlaybackService.openFile(podcastItem);
|
||||
loadPodcastFavIcon();// Picasso.with(this).load(rssItem.getFeed().getFaviconUrl()).into(mPodcastFragment.imgFavIcon);
|
||||
openPodcast(podcastItem);
|
||||
} else if(!podcastItem.offlineCached) {
|
||||
|
||||
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this)
|
||||
|
@ -581,9 +601,7 @@ public class PodcastFragmentActivity extends AppCompatActivity implements IPlayP
|
|||
alertDialog.setPositiveButton("Stream", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
mPodcastPlaybackService.openFile(podcastItem);
|
||||
//Picasso.with(PodcastFragmentActivity.this).load(rssItem.getFeed().getFaviconUrl()).into(mPodcastFragment.imgFavIcon);
|
||||
loadPodcastFavIcon();
|
||||
openPodcast(podcastItem);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.DecimalFormat;
|
||||
|
@ -655,29 +656,30 @@ public class SettingsActivity extends PreferenceActivity {
|
|||
protected Boolean doInBackground(Void... params) {
|
||||
DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(_mActivity);
|
||||
dbConn.resetDatabase();
|
||||
boolean success = ImageHandler.clearCache(_mActivity);
|
||||
new GetCacheSizeAsync().execute((Void)null);
|
||||
return success;
|
||||
return ImageHandler.clearCache(_mActivity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
pd.dismiss();
|
||||
if(result)
|
||||
LoginDialogFragment.ShowAlertDialog("Information" , "Cache is cleared!", _mActivity);
|
||||
new GetCacheSizeAsync().execute((Void) null);
|
||||
pd.dismiss();
|
||||
String resultString;
|
||||
if(result)
|
||||
resultString = context.getString(R.string.cache_is_cleared);
|
||||
else
|
||||
LoginDialogFragment.ShowAlertDialog("Information", context.getString(R.string.login_dialog_text_something_went_wrong), _mActivity);
|
||||
resultString = context.getString(R.string.login_dialog_text_something_went_wrong);
|
||||
Toast.makeText(context, resultString, Toast.LENGTH_SHORT).show();
|
||||
super.onPostExecute(result);
|
||||
};
|
||||
}
|
||||
|
||||
public static class GetCacheSizeAsync extends AsyncTask<Void, Void, Void> {
|
||||
|
||||
String mSize = "0MB";
|
||||
String mCount = "0 Files";
|
||||
int count = 0;
|
||||
long size = 0;
|
||||
DecimalFormat dcmFormat = new DecimalFormat("#.##");
|
||||
private String mSize = "0MB";
|
||||
private String mCount;
|
||||
private int count = 0;
|
||||
private long size = 0;
|
||||
private DecimalFormat dcmFormat = new DecimalFormat("#.##");
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
|
@ -685,11 +687,12 @@ public class SettingsActivity extends PreferenceActivity {
|
|||
{
|
||||
getFolderSize(new File(FileUtils.getPath(_mActivity)));
|
||||
mSize = dcmFormat.format(size / 1024d / 1024d) + "MB";
|
||||
mCount = String.valueOf(count) + " Files";
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
} finally {
|
||||
mCount = _mActivity.getResources().getQuantityString(R.plurals.number_of_files,count,count);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ public class GetImageThreaded extends Thread
|
|||
|
||||
DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(cont);
|
||||
Feed feed = dbConn.getFeedById(ThreadId);
|
||||
if(!cacheFile.isFile() || feed.getAvgColour() == null)
|
||||
if(!cacheFile.isFile() || (feed != null && feed.getAvgColour() == null))
|
||||
{
|
||||
File dir = new File(rootPath);
|
||||
dir.mkdirs();
|
||||
|
|
|
@ -429,7 +429,7 @@ public class DatabaseConnectionOrm {
|
|||
String whereStatement = getAllItemsIdsForFolderSQL(ID_FOLDER, onlyUnread, sortDirection);
|
||||
whereStatement = whereStatement.replace("SELECT " + RssItemDao.Properties.Id.columnName + " FROM " + RssItemDao.TABLENAME, "");
|
||||
whereStatement += " LIMIT " + limit;
|
||||
return daoSession.getRssItemDao().queryRaw(whereStatement, null);
|
||||
return daoSession.getRssItemDao().queryRaw(whereStatement, (String)null);
|
||||
}
|
||||
|
||||
public String getAllItemsIdsForFolderSQL(long ID_FOLDER, boolean onlyUnread, SORT_DIRECTION sortDirection) {
|
||||
|
|
|
@ -1,117 +0,0 @@
|
|||
/**
|
||||
* Android ownCloud News
|
||||
*
|
||||
* @author David Luhmer
|
||||
* @copyright 2013 David Luhmer david-dev@live.de
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package de.luhmer.owncloudnewsreader.helper;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.http.AndroidHttpClient;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* Created by David on 24.05.13.
|
||||
*/
|
||||
public class BitmapDownloaderTask extends AsyncTask<String, Void, Drawable> {
|
||||
//private String url;
|
||||
private final WeakReference<ImageView> imageViewReference;
|
||||
|
||||
public BitmapDownloaderTask(ImageView imageView) {
|
||||
imageViewReference = new WeakReference<ImageView>(imageView);
|
||||
}
|
||||
|
||||
@Override
|
||||
// Actual download method, run in the task thread
|
||||
protected Drawable doInBackground(String... params) {
|
||||
// params comes from the execute() call: params[0] is the url.
|
||||
//return downloadBitmap(params[0]);
|
||||
return ImageHandler.LoadImageFromWebOperations(params[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
// Once the image is downloaded, associates it to the imageView
|
||||
protected void onPostExecute(Drawable bitmap) {
|
||||
if (isCancelled()) {
|
||||
bitmap = null;
|
||||
}
|
||||
|
||||
if (imageViewReference != null) {
|
||||
ImageView imageView = imageViewReference.get();
|
||||
if (imageView != null) {
|
||||
imageView.setImageDrawable(bitmap);
|
||||
//imageView.setImageBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.FROYO)
|
||||
static Bitmap downloadBitmap(String url) {
|
||||
final AndroidHttpClient client = AndroidHttpClient.newInstance("Android");
|
||||
final HttpGet getRequest = new HttpGet(url);
|
||||
|
||||
|
||||
try {
|
||||
HttpResponse response = client.execute(getRequest);
|
||||
final int statusCode = response.getStatusLine().getStatusCode();
|
||||
if (statusCode != HttpStatus.SC_OK) {
|
||||
Log.d("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url);
|
||||
return null;
|
||||
}
|
||||
|
||||
final HttpEntity entity = response.getEntity();
|
||||
if (entity != null) {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = entity.getContent();
|
||||
final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
|
||||
return bitmap;
|
||||
} finally {
|
||||
if (inputStream != null) {
|
||||
inputStream.close();
|
||||
}
|
||||
entity.consumeContent();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Could provide a more explicit error message for IOException or IllegalStateException
|
||||
getRequest.abort();
|
||||
Log.d("ImageDownloader", "Error while retrieving bitmap from " + url);
|
||||
} finally {
|
||||
if (client != null) {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,11 @@
|
|||
package de.luhmer.owncloudnewsreader.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Created by David on 10.01.2015.
|
||||
*/
|
||||
public class TTSItem {
|
||||
public class TTSItem implements Serializable {
|
||||
|
||||
public TTSItem() {
|
||||
|
||||
|
|
|
@ -25,25 +25,24 @@ import android.annotation.SuppressLint;
|
|||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.auth.AuthenticationException;
|
||||
import org.apache.http.client.utils.URLEncodedUtils;
|
||||
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import android.util.Base64;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
|
@ -56,17 +55,17 @@ import de.luhmer.owncloudnewsreader.SettingsActivity;
|
|||
import de.luhmer.owncloudnewsreader.reader.owncloud.API;
|
||||
import de.luhmer.owncloudnewsreader.ssl.MemorizingTrustManager;
|
||||
import de.luhmer.owncloudnewsreader.ssl.TLSSocketFactory;
|
||||
import de.luhmer.owncloudnewsreader.util.Base64;
|
||||
|
||||
public class HttpJsonRequest {
|
||||
//private static final String TAG = "HttpJsonRequest";
|
||||
|
||||
//@TargetApi(Build.VERSION_CODES.GINGERBREAD)
|
||||
@SuppressLint("DefaultLocale")
|
||||
public static InputStream PerformJsonRequest(String urlString, List<NameValuePair> nameValuePairs, final String username, final String password, Context context) throws AuthenticationException, Exception
|
||||
public static InputStream PerformJsonRequest(String urlString, HashMap<String,String> nameValuePairs, final String username, final String password, Context context) throws Exception
|
||||
{
|
||||
if(nameValuePairs != null)
|
||||
urlString += "&" + URLEncodedUtils.format(nameValuePairs, "utf-8");
|
||||
if(nameValuePairs != null) {
|
||||
urlString += getUrlEncodedString(nameValuePairs);
|
||||
}
|
||||
|
||||
URL url = new URL(API.validateURL(urlString));
|
||||
|
||||
|
@ -114,15 +113,20 @@ public class HttpJsonRequest {
|
|||
if(HttpResult == HttpURLConnection.HTTP_OK) {
|
||||
return urlConnection.getInputStream();
|
||||
} else {
|
||||
if(urlConnection.getResponseMessage().equals("Unauthorized"))
|
||||
throw new AuthenticationException(urlConnection.getResponseMessage());
|
||||
else
|
||||
throw new Exception(urlConnection.getResponseMessage());
|
||||
throw new Exception(urlConnection.getResponseMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static String getUrlEncodedString(HashMap<String, String> nameValuePairs) throws UnsupportedEncodingException {
|
||||
String urlString = "";
|
||||
for(Entry<String,String> entry: nameValuePairs.entrySet()) {
|
||||
urlString += String.format("&%s=%s", URLEncoder.encode(entry.getKey(), "UTF-8"), URLEncoder.encode(entry.getValue(), "UTF-8"));
|
||||
}
|
||||
return urlString;
|
||||
}
|
||||
|
||||
private static HttpURLConnection getUrlConnection(URL url, Context context, String username, String password) throws IOException, KeyManagementException, NoSuchAlgorithmException {
|
||||
|
||||
private static HttpURLConnection getUrlConnection(URL url, Context context, String username, String password) throws IOException, KeyManagementException, NoSuchAlgorithmException {
|
||||
URLConnection urlConnection = url.openConnection();
|
||||
|
||||
// If https is used, use MemorizingTrustManager for certificate verification
|
||||
|
@ -177,13 +181,18 @@ public class HttpJsonRequest {
|
|||
// (this still shows a certification dialog, which requires user interaction!)
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if(sp.getBoolean(SettingsActivity.CB_DISABLE_HOSTNAME_VERIFICATION_STRING, false))
|
||||
httpsURLConnection.setHostnameVerifier(new AllowAllHostnameVerifier());
|
||||
httpsURLConnection.setHostnameVerifier(new HostnameVerifier() {
|
||||
@Override
|
||||
public boolean verify(String hostname, SSLSession session) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
else
|
||||
httpsURLConnection.setHostnameVerifier(HttpsURLConnection.getDefaultHostnameVerifier());
|
||||
}
|
||||
|
||||
if(username != null && password != null)
|
||||
urlConnection.setRequestProperty("Authorization", "Basic " + Base64.encode((username + ":" + password).getBytes()));
|
||||
urlConnection.setRequestProperty("Authorization", "Basic " + Base64.encodeToString((username + ":" + password).getBytes(),Base64.DEFAULT));
|
||||
|
||||
return (HttpURLConnection) urlConnection;
|
||||
}
|
||||
|
@ -221,11 +230,10 @@ public class HttpJsonRequest {
|
|||
*/
|
||||
|
||||
public static int performCreateFeedRequest(String urlString, String username, String password, Context context, String feedUrl, long folderId) throws Exception {
|
||||
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
|
||||
nameValuePairs.add(new BasicNameValuePair("url", feedUrl));
|
||||
nameValuePairs.add(new BasicNameValuePair("folderId", String.valueOf(folderId)));
|
||||
if(nameValuePairs != null)
|
||||
urlString += "&" + URLEncodedUtils.format(nameValuePairs, "utf-8");
|
||||
HashMap<String,String> nameValuePairs = new HashMap<>();
|
||||
nameValuePairs.put("url", feedUrl);
|
||||
nameValuePairs.put("folderId", String.valueOf(folderId));
|
||||
urlString += getUrlEncodedString(nameValuePairs);
|
||||
|
||||
|
||||
URL url = new URL(API.validateURL(urlString));
|
||||
|
|
|
@ -58,7 +58,7 @@ public class AsyncTask_GetItems extends AsyncTask_Reader {
|
|||
|
||||
@Override
|
||||
protected void onProgressUpdate(Void... values) {
|
||||
Toast.makeText(context, "Fetched " + totalCount + " items so far..", Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(context, context.getResources().getQuantityString(R.plurals.fetched_items_so_far,totalCount,totalCount), Toast.LENGTH_SHORT).show();
|
||||
|
||||
super.onProgressUpdate(values);
|
||||
}
|
||||
|
|
|
@ -26,9 +26,6 @@ import android.content.Context;
|
|||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonToken;
|
||||
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.auth.AuthenticationException;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
@ -36,7 +33,6 @@ import org.json.JSONObject;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
@ -56,19 +52,19 @@ public class OwnCloudReaderMethods {
|
|||
|
||||
public static int[] GetUpdatedItems(TAGS tag, Context cont, long lastSync, API api) throws Exception
|
||||
{
|
||||
List<NameValuePair> nVPairs = new ArrayList<NameValuePair>();
|
||||
//nVPairs.add(new BasicNameValuePair("batchSize", maxSizePerSync));
|
||||
HashMap<String,String> nVPairs = new HashMap<>();
|
||||
//nVPairs.put("batchSize", maxSizePerSync));
|
||||
if(tag.equals(TAGS.ALL_STARRED))
|
||||
{
|
||||
nVPairs.add(new BasicNameValuePair("type", "2"));
|
||||
nVPairs.add(new BasicNameValuePair("id", "0"));
|
||||
nVPairs.put("type", "2");
|
||||
nVPairs.put("id", "0");
|
||||
}
|
||||
else if(tag.equals(TAGS.ALL))
|
||||
{
|
||||
nVPairs.add(new BasicNameValuePair("type", "3"));
|
||||
nVPairs.add(new BasicNameValuePair("id", "0"));
|
||||
nVPairs.put("type", "3");
|
||||
nVPairs.put("id", "0");
|
||||
}
|
||||
nVPairs.add(new BasicNameValuePair("lastModified", String.valueOf(lastSync)));
|
||||
nVPairs.put("lastModified", String.valueOf(lastSync));
|
||||
|
||||
|
||||
InputStream is = HttpJsonRequest.PerformJsonRequest(api.getItemUpdatedUrl(), nVPairs, api.getUsername(), api.getPassword(), cont);
|
||||
|
@ -89,23 +85,23 @@ public class OwnCloudReaderMethods {
|
|||
//"type": 1, // the type of the query (Feed: 0, Folder: 1, Starred: 2, All: 3)
|
||||
public static int GetItems(TAGS tag, Context cont, String offset, boolean getRead, String id, String type, API api) throws Exception
|
||||
{
|
||||
List<NameValuePair> nVPairs = new ArrayList<NameValuePair>();
|
||||
nVPairs.add(new BasicNameValuePair("batchSize", maxSizePerSync));
|
||||
HashMap<String,String> nVPairs = new HashMap<>();
|
||||
nVPairs.put("batchSize", maxSizePerSync);
|
||||
if(tag.equals(TAGS.ALL_STARRED))
|
||||
{
|
||||
nVPairs.add(new BasicNameValuePair("type", type));
|
||||
nVPairs.add(new BasicNameValuePair("id", id));
|
||||
nVPairs.put("type", type);
|
||||
nVPairs.put("id", id);
|
||||
}
|
||||
else if(tag.equals(TAGS.ALL))
|
||||
{
|
||||
nVPairs.add(new BasicNameValuePair("type", type));
|
||||
nVPairs.add(new BasicNameValuePair("id", id));
|
||||
nVPairs.put("type", type);
|
||||
nVPairs.put("id", id);
|
||||
}
|
||||
nVPairs.add(new BasicNameValuePair("offset", offset));
|
||||
nVPairs.put("offset", offset);
|
||||
if(getRead)
|
||||
nVPairs.add(new BasicNameValuePair("getRead", "true"));
|
||||
nVPairs.put("getRead", "true");
|
||||
else
|
||||
nVPairs.add(new BasicNameValuePair("getRead", "false"));
|
||||
nVPairs.put("getRead", "false");
|
||||
|
||||
|
||||
InputStream is = HttpJsonRequest.PerformJsonRequest(api.getItemUrl(), nVPairs, api.getUsername(), api.getPassword(), cont);
|
||||
|
@ -370,7 +366,7 @@ public class OwnCloudReaderMethods {
|
|||
if(jsonIds != null)
|
||||
{
|
||||
nameValuePairs = new ArrayList<NameValuePair>();
|
||||
nameValuePairs.add(new BasicNameValuePair("itemIds", jsonIds));
|
||||
nameValuePairs.put("itemIds", jsonIds));
|
||||
}*/
|
||||
|
||||
if(tag.equals(TAGS.MARK_ITEM_AS_STARRED))
|
||||
|
@ -458,9 +454,6 @@ public class OwnCloudReaderMethods {
|
|||
} finally {
|
||||
is.close();
|
||||
}
|
||||
}
|
||||
catch(AuthenticationException ex) {
|
||||
throw ex;
|
||||
} catch(Exception ex) {//TODO GET HERE THE RIGHT EXCEPTION
|
||||
String requestUrl = oc_root_path + OwnCloudConstants.ROOT_PATH_APIv1 + OwnCloudConstants.VERSION_PATH + OwnCloudConstants.JSON_FORMAT;
|
||||
requestUrl = API.validateURL(requestUrl);
|
||||
|
|
|
@ -54,7 +54,8 @@ public class PodcastPlaybackService extends Service implements TextToSpeech.OnIn
|
|||
}
|
||||
|
||||
|
||||
|
||||
public static final String PODCAST_ITEM = "PODCAST_ITEM";
|
||||
public static final String TTS_ITEM = "TTS_ITEM";
|
||||
|
||||
private PodcastItem mCurrentlyPlayingPodcast;
|
||||
private TTSItem mCurrentlyPlayingTTS;
|
||||
|
@ -141,6 +142,13 @@ public class PodcastPlaybackService extends Service implements TextToSpeech.OnIn
|
|||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
if (intent != null) {
|
||||
if (intent.hasExtra(PODCAST_ITEM)) {
|
||||
openFile((PodcastItem) intent.getSerializableExtra(PODCAST_ITEM));
|
||||
} else if(intent.hasExtra(TTS_ITEM)) {
|
||||
openTtsFeed((TTSItem) intent.getSerializableExtra(TTS_ITEM));
|
||||
}
|
||||
}
|
||||
return Service.START_STICKY;
|
||||
}
|
||||
|
||||
|
|
|
@ -220,9 +220,9 @@ public class MemorizingTrustManager implements X509TrustManager {
|
|||
}
|
||||
try {
|
||||
ks.load(null, null);
|
||||
ks.load(new java.io.FileInputStream(keyStoreFile), "MTM".toCharArray());
|
||||
} catch (java.io.FileNotFoundException e) {
|
||||
Log.i(TAG, "getAppKeyStore(" + keyStoreFile + ") - file does not exist");
|
||||
if(keyStoreFile.canRead()) {
|
||||
ks.load(new java.io.FileInputStream(keyStoreFile), "MTM".toCharArray());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "getAppKeyStore(" + keyStoreFile + ")", e);
|
||||
}
|
||||
|
|
|
@ -1,570 +0,0 @@
|
|||
// Portions copyright 2002, Google, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package de.luhmer.owncloudnewsreader.util;
|
||||
|
||||
// This code was converted from code at http://iharder.sourceforge.net/base64/
|
||||
// Lots of extraneous features were removed.
|
||||
/* The original code said:
|
||||
* <p>
|
||||
* I am placing this code in the Public Domain. Do with it as you will.
|
||||
* This software comes with no guarantees or warranties but with
|
||||
* plenty of well-wishing instead!
|
||||
* Please visit
|
||||
* <a href="http://iharder.net/xmlizable">http://iharder.net/xmlizable</a>
|
||||
* periodically to check for updates or to contribute improvements.
|
||||
* </p>
|
||||
*
|
||||
* @author Robert Harder
|
||||
* @author rharder@usa.net
|
||||
* @version 1.3
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base64 converter class. This code is not a complete MIME encoder;
|
||||
* it simply converts binary data to base64 data and back.
|
||||
*
|
||||
* <p>Note {@link CharBase64} is a GWT-compatible implementation of this
|
||||
* class.
|
||||
*/
|
||||
public class Base64 {
|
||||
/** Specify encoding (value is {@code true}). */
|
||||
public final static boolean ENCODE = true;
|
||||
|
||||
/** Specify decoding (value is {@code false}). */
|
||||
public final static boolean DECODE = false;
|
||||
|
||||
/** The equals sign (=) as a byte. */
|
||||
private final static byte EQUALS_SIGN = (byte) '=';
|
||||
|
||||
/** The new line character (\n) as a byte. */
|
||||
private final static byte NEW_LINE = (byte) '\n';
|
||||
|
||||
/**
|
||||
* The 64 valid Base64 values.
|
||||
*/
|
||||
private final static byte[] ALPHABET =
|
||||
{(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F',
|
||||
(byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K',
|
||||
(byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P',
|
||||
(byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U',
|
||||
(byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z',
|
||||
(byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e',
|
||||
(byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j',
|
||||
(byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o',
|
||||
(byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't',
|
||||
(byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y',
|
||||
(byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3',
|
||||
(byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8',
|
||||
(byte) '9', (byte) '+', (byte) '/'};
|
||||
|
||||
/**
|
||||
* The 64 valid web safe Base64 values.
|
||||
*/
|
||||
private final static byte[] WEBSAFE_ALPHABET =
|
||||
{(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F',
|
||||
(byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K',
|
||||
(byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P',
|
||||
(byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U',
|
||||
(byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z',
|
||||
(byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e',
|
||||
(byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j',
|
||||
(byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o',
|
||||
(byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't',
|
||||
(byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y',
|
||||
(byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3',
|
||||
(byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8',
|
||||
(byte) '9', (byte) '-', (byte) '_'};
|
||||
|
||||
/**
|
||||
* Translates a Base64 value to either its 6-bit reconstruction value
|
||||
* or a negative number indicating some other meaning.
|
||||
**/
|
||||
private final static byte[] DECODABET = {-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
|
||||
-5, -5, // Whitespace: Tab and Linefeed
|
||||
-9, -9, // Decimal 11 - 12
|
||||
-5, // Whitespace: Carriage Return
|
||||
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
|
||||
-9, -9, -9, -9, -9, // Decimal 27 - 31
|
||||
-5, // Whitespace: Space
|
||||
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42
|
||||
62, // Plus sign at decimal 43
|
||||
-9, -9, -9, // Decimal 44 - 46
|
||||
63, // Slash at decimal 47
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
|
||||
-9, -9, -9, // Decimal 58 - 60
|
||||
-1, // Equals sign at decimal 61
|
||||
-9, -9, -9, // Decimal 62 - 64
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N'
|
||||
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z'
|
||||
-9, -9, -9, -9, -9, -9, // Decimal 91 - 96
|
||||
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm'
|
||||
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z'
|
||||
-9, -9, -9, -9, -9 // Decimal 123 - 127
|
||||
/* ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139
|
||||
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
|
||||
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
|
||||
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
|
||||
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
|
||||
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
|
||||
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
|
||||
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
|
||||
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
|
||||
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
|
||||
};
|
||||
|
||||
/** The web safe decodabet */
|
||||
private final static byte[] WEBSAFE_DECODABET =
|
||||
{-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
|
||||
-5, -5, // Whitespace: Tab and Linefeed
|
||||
-9, -9, // Decimal 11 - 12
|
||||
-5, // Whitespace: Carriage Return
|
||||
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
|
||||
-9, -9, -9, -9, -9, // Decimal 27 - 31
|
||||
-5, // Whitespace: Space
|
||||
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 44
|
||||
62, // Dash '-' sign at decimal 45
|
||||
-9, -9, // Decimal 46-47
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
|
||||
-9, -9, -9, // Decimal 58 - 60
|
||||
-1, // Equals sign at decimal 61
|
||||
-9, -9, -9, // Decimal 62 - 64
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N'
|
||||
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z'
|
||||
-9, -9, -9, -9, // Decimal 91-94
|
||||
63, // Underscore '_' at decimal 95
|
||||
-9, // Decimal 96
|
||||
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm'
|
||||
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z'
|
||||
-9, -9, -9, -9, -9 // Decimal 123 - 127
|
||||
/* ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139
|
||||
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
|
||||
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
|
||||
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
|
||||
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
|
||||
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
|
||||
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
|
||||
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
|
||||
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
|
||||
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
|
||||
};
|
||||
|
||||
// Indicates white space in encoding
|
||||
private final static byte WHITE_SPACE_ENC = -5;
|
||||
// Indicates equals sign in encoding
|
||||
private final static byte EQUALS_SIGN_ENC = -1;
|
||||
|
||||
/** Defeats instantiation. */
|
||||
private Base64() {
|
||||
}
|
||||
|
||||
/* ******** E N C O D I N G M E T H O D S ******** */
|
||||
|
||||
/**
|
||||
* Encodes up to three bytes of the array <var>source</var>
|
||||
* and writes the resulting four Base64 bytes to <var>destination</var>.
|
||||
* The source and destination arrays can be manipulated
|
||||
* anywhere along their length by specifying
|
||||
* <var>srcOffset</var> and <var>destOffset</var>.
|
||||
* This method does not check to make sure your arrays
|
||||
* are large enough to accommodate <var>srcOffset</var> + 3 for
|
||||
* the <var>source</var> array or <var>destOffset</var> + 4 for
|
||||
* the <var>destination</var> array.
|
||||
* The actual number of significant bytes in your array is
|
||||
* given by <var>numSigBytes</var>.
|
||||
*
|
||||
* @param source the array to convert
|
||||
* @param srcOffset the index where conversion begins
|
||||
* @param numSigBytes the number of significant bytes in your array
|
||||
* @param destination the array to hold the conversion
|
||||
* @param destOffset the index where output will be put
|
||||
* @param alphabet is the encoding alphabet
|
||||
* @return the <var>destination</var> array
|
||||
* @since 1.3
|
||||
*/
|
||||
private static byte[] encode3to4(byte[] source, int srcOffset,
|
||||
int numSigBytes, byte[] destination, int destOffset, byte[] alphabet) {
|
||||
// 1 2 3
|
||||
// 01234567890123456789012345678901 Bit position
|
||||
// --------000000001111111122222222 Array position from threeBytes
|
||||
// --------| || || || | Six bit groups to index alphabet
|
||||
// >>18 >>12 >> 6 >> 0 Right shift necessary
|
||||
// 0x3f 0x3f 0x3f Additional AND
|
||||
|
||||
// Create buffer with zero-padding if there are only one or two
|
||||
// significant bytes passed in the array.
|
||||
// We have to shift left 24 in order to flush out the 1's that appear
|
||||
// when Java treats a value as negative that is cast from a byte to an int.
|
||||
int inBuff =
|
||||
(numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0)
|
||||
| (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0)
|
||||
| (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0);
|
||||
|
||||
switch (numSigBytes) {
|
||||
case 3:
|
||||
destination[destOffset] = alphabet[(inBuff >>> 18)];
|
||||
destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f];
|
||||
destination[destOffset + 2] = alphabet[(inBuff >>> 6) & 0x3f];
|
||||
destination[destOffset + 3] = alphabet[(inBuff) & 0x3f];
|
||||
return destination;
|
||||
case 2:
|
||||
destination[destOffset] = alphabet[(inBuff >>> 18)];
|
||||
destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f];
|
||||
destination[destOffset + 2] = alphabet[(inBuff >>> 6) & 0x3f];
|
||||
destination[destOffset + 3] = EQUALS_SIGN;
|
||||
return destination;
|
||||
case 1:
|
||||
destination[destOffset] = alphabet[(inBuff >>> 18)];
|
||||
destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f];
|
||||
destination[destOffset + 2] = EQUALS_SIGN;
|
||||
destination[destOffset + 3] = EQUALS_SIGN;
|
||||
return destination;
|
||||
default:
|
||||
return destination;
|
||||
} // end switch
|
||||
} // end encode3to4
|
||||
|
||||
/**
|
||||
* Encodes a byte array into Base64 notation.
|
||||
* Equivalent to calling
|
||||
* {@code encodeBytes(source, 0, source.length)}
|
||||
*
|
||||
* @param source The data to convert
|
||||
* @since 1.4
|
||||
*/
|
||||
public static String encode(byte[] source) {
|
||||
return encode(source, 0, source.length, ALPHABET, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a byte array into web safe Base64 notation.
|
||||
*
|
||||
* @param source The data to convert
|
||||
* @param doPadding is {@code true} to pad result with '=' chars
|
||||
* if it does not fall on 3 byte boundaries
|
||||
*/
|
||||
public static String encodeWebSafe(byte[] source, boolean doPadding) {
|
||||
return encode(source, 0, source.length, WEBSAFE_ALPHABET, doPadding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a byte array into Base64 notation.
|
||||
*
|
||||
* @param source the data to convert
|
||||
* @param off offset in array where conversion should begin
|
||||
* @param len length of data to convert
|
||||
* @param alphabet the encoding alphabet
|
||||
* @param doPadding is {@code true} to pad result with '=' chars
|
||||
* if it does not fall on 3 byte boundaries
|
||||
* @since 1.4
|
||||
*/
|
||||
public static String encode(byte[] source, int off, int len, byte[] alphabet,
|
||||
boolean doPadding) {
|
||||
byte[] outBuff = encode(source, off, len, alphabet, Integer.MAX_VALUE);
|
||||
int outLen = outBuff.length;
|
||||
|
||||
// If doPadding is false, set length to truncate '='
|
||||
// padding characters
|
||||
while (doPadding == false && outLen > 0) {
|
||||
if (outBuff[outLen - 1] != '=') {
|
||||
break;
|
||||
}
|
||||
outLen -= 1;
|
||||
}
|
||||
|
||||
return new String(outBuff, 0, outLen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a byte array into Base64 notation.
|
||||
*
|
||||
* @param source the data to convert
|
||||
* @param off offset in array where conversion should begin
|
||||
* @param len length of data to convert
|
||||
* @param alphabet is the encoding alphabet
|
||||
* @param maxLineLength maximum length of one line.
|
||||
* @return the BASE64-encoded byte array
|
||||
*/
|
||||
public static byte[] encode(byte[] source, int off, int len, byte[] alphabet,
|
||||
int maxLineLength) {
|
||||
int lenDiv3 = (len + 2) / 3; // ceil(len / 3)
|
||||
int len43 = lenDiv3 * 4;
|
||||
byte[] outBuff = new byte[len43 // Main 4:3
|
||||
+ (len43 / maxLineLength)]; // New lines
|
||||
|
||||
int d = 0;
|
||||
int e = 0;
|
||||
int len2 = len - 2;
|
||||
int lineLength = 0;
|
||||
for (; d < len2; d += 3, e += 4) {
|
||||
|
||||
// The following block of code is the same as
|
||||
// encode3to4( source, d + off, 3, outBuff, e, alphabet );
|
||||
// but inlined for faster encoding (~20% improvement)
|
||||
int inBuff =
|
||||
((source[d + off] << 24) >>> 8)
|
||||
| ((source[d + 1 + off] << 24) >>> 16)
|
||||
| ((source[d + 2 + off] << 24) >>> 24);
|
||||
outBuff[e] = alphabet[(inBuff >>> 18)];
|
||||
outBuff[e + 1] = alphabet[(inBuff >>> 12) & 0x3f];
|
||||
outBuff[e + 2] = alphabet[(inBuff >>> 6) & 0x3f];
|
||||
outBuff[e + 3] = alphabet[(inBuff) & 0x3f];
|
||||
|
||||
lineLength += 4;
|
||||
if (lineLength == maxLineLength) {
|
||||
outBuff[e + 4] = NEW_LINE;
|
||||
e++;
|
||||
lineLength = 0;
|
||||
} // end if: end of line
|
||||
} // end for: each piece of array
|
||||
|
||||
if (d < len) {
|
||||
encode3to4(source, d + off, len - d, outBuff, e, alphabet);
|
||||
|
||||
lineLength += 4;
|
||||
if (lineLength == maxLineLength) {
|
||||
// Add a last newline
|
||||
outBuff[e + 4] = NEW_LINE;
|
||||
e++;
|
||||
}
|
||||
e += 4;
|
||||
}
|
||||
|
||||
assert (e == outBuff.length);
|
||||
return outBuff;
|
||||
}
|
||||
|
||||
|
||||
/* ******** D E C O D I N G M E T H O D S ******** */
|
||||
|
||||
|
||||
/**
|
||||
* Decodes four bytes from array <var>source</var>
|
||||
* and writes the resulting bytes (up to three of them)
|
||||
* to <var>destination</var>.
|
||||
* The source and destination arrays can be manipulated
|
||||
* anywhere along their length by specifying
|
||||
* <var>srcOffset</var> and <var>destOffset</var>.
|
||||
* This method does not check to make sure your arrays
|
||||
* are large enough to accommodate <var>srcOffset</var> + 4 for
|
||||
* the <var>source</var> array or <var>destOffset</var> + 3 for
|
||||
* the <var>destination</var> array.
|
||||
* This method returns the actual number of bytes that
|
||||
* were converted from the Base64 encoding.
|
||||
*
|
||||
*
|
||||
* @param source the array to convert
|
||||
* @param srcOffset the index where conversion begins
|
||||
* @param destination the array to hold the conversion
|
||||
* @param destOffset the index where output will be put
|
||||
* @param decodabet the decodabet for decoding Base64 content
|
||||
* @return the number of decoded bytes converted
|
||||
* @since 1.3
|
||||
*/
|
||||
private static int decode4to3(byte[] source, int srcOffset,
|
||||
byte[] destination, int destOffset, byte[] decodabet) {
|
||||
// Example: Dk==
|
||||
if (source[srcOffset + 2] == EQUALS_SIGN) {
|
||||
int outBuff =
|
||||
((decodabet[source[srcOffset]] << 24) >>> 6)
|
||||
| ((decodabet[source[srcOffset + 1]] << 24) >>> 12);
|
||||
|
||||
destination[destOffset] = (byte) (outBuff >>> 16);
|
||||
return 1;
|
||||
} else if (source[srcOffset + 3] == EQUALS_SIGN) {
|
||||
// Example: DkL=
|
||||
int outBuff =
|
||||
((decodabet[source[srcOffset]] << 24) >>> 6)
|
||||
| ((decodabet[source[srcOffset + 1]] << 24) >>> 12)
|
||||
| ((decodabet[source[srcOffset + 2]] << 24) >>> 18);
|
||||
|
||||
destination[destOffset] = (byte) (outBuff >>> 16);
|
||||
destination[destOffset + 1] = (byte) (outBuff >>> 8);
|
||||
return 2;
|
||||
} else {
|
||||
// Example: DkLE
|
||||
int outBuff =
|
||||
((decodabet[source[srcOffset]] << 24) >>> 6)
|
||||
| ((decodabet[source[srcOffset + 1]] << 24) >>> 12)
|
||||
| ((decodabet[source[srcOffset + 2]] << 24) >>> 18)
|
||||
| ((decodabet[source[srcOffset + 3]] << 24) >>> 24);
|
||||
|
||||
destination[destOffset] = (byte) (outBuff >> 16);
|
||||
destination[destOffset + 1] = (byte) (outBuff >> 8);
|
||||
destination[destOffset + 2] = (byte) (outBuff);
|
||||
return 3;
|
||||
}
|
||||
} // end decodeToBytes
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from Base64 notation.
|
||||
*
|
||||
* @param s the string to decode (decoded in default encoding)
|
||||
* @return the decoded data
|
||||
* @since 1.4
|
||||
*/
|
||||
public static byte[] decode(String s) throws Base64DecoderException {
|
||||
byte[] bytes = s.getBytes();
|
||||
return decode(bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes data from web safe Base64 notation.
|
||||
* Web safe encoding uses '-' instead of '+', '_' instead of '/'
|
||||
*
|
||||
* @param s the string to decode (decoded in default encoding)
|
||||
* @return the decoded data
|
||||
*/
|
||||
public static byte[] decodeWebSafe(String s) throws Base64DecoderException {
|
||||
byte[] bytes = s.getBytes();
|
||||
return decodeWebSafe(bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes Base64 content in byte array format and returns
|
||||
* the decoded byte array.
|
||||
*
|
||||
* @param source The Base64 encoded data
|
||||
* @return decoded data
|
||||
* @since 1.3
|
||||
* @throws Base64DecoderException
|
||||
*/
|
||||
public static byte[] decode(byte[] source) throws Base64DecoderException {
|
||||
return decode(source, 0, source.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes web safe Base64 content in byte array format and returns
|
||||
* the decoded data.
|
||||
* Web safe encoding uses '-' instead of '+', '_' instead of '/'
|
||||
*
|
||||
* @param source the string to decode (decoded in default encoding)
|
||||
* @return the decoded data
|
||||
*/
|
||||
public static byte[] decodeWebSafe(byte[] source)
|
||||
throws Base64DecoderException {
|
||||
return decodeWebSafe(source, 0, source.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes Base64 content in byte array format and returns
|
||||
* the decoded byte array.
|
||||
*
|
||||
* @param source the Base64 encoded data
|
||||
* @param off the offset of where to begin decoding
|
||||
* @param len the length of characters to decode
|
||||
* @return decoded data
|
||||
* @since 1.3
|
||||
* @throws Base64DecoderException
|
||||
*/
|
||||
public static byte[] decode(byte[] source, int off, int len)
|
||||
throws Base64DecoderException {
|
||||
return decode(source, off, len, DECODABET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes web safe Base64 content in byte array format and returns
|
||||
* the decoded byte array.
|
||||
* Web safe encoding uses '-' instead of '+', '_' instead of '/'
|
||||
*
|
||||
* @param source the Base64 encoded data
|
||||
* @param off the offset of where to begin decoding
|
||||
* @param len the length of characters to decode
|
||||
* @return decoded data
|
||||
*/
|
||||
public static byte[] decodeWebSafe(byte[] source, int off, int len)
|
||||
throws Base64DecoderException {
|
||||
return decode(source, off, len, WEBSAFE_DECODABET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes Base64 content using the supplied decodabet and returns
|
||||
* the decoded byte array.
|
||||
*
|
||||
* @param source the Base64 encoded data
|
||||
* @param off the offset of where to begin decoding
|
||||
* @param len the length of characters to decode
|
||||
* @param decodabet the decodabet for decoding Base64 content
|
||||
* @return decoded data
|
||||
*/
|
||||
public static byte[] decode(byte[] source, int off, int len, byte[] decodabet)
|
||||
throws Base64DecoderException {
|
||||
int len34 = len * 3 / 4;
|
||||
byte[] outBuff = new byte[2 + len34]; // Upper limit on size of output
|
||||
int outBuffPosn = 0;
|
||||
|
||||
byte[] b4 = new byte[4];
|
||||
int b4Posn = 0;
|
||||
int i = 0;
|
||||
byte sbiCrop = 0;
|
||||
byte sbiDecode = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
sbiCrop = (byte) (source[i + off] & 0x7f); // Only the low seven bits
|
||||
sbiDecode = decodabet[sbiCrop];
|
||||
|
||||
if (sbiDecode >= WHITE_SPACE_ENC) { // White space Equals sign or better
|
||||
if (sbiDecode >= EQUALS_SIGN_ENC) {
|
||||
// An equals sign (for padding) must not occur at position 0 or 1
|
||||
// and must be the last byte[s] in the encoded value
|
||||
if (sbiCrop == EQUALS_SIGN) {
|
||||
int bytesLeft = len - i;
|
||||
byte lastByte = (byte) (source[len - 1 + off] & 0x7f);
|
||||
if (b4Posn == 0 || b4Posn == 1) {
|
||||
throw new Base64DecoderException(
|
||||
"invalid padding byte '=' at byte offset " + i);
|
||||
} else if ((b4Posn == 3 && bytesLeft > 2)
|
||||
|| (b4Posn == 4 && bytesLeft > 1)) {
|
||||
throw new Base64DecoderException(
|
||||
"padding byte '=' falsely signals end of encoded value "
|
||||
+ "at offset " + i);
|
||||
} else if (lastByte != EQUALS_SIGN && lastByte != NEW_LINE) {
|
||||
throw new Base64DecoderException(
|
||||
"encoded value has invalid trailing byte");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
b4[b4Posn++] = sbiCrop;
|
||||
if (b4Posn == 4) {
|
||||
outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, decodabet);
|
||||
b4Posn = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new Base64DecoderException("Bad Base64 input character at " + i
|
||||
+ ": " + source[i + off] + "(decimal)");
|
||||
}
|
||||
}
|
||||
|
||||
// Because web safe encoding allows non padding base64 encodes, we
|
||||
// need to pad the rest of the b4 buffer with equal signs when
|
||||
// b4Posn != 0. There can be at most 2 equal signs at the end of
|
||||
// four characters, so the b4 buffer must have two or three
|
||||
// characters. This also catches the case where the input is
|
||||
// padded with EQUALS_SIGN
|
||||
if (b4Posn != 0) {
|
||||
if (b4Posn == 1) {
|
||||
throw new Base64DecoderException("single trailing character at offset "
|
||||
+ (len - 1));
|
||||
}
|
||||
b4[b4Posn++] = EQUALS_SIGN;
|
||||
outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, decodabet);
|
||||
}
|
||||
|
||||
byte[] out = new byte[outBuffPosn];
|
||||
System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
|
||||
return out;
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright 2002, Google, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package de.luhmer.owncloudnewsreader.util;
|
||||
|
||||
/**
|
||||
* Exception thrown when encountering an invalid Base64 input character.
|
||||
*
|
||||
* @author nelson
|
||||
*/
|
||||
public class Base64DecoderException extends Exception {
|
||||
public Base64DecoderException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Base64DecoderException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
After Width: | Height: | Size: 504 B |
After Width: | Height: | Size: 335 B |
After Width: | Height: | Size: 643 B |
After Width: | Height: | Size: 934 B |
Before Width: | Height: | Size: 245 B |
Before Width: | Height: | Size: 476 B |
Before Width: | Height: | Size: 284 B |
Before Width: | Height: | Size: 281 B |
Before Width: | Height: | Size: 289 B |
Before Width: | Height: | Size: 290 B |
Before Width: | Height: | Size: 473 B |
Before Width: | Height: | Size: 474 B |
Before Width: | Height: | Size: 288 B |
Before Width: | Height: | Size: 408 B |
Before Width: | Height: | Size: 118 B |
Before Width: | Height: | Size: 362 B |
Before Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 548 B |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 987 B |
Before Width: | Height: | Size: 1,004 B |
Before Width: | Height: | Size: 291 B |
Before Width: | Height: | Size: 500 B |
Before Width: | Height: | Size: 595 B |
|
@ -1,107 +1,94 @@
|
|||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".LoginActivity"
|
||||
android:id="@+id/login_form"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" >
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".LoginActivity"
|
||||
android:id="@+id/login_form"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" >
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/abc_dialog_padding_material"
|
||||
android:paddingRight="@dimen/abc_dialog_padding_material"
|
||||
android:paddingTop="@dimen/abc_dialog_padding_material">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/username"
|
||||
android:inputType="textEmailAddress"
|
||||
style="@style/LoginDialogEditTextStyle"
|
||||
android:hint="@string/pref_title_username" />
|
||||
|
||||
|
||||
<FrameLayout
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:id="@+id/username_container">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/username"
|
||||
android:inputType="textEmailAddress"
|
||||
android:hint="@string/pref_title_username"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/username_container"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:id="@+id/password_container">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/password"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:hint="@string/pref_title_password"
|
||||
style="@style/LoginDialogEditTextStyle"
|
||||
android:fontFamily="sans-serif"
|
||||
android:inputType="textPassword"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true" />
|
||||
android:singleLine="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgView_ShowPassword"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="right"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:src="@android:drawable/ic_menu_view"/>
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/edt_owncloudRootPath"
|
||||
android:fontFamily="sans-serif"
|
||||
android:hint="@string/pref_default_owncloudRootPath"
|
||||
android:inputType="textUri"
|
||||
android:maxLines="1"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:title="@string/pref_default_owncloudRootPath"
|
||||
style="@style/LoginDialogEditTextStyle" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cb_AllowAllSSLCertificates"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/pref_title_DisableHostnameVerification" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_importAccount"
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/url_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Import Account from other ownCloud App"/>
|
||||
android:layout_below="@+id/password_container"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="#383E44"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp" />
|
||||
<EditText
|
||||
android:id="@+id/edt_owncloudRootPath"
|
||||
android:hint="@string/pref_title_owncloudRootPath"
|
||||
android:inputType="textUri"
|
||||
android:maxLines="1"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:title="@string/pref_default_owncloudRootPath"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" >
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_cancel"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="@android:string/cancel" />
|
||||
<ImageView
|
||||
android:id="@+id/imgView_ShowPassword"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="right"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:src="@drawable/ic_action_visibility"
|
||||
android:layout_alignTop="@+id/password_container"
|
||||
android:layout_alignBottom="@+id/password_container"
|
||||
android:layout_alignRight="@+id/password_container" />
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#383E44"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp" />
|
||||
<CheckBox
|
||||
android:id="@+id/cb_AllowAllSSLCertificates"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/pref_title_DisableHostnameVerification"
|
||||
android:layout_below="@+id/url_container"
|
||||
android:layout_alignRight="@+id/imgView_ShowPassword"
|
||||
android:layout_alignEnd="@+id/imgView_ShowPassword" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_signin"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="@string/action_sign_in_short" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</ScrollView>
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:baselineAligned="false"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="10dp" >
|
||||
|
||||
<!--
|
||||
android:background="@drawable/checkbox_background"
|
||||
android:button="@drawable/checkbox"
|
||||
-->
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_subscription"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:singleLine="true"
|
||||
android:text="@string/empty_view_header"
|
||||
android:textSize="15sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/summary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:lines="1"
|
||||
android:text="@string/empty_view_content"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
|
@ -6,4 +6,4 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorPrimaryDark"
|
||||
app:theme="@style/ToolbarTheme" />
|
||||
android:theme="@style/ToolbarTheme" />
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
<string name="menu_downloadMoreItems">Download more items</string>
|
||||
|
||||
<!-- Import Accounts -->
|
||||
<string name="import_account_dialog_title">Import Account</string>
|
||||
<string name="import_account">Import Account</string>
|
||||
|
||||
<!-- EMAIL -->
|
||||
<string name="email_sourceCode">Sourcecode of item - Bugreport</string>
|
||||
|
@ -67,7 +67,7 @@
|
|||
<!-- Strings related to login -->
|
||||
<string name="pref_title_username">Username</string>
|
||||
<string name="pref_title_password">Password</string>
|
||||
<!-- <string name="pref_title_owncloudRootPath">ownCloud root address</string> -->
|
||||
<string name="pref_title_owncloudRootPath">ownCloud root address</string>
|
||||
<string name="pref_default_owncloudRootPath">https://1.2.3.4/owncloud</string>
|
||||
<!-- <string name="pref_default_username">admin</string> -->
|
||||
|
||||
|
@ -87,9 +87,18 @@
|
|||
<string name="pull_to_refresh_updateFolder">Synchronizing folder</string>
|
||||
<string name="pull_to_refresh_updateFeeds">Synchronizing feeds</string>
|
||||
<string name="pull_to_refresh_updateItems">Synchronizing items</string>
|
||||
<plurals name="fetched_items_so_far">
|
||||
<item quantity="one">Fetched %d item so far..</item>
|
||||
<item quantity="other">Fetched %d items so far..</item>
|
||||
</plurals>
|
||||
|
||||
<!-- Strings related to Settings -->
|
||||
<string name="title_activity_settings">Settings</string>
|
||||
<string name="cache_is_cleared">Cache is cleared!</string>
|
||||
<plurals name="number_of_files">
|
||||
<item quantity="one">%d File</item>
|
||||
<item quantity="other">%d Files</item>
|
||||
</plurals>
|
||||
|
||||
<!-- General settings -->
|
||||
<string name="pref_header_general">General</string>
|
||||
|
|
|
@ -58,15 +58,4 @@
|
|||
|
||||
|
||||
|
||||
<style name="LoginDialogEditTextStyle" >
|
||||
<item name="android:layout_marginTop">4dp</item>
|
||||
<item name="android:layout_marginLeft">4dp</item>
|
||||
<item name="android:layout_marginRight">4dp</item>
|
||||
<item name="android:layout_marginBottom">4dp</item>
|
||||
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
|
||||
<!-- RobotoFontStyle -->
|
||||
</style>
|
||||
</resources>
|
|
@ -1 +0,0 @@
|
|||
Subproject commit cea2318fdf41f693fd7ce2dd27fbf551c35c844d
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:1.2.3'
|
||||
|
@ -11,6 +11,6 @@ buildscript {
|
|||
|
||||
allprojects {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
git rm -r News-Android-App/src/main/res/values-ach/
|
||||
git rm -r News-Android-App/src/main/res/values-ady/
|
||||
git rm -r News-Android-App/src/main/res/values-en@pirate/
|
||||
git rm -r News-Android-App/src/main/res/values-nds/
|
||||
git rm -r News-Android-App/src/main/res/values-nqo/
|
||||
git rm -r News-Android-App/src/main/res/values-tzm/
|
||||
git rm -r News-Android-App/src/main/res/values-ast/
|
|
@ -1,7 +1,6 @@
|
|||
include ':News-Android-App', ':ownCloud-Account-Importer'
|
||||
include ':Changeloglib:ChangeLogLibrary'
|
||||
include ':ShowcaseView:library'
|
||||
include ':android-HoloCircularProgressBar:library'
|
||||
|
||||
include 'customtabs'
|
||||
project(':customtabs').projectDir = new File(settingsDir, './custom-tabs-client/customtabs')
|