├── .gitattributes ├── .gitignore ├── ImapNote2 ├── build.gradle ├── libs │ ├── activation.jar │ ├── additionnal.jar │ ├── android-support-v4.jar │ ├── commons-io-2.4.jar │ ├── javamaildir-0.6.jar │ └── mail.jar └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── Pau │ │ └── ImapNotes2 │ │ ├── AccontConfigurationActivity.java │ │ ├── Data │ │ ├── ConfigurationFile.java │ │ ├── ImapNotes2Account.java │ │ └── NotesDb.java │ │ ├── ImapNotes2.java │ │ ├── Listactivity.java │ │ ├── Miscs │ │ ├── ImapNotes2Result.java │ │ ├── ImapNotesAuthenticatorService.java │ │ ├── Imaper.java │ │ ├── OneNote.java │ │ ├── Sticky.java │ │ ├── SyncThread.java │ │ └── UpdateThread.java │ │ ├── NewNoteActivity.java │ │ ├── NoteDetailActivity.java │ │ ├── NotesListAdapter.java │ │ └── Sync │ │ ├── StubProvider.java │ │ ├── SyncAdapter.java │ │ ├── SyncService.java │ │ └── SyncUtils.java │ └── res │ ├── drawable-hdpi │ └── ic_launcher.png │ ├── drawable-mdpi │ ├── ic_action_about.png │ ├── ic_action_color.png │ ├── ic_action_delete.png │ ├── ic_action_login.png │ ├── ic_action_new.png │ ├── ic_action_refresh.png │ ├── ic_action_save.png │ ├── ic_action_search.png │ ├── ic_action_user_edit.png │ └── ic_launcher.png │ ├── drawable-xhdpi │ └── ic_launcher.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── layout │ ├── account_selection.xml │ ├── main.xml │ ├── new_note.xml │ ├── note_detail.xml │ └── note_element.xml │ ├── menu │ ├── detail.xml │ ├── list.xml │ └── newnote.xml │ ├── values-v14 │ └── styles.xml │ ├── values │ ├── strings.xml │ └── styles.xml │ └── xml │ ├── account_preferences.xml │ ├── authenticator.xml │ ├── searchable.xml │ └── syncadapter.xml ├── LICENSE ├── README.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitattributes: -------------------------------------------------------------------------------- 1 | *.bat text eol=crlf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # generated files 12 | bin/ 13 | build/ 14 | gen/ 15 | obj/ 16 | .gradle/ 17 | 18 | # Local configuration file (sdk path, etc) 19 | local.properties 20 | project.properties 21 | 22 | # Eclipse project files 23 | .settings/ 24 | .classpath 25 | .project 26 | 27 | # Proguard folder generated by Eclipse 28 | proguard/ 29 | 30 | # Intellij project files 31 | *.iml 32 | *.ipr 33 | *.iws 34 | .idea/ 35 | 36 | # Gradle wrapper 37 | gradle/wrapper/gradle/ 38 | gradle/wrapper/gradlew* 39 | 40 | -------------------------------------------------------------------------------- /ImapNote2/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | applicationId "com.Pau.ImapNotes2" 9 | minSdkVersion 16 10 | targetSdkVersion 16 11 | } 12 | 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 17 | } 18 | } 19 | 20 | packagingOptions { 21 | exclude 'META-INF/LICENSE.txt' 22 | } 23 | } 24 | 25 | dependencies { 26 | compile 'com.android.support:support-v4:21.0.3' 27 | compile files('libs/activation.jar') 28 | compile files('libs/additionnal.jar') 29 | compile files('libs/commons-io-2.4.jar') 30 | compile files('libs/javamaildir-0.6.jar') 31 | compile files('libs/mail.jar') 32 | } 33 | -------------------------------------------------------------------------------- /ImapNote2/libs/activation.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N0ury/ImapNote2/73cc32655583237223b437777516bb0c88dcd633/ImapNote2/libs/activation.jar -------------------------------------------------------------------------------- /ImapNote2/libs/additionnal.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N0ury/ImapNote2/73cc32655583237223b437777516bb0c88dcd633/ImapNote2/libs/additionnal.jar -------------------------------------------------------------------------------- /ImapNote2/libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N0ury/ImapNote2/73cc32655583237223b437777516bb0c88dcd633/ImapNote2/libs/android-support-v4.jar -------------------------------------------------------------------------------- /ImapNote2/libs/commons-io-2.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N0ury/ImapNote2/73cc32655583237223b437777516bb0c88dcd633/ImapNote2/libs/commons-io-2.4.jar -------------------------------------------------------------------------------- /ImapNote2/libs/javamaildir-0.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N0ury/ImapNote2/73cc32655583237223b437777516bb0c88dcd633/ImapNote2/libs/javamaildir-0.6.jar -------------------------------------------------------------------------------- /ImapNote2/libs/mail.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N0ury/ImapNote2/73cc32655583237223b437777516bb0c88dcd633/ImapNote2/libs/mail.jar -------------------------------------------------------------------------------- /ImapNote2/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | 34 | 35 | 38 | 40 | 41 | 42 | 44 | 46 | 47 | 48 | 50 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 60 | 61 | 62 | 66 | 67 | 68 | 69 | 70 | 71 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /ImapNote2/src/main/java/com/Pau/ImapNotes2/AccontConfigurationActivity.java: -------------------------------------------------------------------------------- 1 | package com.Pau.ImapNotes2; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.Pau.ImapNotes2.Data.ConfigurationFile; 7 | import com.Pau.ImapNotes2.Data.ImapNotes2Account; 8 | import com.Pau.ImapNotes2.Miscs.ImapNotes2Result; 9 | import com.Pau.ImapNotes2.Miscs.Imaper; 10 | 11 | import android.accounts.Account; 12 | import android.accounts.AccountAuthenticatorActivity; 13 | import android.accounts.AccountManager; 14 | import android.app.ProgressDialog; 15 | import android.content.ContentResolver; 16 | import android.os.AsyncTask; 17 | import android.os.Bundle; 18 | import android.os.CountDownTimer; 19 | import android.support.v4.app.NavUtils; 20 | import android.util.Log; 21 | import android.view.Menu; 22 | import android.view.MenuItem; 23 | import android.view.View; 24 | import android.view.View.OnClickListener; 25 | import android.view.WindowManager; 26 | import android.widget.AdapterView; 27 | import android.widget.AdapterView.OnItemSelectedListener; 28 | import android.widget.ArrayAdapter; 29 | import android.widget.Button; 30 | import android.widget.CheckBox; 31 | import android.widget.LinearLayout; 32 | import android.widget.Spinner; 33 | import android.widget.TextView; 34 | import android.widget.Toast; 35 | 36 | public class AccontConfigurationActivity extends AccountAuthenticatorActivity implements OnItemSelectedListener{ 37 | public static final int TO_REFRESH = 999; 38 | public static final String AUTHORITY = "com.Pau.ImapNotes2.provider"; 39 | private static final String TAG = "AccontConfigurationActivity"; 40 | 41 | private Imaper imapFolder; 42 | 43 | private TextView accountnameTextView; 44 | private TextView usernameTextView; 45 | private TextView passwordTextView; 46 | private TextView serverTextView; 47 | private TextView portnumTextView; 48 | private TextView syncintervalTextView; 49 | private TextView folderTextView; 50 | private CheckBox stickyCheckBox; 51 | private Spinner securitySpinner; 52 | private ImapNotes2Account imapNotes2Account; 53 | private String security; 54 | private int security_i; 55 | private String action; 56 | private String accountname; 57 | private ConfigurationFile settings; 58 | private static Account myAccount = null; 59 | private static AccountManager accountManager; 60 | 61 | private OnClickListener clickListenerLogin = new View.OnClickListener() { 62 | @Override 63 | public void onClick(View v) { 64 | // Click on Login Button 65 | if (((String) accountnameTextView.getText().toString()).contains("'")) { 66 | // Single quotation marks are not allowed in accountname 67 | Toast.makeText(getApplicationContext(), "Quotation marks are not allowed in accountname", 68 | Toast.LENGTH_LONG).show(); 69 | } else { 70 | DoLogin(v); 71 | } 72 | } 73 | }; 74 | 75 | private OnClickListener clickListenerEdit = new View.OnClickListener() { 76 | @Override 77 | public void onClick(View v) { 78 | // Click on Edit Button 79 | if (((String) accountnameTextView.getText().toString()).contains("'")) { 80 | // Single quotation marks are not allowed in accountname 81 | Toast.makeText(getApplicationContext(), "Quotation marks are not allowed in accountname", 82 | Toast.LENGTH_LONG).show(); 83 | } else { 84 | DoLogin(v); 85 | } 86 | } 87 | }; 88 | 89 | private OnClickListener clickListenerRemove = new View.OnClickListener() { 90 | @Override 91 | public void onClick(View v) { 92 | // Clic on Remove Button 93 | accountManager.removeAccount(myAccount, null, null); 94 | Toast.makeText(getApplicationContext(), "Account has been removed", 95 | Toast.LENGTH_LONG).show(); 96 | finish();//finishing activity 97 | } 98 | }; 99 | 100 | @Override 101 | public void onCreate(Bundle savedInstanceState) { 102 | super.onCreate(savedInstanceState); 103 | setContentView(R.layout.account_selection); 104 | getActionBar().setDisplayHomeAsUpEnabled(true); 105 | this.accountnameTextView = (TextView)(findViewById(R.id.accountnameEdit)); 106 | this.usernameTextView = (TextView)findViewById(R.id.usernameEdit); 107 | this.passwordTextView = (TextView)findViewById(R.id.passwordEdit); 108 | this.serverTextView = (TextView)findViewById(R.id.serverEdit); 109 | this.portnumTextView = (TextView)findViewById(R.id.portnumEdit); 110 | this.syncintervalTextView = (TextView)findViewById(R.id.syncintervalEdit); 111 | this.folderTextView = (TextView)findViewById(R.id.folderEdit); 112 | this.stickyCheckBox = (CheckBox)findViewById(R.id.stickyCheckBox); 113 | 114 | securitySpinner = (Spinner) findViewById(R.id.securitySpinner); 115 | List list = new ArrayList(); 116 | list.add("None"); 117 | list.add("SSL/TLS"); 118 | list.add("SSL/TLS (accept all certificates)"); 119 | list.add("STARTTLS"); 120 | list.add("STARTTLS (accept all certificates)"); 121 | ArrayAdapter dataAdapter = new ArrayAdapter 122 | (this, android.R.layout.simple_spinner_item,list); 123 | dataAdapter.setDropDownViewResource 124 | (android.R.layout.simple_spinner_dropdown_item); 125 | securitySpinner.setAdapter(dataAdapter); 126 | // Spinner item selection Listener 127 | securitySpinner.setOnItemSelectedListener(this); 128 | 129 | imapNotes2Account = new ImapNotes2Account(); 130 | this.imapFolder = ((ImapNotes2)getApplicationContext()).GetImaper(); 131 | this.settings = new ConfigurationFile(this.getApplicationContext()); 132 | 133 | Bundle extras = getIntent().getExtras(); 134 | if (extras != null) { 135 | if (extras.containsKey("action")) { 136 | action = extras.getString("action"); 137 | } 138 | if (extras.containsKey("accountname")) { 139 | accountname = extras.getString("accountname"); 140 | } 141 | } 142 | 143 | if (this.settings != null) { 144 | this.accountnameTextView.setText(this.settings.GetAccountname()); 145 | this.usernameTextView.setText(this.settings.GetUsername()); 146 | this.passwordTextView.setText(this.settings.GetPassword()); 147 | this.serverTextView.setText(this.settings.GetServer()); 148 | this.portnumTextView.setText(this.settings.GetPortnum()); 149 | this.security = this.settings.GetSecurity(); 150 | if (this.security == null) this.security = "0"; 151 | this.security_i = Integer.parseInt(this.security); 152 | this.securitySpinner.setSelection(this.security_i); 153 | this.stickyCheckBox.setChecked(Boolean.parseBoolean(this.settings.GetUsesticky())); 154 | this.syncintervalTextView.setText("15"); 155 | this.folderTextView.setText(this.settings.GetFoldername()); 156 | } 157 | 158 | LinearLayout layout = (LinearLayout) findViewById(R.id.bttonsLayout); 159 | accountManager = AccountManager.get(getApplicationContext()); 160 | Account[] accounts = accountManager.getAccountsByType("com.Pau.ImapNotes2"); 161 | for (Account account : accounts) { 162 | if (account.name.equals(accountname)) { 163 | myAccount = account; 164 | break; 165 | } 166 | } 167 | 168 | if ((this.action == null) || (this.myAccount == null)) { this.action = "CREATE_ACCOUNT"; } 169 | 170 | if (this.action.equals("EDIT_ACCOUNT")) { 171 | // Here we have to edit an existing account 172 | this.accountnameTextView.setText(this.accountname); 173 | this.usernameTextView.setText(this.accountManager.getUserData (myAccount, "username")); 174 | this.passwordTextView.setText(this.accountManager.getPassword(myAccount)); 175 | this.serverTextView.setText(this.accountManager.getUserData(myAccount, "server")); 176 | this.portnumTextView.setText(this.accountManager.getUserData(myAccount, "portnum")); 177 | this.security = this.accountManager.getUserData (myAccount, "security"); 178 | this.stickyCheckBox.setChecked(Boolean.parseBoolean(this.accountManager.getUserData(myAccount,"usesticky"))); 179 | this.syncintervalTextView.setText(this.accountManager.getUserData(myAccount, "syncinterval")); 180 | this.folderTextView.setText(this.accountManager.getUserData (myAccount, "imapfolder")); 181 | if (this.security == null) this.security = "0"; 182 | this.security_i = Integer.parseInt(this.security); 183 | this.securitySpinner.setSelection(this.security_i); 184 | Button buttonEdit = new Button(this); 185 | buttonEdit.setText("Save"); 186 | buttonEdit.setOnClickListener(clickListenerEdit); 187 | layout.addView(buttonEdit); 188 | Button buttonRemove = new Button(this); 189 | buttonRemove.setText("Remove"); 190 | buttonRemove.setOnClickListener(clickListenerRemove); 191 | layout.addView(buttonRemove); 192 | } else { 193 | // Here we have to create a new account 194 | Button buttonView = new Button(this); 195 | buttonView.setText("Check & Create Account"); 196 | buttonView.setOnClickListener(clickListenerLogin); 197 | layout.addView(buttonView); 198 | } 199 | 200 | // Don't display keyboard when on note detail, only if user touches the screen 201 | getWindow().setSoftInputMode( 202 | WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN 203 | ); 204 | } 205 | 206 | // DoLogin method is defined in account_selection.xml (account_selection layout) 207 | public void DoLogin(View v) { 208 | ProgressDialog loadingDialog = ProgressDialog.show(this, "ImapNotes2" , "Logging into your account... ", true); 209 | this.imapNotes2Account.SetAccountname(this.accountnameTextView.getText().toString().trim()); 210 | this.imapNotes2Account.SetUsername(this.usernameTextView.getText().toString().trim()); 211 | this.imapNotes2Account.SetPassword(this.passwordTextView.getText().toString().trim()); 212 | this.imapNotes2Account.SetServer(this.serverTextView.getText().toString().trim()); 213 | this.imapNotes2Account.SetPortnum(this.portnumTextView.getText().toString()); 214 | this.imapNotes2Account.SetSecurity(this.security); 215 | this.imapNotes2Account.SetUsesticky(String.valueOf(this.stickyCheckBox.isChecked())); 216 | this.imapNotes2Account.SetSyncinterval(this.syncintervalTextView.getText().toString()); 217 | this.imapNotes2Account.SetFoldername(this.folderTextView.getText().toString()); 218 | long SYNC_FREQUENCY = Long.parseLong(syncintervalTextView.getText().toString(), 10) * 60; 219 | new LoginThread().execute(this.imapFolder, this.imapNotes2Account, loadingDialog, this, this.action, SYNC_FREQUENCY); 220 | 221 | } 222 | 223 | class LoginThread extends AsyncTask { 224 | 225 | private AccontConfigurationActivity accontConfigurationActivity; 226 | private ImapNotes2Result res = new ImapNotes2Result(); 227 | String action; 228 | 229 | protected Boolean doInBackground(Object... stuffs) { 230 | this.action = (String)stuffs[4]; 231 | try { 232 | this.res=((Imaper)stuffs[0]).ConnectToProvider( 233 | ((ImapNotes2Account)stuffs[1]).GetUsername(), 234 | ((ImapNotes2Account)stuffs[1]).GetPassword(), 235 | ((ImapNotes2Account)stuffs[1]).GetServer(), 236 | ((ImapNotes2Account)stuffs[1]).GetPortnum(), 237 | ((ImapNotes2Account)stuffs[1]).GetSecurity(), 238 | ((ImapNotes2Account)stuffs[1]).GetUsesticky(), 239 | ((ImapNotes2Account)stuffs[1]).GetFoldername()); 240 | accontConfigurationActivity = (AccontConfigurationActivity)stuffs[3]; 241 | if (this.res.returnCode==0) { 242 | Account account = new Account(((ImapNotes2Account)stuffs[1]).GetAccountname(), "com.Pau.ImapNotes2"); 243 | long SYNC_FREQUENCY = (long)stuffs[5]; 244 | AccountManager am = AccountManager.get(((AccontConfigurationActivity)stuffs[3])); 245 | accontConfigurationActivity.setResult(AccontConfigurationActivity.TO_REFRESH); 246 | Bundle result = null; 247 | if (this.action.equals("EDIT_ACCOUNT")) { 248 | result = new Bundle(); 249 | result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name); 250 | result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type); 251 | setAccountAuthenticatorResult(result); 252 | am.setUserData(account, "username", ((ImapNotes2Account)stuffs[1]).GetUsername()); 253 | am.setUserData(account, "server", ((ImapNotes2Account)stuffs[1]).GetServer()); 254 | am.setUserData(account, "portnum", ((ImapNotes2Account)stuffs[1]).GetPortnum()); 255 | am.setUserData(account, "syncinterval", ((ImapNotes2Account)stuffs[1]).GetSyncinterval()); 256 | am.setUserData(account, "security", ((ImapNotes2Account)stuffs[1]).GetSecurity()); 257 | am.setUserData(account, "usesticky", ((ImapNotes2Account)stuffs[1]).GetUsesticky()); 258 | am.setUserData(account, "imapfolder", ((ImapNotes2Account)stuffs[1]).GetFoldername()); 259 | // Run the Sync Adapter Periodically 260 | ContentResolver.setIsSyncable(account, AUTHORITY, 1); 261 | ContentResolver.setSyncAutomatically(account, AUTHORITY, true); 262 | ContentResolver.addPeriodicSync(account, AUTHORITY, new Bundle(), SYNC_FREQUENCY); 263 | this.res.errorMessage = "Account has been modified"; 264 | return true; 265 | } else { 266 | if (am.addAccountExplicitly(account, ((ImapNotes2Account)stuffs[1]).GetPassword(), null)) { 267 | result = new Bundle(); 268 | result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name); 269 | result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type); 270 | setAccountAuthenticatorResult(result); 271 | am.setUserData(account, "username", ((ImapNotes2Account)stuffs[1]).GetUsername()); 272 | am.setUserData(account, "server", ((ImapNotes2Account)stuffs[1]).GetServer()); 273 | am.setUserData(account, "portnum", ((ImapNotes2Account)stuffs[1]).GetPortnum()); 274 | am.setUserData(account, "syncinterval", ((ImapNotes2Account)stuffs[1]).GetSyncinterval()); 275 | am.setUserData(account, "security", ((ImapNotes2Account)stuffs[1]).GetSecurity()); 276 | am.setUserData(account, "usesticky", ((ImapNotes2Account)stuffs[1]).GetUsesticky()); 277 | am.setUserData(account, "imapfolder", ((ImapNotes2Account)stuffs[1]).GetFoldername()); 278 | // Run the Sync Adapter Periodically 279 | ContentResolver.setIsSyncable(account, AUTHORITY, 1); 280 | ContentResolver.setSyncAutomatically(account, AUTHORITY, true); 281 | ContentResolver.addPeriodicSync(account, AUTHORITY, new Bundle(), SYNC_FREQUENCY); 282 | this.res.errorMessage = "Account has been added"; 283 | return true; 284 | } else { 285 | this.res.errorMessage = "Account already exists or is null"; 286 | return false; 287 | } 288 | } 289 | } 290 | } catch (Exception e) { 291 | e.printStackTrace(); 292 | } finally { 293 | ((ProgressDialog)stuffs[2]).dismiss(); 294 | } 295 | return false; 296 | } 297 | 298 | protected void onPostExecute(Boolean result){ 299 | if(result){ 300 | accontConfigurationActivity.settings.Clear(); 301 | this.accontConfigurationActivity.accountnameTextView.setText(""); 302 | this.accontConfigurationActivity.usernameTextView.setText(""); 303 | this.accontConfigurationActivity.passwordTextView.setText(""); 304 | this.accontConfigurationActivity.serverTextView.setText(""); 305 | this.accontConfigurationActivity.portnumTextView.setText(""); 306 | this.accontConfigurationActivity.syncintervalTextView.setText("15"); 307 | this.accontConfigurationActivity.securitySpinner.setSelection(0); 308 | this.accontConfigurationActivity.folderTextView.setText(""); 309 | this.accontConfigurationActivity.stickyCheckBox.setChecked(false); 310 | } 311 | final Toast tag = Toast.makeText(getApplicationContext(), this.res.errorMessage,Toast.LENGTH_LONG); 312 | tag.show(); 313 | new CountDownTimer(5000, 1000) { 314 | public void onTick(long millisUntilFinished) {tag.show();} 315 | public void onFinish() {tag.show();} 316 | }.start(); 317 | if (this.action.equals("EDIT_ACCOUNT")) finish(); 318 | } 319 | } 320 | 321 | public boolean onCreateOptionsMenu(Menu menu) { 322 | return true; 323 | } 324 | 325 | public boolean onOptionsItemSelected (MenuItem item){ 326 | switch (item.getItemId()){ 327 | case android.R.id.home: 328 | NavUtils.navigateUpFromSameTask(this); 329 | return true; 330 | default: 331 | return super.onOptionsItemSelected(item); 332 | } 333 | } 334 | 335 | @Override 336 | public void onItemSelected(AdapterView parent, View view, int position, long id) { 337 | this.security = Integer.toString(position); 338 | if ((position == 0) || (position == 3) || (position == 4)) 339 | this.portnumTextView.setText("143"); 340 | if ((position == 1) || (position == 2)) 341 | this.portnumTextView.setText("993"); 342 | } 343 | 344 | @Override 345 | public void onNothingSelected(AdapterView parent) { 346 | // TODO Auto-generated method stub 347 | } 348 | 349 | } 350 | -------------------------------------------------------------------------------- /ImapNote2/src/main/java/com/Pau/ImapNotes2/Data/ConfigurationFile.java: -------------------------------------------------------------------------------- 1 | package com.Pau.ImapNotes2.Data; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.IOException; 6 | 7 | import javax.xml.parsers.DocumentBuilderFactory; 8 | 9 | import org.w3c.dom.Document; 10 | import org.w3c.dom.NodeList; 11 | import org.xmlpull.v1.XmlSerializer; 12 | 13 | import android.content.Context; 14 | import android.util.Log; 15 | import android.util.Xml; 16 | 17 | public class ConfigurationFile { 18 | 19 | private Context applicationContext; 20 | private static final String TAG = "IN_ConfigurationFile"; 21 | 22 | private String accountname; 23 | private String username; 24 | private String password; 25 | private String server; 26 | private String portnum; 27 | private String security; 28 | private String usesticky; 29 | private String imapfolder; 30 | 31 | 32 | public ConfigurationFile(Context myContext){ 33 | this.applicationContext = myContext; 34 | 35 | try { 36 | Document fileToLoad = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse( 37 | new File(this.applicationContext.getFilesDir()+"/ImapNotes2.conf")); 38 | this.username = this.LoadItemFromXML(fileToLoad, "username").item(0).getChildNodes().item(0).getNodeValue(); 39 | this.password = this.LoadItemFromXML(fileToLoad, "password").item(0).getChildNodes().item(0).getNodeValue(); 40 | this.server = this.LoadItemFromXML(fileToLoad, "server").item(0).getChildNodes().item(0).getNodeValue(); 41 | this.imapfolder = this.LoadItemFromXML(fileToLoad, "imapfolder").item(0).getChildNodes().item(0).getNodeValue(); 42 | this.accountname = this.username + "@" + this.server; 43 | if (this.LoadItemFromXML(fileToLoad, "portnum").getLength() == 0) 44 | // portnum option doesn't exist 45 | this.portnum = ""; 46 | else 47 | this.portnum = this.LoadItemFromXML(fileToLoad, "portnum").item(0).getChildNodes().item(0).getNodeValue(); 48 | if (this.LoadItemFromXML(fileToLoad, "security").getLength() == 0) 49 | // security option doesn't exist, say "0" 50 | this.security = "0"; 51 | else 52 | this.security = this.LoadItemFromXML(fileToLoad, "security").item(0).getChildNodes().item(0).getNodeValue(); 53 | if (this.LoadItemFromXML(fileToLoad, "usesticky").getLength() == 0) 54 | // usesticky option doesn't exist, say no 55 | this.usesticky = "false"; 56 | else 57 | this.usesticky = this.LoadItemFromXML(fileToLoad, "usesticky").item(0).getChildNodes().item(0).getNodeValue(); 58 | 59 | //Log.d(TAG, "conf file present, we read data"); 60 | } catch (Exception e) { 61 | //Log.d(TAG, "Conf file absent, go to the exception that initializes variables"); 62 | this.accountname = ""; 63 | this.username = ""; 64 | this.password = ""; 65 | this.server = ""; 66 | this.portnum = ""; 67 | this.security = "0"; 68 | this.usesticky = "false"; 69 | this.imapfolder = ""; 70 | } 71 | } 72 | 73 | public String GetAccountname(){ 74 | return this.accountname; 75 | } 76 | 77 | public String GetUsername(){ 78 | return this.username; 79 | } 80 | 81 | public void SetUsername(String Username){ 82 | this.username = Username; 83 | } 84 | 85 | public String GetPassword(){ 86 | return this.password; 87 | } 88 | 89 | public void SetPassword(String Password){ 90 | this.password = Password; 91 | } 92 | 93 | public String GetServer(){ 94 | return this.server; 95 | } 96 | 97 | public void SetServer(String Server){ 98 | this.server = Server; 99 | } 100 | 101 | public String GetPortnum(){ 102 | return this.portnum; 103 | } 104 | 105 | public void SetPortnum(String Portnum){ 106 | this.portnum = Portnum; 107 | } 108 | 109 | public String GetSecurity(){ 110 | return this.security; 111 | } 112 | 113 | public void SetSecurity(String Security){ 114 | this.security = Security; 115 | } 116 | 117 | public String GetUsesticky(){ 118 | return this.usesticky; 119 | } 120 | 121 | public void SetUsesticky(String Usesticky){ 122 | this.usesticky = Usesticky; 123 | } 124 | 125 | public String GetFoldername(){ 126 | return this.imapfolder; 127 | } 128 | 129 | public void Clear(){ 130 | new File(this.applicationContext.getFilesDir()+"/ImapNotes2.conf").delete(); 131 | this.username=null; 132 | this.password=null; 133 | this.server=null; 134 | this.portnum=null; 135 | this.security=null; 136 | this.usesticky=null; 137 | this.imapfolder = null; 138 | } 139 | 140 | public void SaveConfigurationToXML() throws IllegalArgumentException, IllegalStateException, IOException{ 141 | FileOutputStream configurationFile = this.applicationContext.openFileOutput("ImapNotes2.conf", Context.MODE_PRIVATE); 142 | XmlSerializer serializer = Xml.newSerializer(); 143 | serializer.setOutput(configurationFile, "UTF-8"); 144 | serializer.startDocument(null, Boolean.valueOf(true)); 145 | serializer.startTag(null, "Configuration"); 146 | serializer.startTag(null, "username"); 147 | serializer.text(this.username); 148 | serializer.endTag(null, "username"); 149 | serializer.startTag(null, "password"); 150 | serializer.text(this.password); 151 | serializer.endTag(null, "password"); 152 | serializer.startTag(null, "server"); 153 | serializer.text(this.server); 154 | serializer.endTag(null, "server"); 155 | serializer.startTag(null, "portnum"); 156 | serializer.text(this.portnum); 157 | serializer.endTag(null, "portnum"); 158 | serializer.startTag(null, "security"); 159 | serializer.text(this.security); 160 | serializer.endTag(null, "security"); 161 | serializer.startTag(null,"imapfolder"); 162 | serializer.text(this.imapfolder); 163 | serializer.endTag(null, "imapfolder"); 164 | serializer.startTag(null, "usesticky"); 165 | serializer.text(this.usesticky); 166 | serializer.endTag(null, "usesticky"); 167 | serializer.endTag(null, "Configuration"); 168 | serializer.endDocument(); 169 | serializer.flush(); 170 | configurationFile.close(); 171 | } 172 | 173 | private NodeList LoadItemFromXML(Document fileLoaded, String tag){ 174 | return fileLoaded.getElementsByTagName(tag); 175 | 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /ImapNote2/src/main/java/com/Pau/ImapNotes2/Data/ImapNotes2Account.java: -------------------------------------------------------------------------------- 1 | package com.Pau.ImapNotes2.Data; 2 | 3 | import android.accounts.Account; 4 | 5 | public class ImapNotes2Account { 6 | 7 | private String accountname = ""; 8 | private String username = ""; 9 | private String password = ""; 10 | private String server = ""; 11 | private String portnum = ""; 12 | private String security = ""; 13 | private String usesticky = ""; 14 | private String syncinterval = "15"; 15 | private String imapfolder = ""; 16 | private Boolean accountHasChanged = false; 17 | private Account account = null; 18 | 19 | 20 | public ImapNotes2Account() { 21 | } 22 | 23 | public String toString() { 24 | return this.accountname + ":" + this.username + ":" + this.password + ":" 25 | + this.server + ":" + this.portnum + ":" + this.security + ":" 26 | + this.usesticky + ":" + this.imapfolder + ":" + this.accountHasChanged.toString(); 27 | } 28 | 29 | public String GetAccountname() { 30 | return this.accountname; 31 | } 32 | 33 | public void SetAccount(Account account) { 34 | this.account = account; 35 | } 36 | 37 | public Account GetAccount() { 38 | return this.account; 39 | } 40 | 41 | public void SetAccountname(String Accountname) { 42 | if (this.accountname.equals(Accountname)) this.accountHasChanged = true; 43 | this.accountname = Accountname; 44 | } 45 | 46 | public String GetUsername() { 47 | return this.username; 48 | } 49 | 50 | public void SetUsername(String Username) { 51 | this.username = Username; 52 | } 53 | 54 | public String GetPassword() { 55 | return this.password; 56 | } 57 | 58 | public void SetPassword(String Password) { 59 | this.password = Password; 60 | } 61 | 62 | public String GetServer() { 63 | return this.server; 64 | } 65 | 66 | public void SetServer(String Server) { 67 | this.server = Server; 68 | } 69 | 70 | public String GetPortnum() { 71 | return this.portnum; 72 | } 73 | 74 | public void SetPortnum(String Portnum) { 75 | this.portnum = Portnum; 76 | } 77 | 78 | public String GetSecurity() { 79 | return this.security; 80 | } 81 | 82 | public void SetSecurity(String Security) { 83 | this.security = Security; 84 | } 85 | 86 | public String GetUsesticky() { 87 | return this.usesticky; 88 | } 89 | 90 | public void SetUsesticky(String Usesticky) { 91 | this.usesticky = Usesticky; 92 | } 93 | 94 | public String GetSyncinterval() { 95 | return this.syncinterval; 96 | } 97 | 98 | public void SetSyncinterval(String Syncinterval) { 99 | this.syncinterval = Syncinterval; 100 | } 101 | 102 | public void SetaccountHasChanged() { 103 | this.accountHasChanged = true; 104 | } 105 | 106 | public void SetaccountHasNotChanged() { 107 | this.accountHasChanged = false; 108 | } 109 | 110 | public Boolean GetaccountHasChanged() { 111 | return this.accountHasChanged; 112 | } 113 | 114 | public String GetFoldername(){ 115 | return this.imapfolder; 116 | } 117 | 118 | public void SetFoldername(String folder) { 119 | this.imapfolder = folder; 120 | } 121 | 122 | public void Clear() { 123 | this.username=null; 124 | this.password=null; 125 | this.server=null; 126 | this.portnum=null; 127 | this.security=null; 128 | this.usesticky=null; 129 | this.imapfolder=null; 130 | this.accountHasChanged=false; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /ImapNote2/src/main/java/com/Pau/ImapNotes2/Data/NotesDb.java: -------------------------------------------------------------------------------- 1 | package com.Pau.ImapNotes2.Data; 2 | 3 | import java.text.DateFormat; 4 | import java.text.ParseException; 5 | import java.text.SimpleDateFormat; 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.Date; 9 | 10 | import com.Pau.ImapNotes2.Miscs.OneNote; 11 | 12 | import android.content.ContentValues; 13 | import android.content.Context; 14 | import android.database.Cursor; 15 | import android.database.sqlite.SQLiteDatabase; 16 | import android.database.sqlite.SQLiteOpenHelper; 17 | import android.util.Log; 18 | 19 | public class NotesDb { 20 | 21 | private static final int NOTES_VERSION = 3; 22 | private static final String TAG = "IN_NotesDb"; 23 | private Context ctx; 24 | 25 | private static final String CREATE_NOTES_DB = "CREATE TABLE IF NOT EXISTS " 26 | + "notesTable (" 27 | + "pk integer primary key autoincrement, " 28 | + "title text not null, " 29 | + "date text not null, " 30 | + "number text not null, " 31 | + "accountname text not null);"; 32 | 33 | private SQLiteDatabase notesDb; 34 | private NotesDbHelper defaultHelper; 35 | 36 | public NotesDb(Context applicationContext){ 37 | this.defaultHelper = new NotesDbHelper(applicationContext, "NotesDb", NOTES_VERSION); 38 | this.ctx = applicationContext; 39 | 40 | } 41 | 42 | public void OpenDb(){ 43 | this.notesDb = this.defaultHelper.getWritableDatabase(); 44 | 45 | } 46 | 47 | public void CloseDb(){ 48 | this.notesDb.close(); 49 | 50 | } 51 | 52 | public void InsertANoteInDb(OneNote noteElement, String accountname){ 53 | ContentValues tableRow = new ContentValues(); 54 | tableRow.put("title", (noteElement.GetTitle() != null) ? noteElement.GetTitle() : ""); 55 | tableRow.put("date", noteElement.GetDate()); 56 | tableRow.put("number", noteElement.GetUid()); 57 | tableRow.put("accountname", accountname); 58 | this.notesDb.insert("notesTable", null, tableRow); 59 | //Log.d(TAG, "note inserted"); 60 | } 61 | 62 | public void DeleteANote(String number, String accountname){ 63 | this.notesDb.execSQL("delete from notesTable where number = '" + number + 64 | "' and accountname = '" + accountname + "'"); 65 | } 66 | 67 | public void UpdateANote(String olduid, String newuid, String accountname){ 68 | String req = "update notesTable set number='" + newuid + "' where number='-" + olduid + "' and accountname='" + accountname + "'"; 69 | this.notesDb.execSQL(req); 70 | } 71 | 72 | public String GetDate(String uid, String accountname){ 73 | String selectQuery = "select date from notesTable where number = '" + uid + "' and accountname='"+accountname+"'"; 74 | Cursor c = this.notesDb.rawQuery(selectQuery, null); 75 | if (c.moveToFirst()) { 76 | return c.getString(0); 77 | } 78 | return ""; 79 | } 80 | 81 | public String GetTempNumber(String accountname) { 82 | String selectQuery = "select case when cast(max(abs(number)+1) as int) > 0 then cast(max(abs(number)+1) as int)*-1 else '-1' end from notesTable where number < '0' and accountname='"+accountname+"'"; 83 | Cursor c = this.notesDb.rawQuery(selectQuery, null); 84 | if (c.moveToFirst()) { 85 | return c.getString(0); 86 | } 87 | return "-1"; 88 | } 89 | 90 | public void GetStoredNotes(ArrayList noteList, String accountname){ 91 | noteList.clear(); 92 | Date date=null; 93 | Cursor resultPointer = this.notesDb.query("notesTable", null,"accountname = ?", new String[]{accountname},null,null,"date DESC"); 94 | 95 | if(resultPointer.moveToFirst()){ 96 | int titleIndex = resultPointer.getColumnIndex("title"); 97 | int bodyIndex = resultPointer.getColumnIndex("body"); 98 | int dateIndex = resultPointer.getColumnIndex("date"); 99 | int numberIndex = resultPointer.getColumnIndex("number"); 100 | int positionIndex = resultPointer.getColumnIndex("position"); 101 | int colorIndex = resultPointer.getColumnIndex("color"); 102 | do { 103 | String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; 104 | SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT); 105 | try { 106 | date = sdf.parse(resultPointer.getString(dateIndex)); 107 | } catch(ParseException e){ 108 | //Exception handling 109 | } catch(Exception e){ 110 | //handle exception 111 | } 112 | DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(this.ctx); 113 | //String sdate = dateFormat.format(date); 114 | String sdate = DateFormat.getDateTimeInstance().format(date); 115 | 116 | noteList.add(new OneNote(resultPointer.getString(titleIndex), 117 | sdate, 118 | resultPointer.getString(numberIndex))); 119 | } while (resultPointer.moveToNext()); 120 | } 121 | 122 | } 123 | 124 | public void ClearDb(String accountname){ 125 | this.notesDb.execSQL("delete from notesTable where accountname = '" + accountname+"'"); 126 | 127 | } 128 | 129 | /** 130 | * Database helper that creates and maintains the SQLite database. 131 | */ 132 | 133 | private static class NotesDbHelper extends SQLiteOpenHelper { 134 | 135 | public NotesDbHelper(Context currentApplicationContext, String dbName, int dbVersion) { 136 | super(currentApplicationContext, dbName, null, dbVersion); 137 | } 138 | 139 | @Override 140 | public void onCreate(SQLiteDatabase _db) { 141 | _db.execSQL(NotesDb.CREATE_NOTES_DB); 142 | } 143 | 144 | @Override 145 | public void onUpgrade(SQLiteDatabase _db, int oldVersion, int newVersion) { 146 | //Log.d(TAG,"onUpgrade from:"+oldVersion+" to:"+newVersion); 147 | for (int i=oldVersion; i noteList; 17 | private static Context context; 18 | 19 | public void onCreate(){ 20 | super.onCreate(); 21 | ImapNotes2.context = getApplicationContext(); 22 | } 23 | 24 | public static Context getAppContext() { 25 | return ImapNotes2.context; 26 | } 27 | 28 | public void SetConfigurationFile(ConfigurationFile currentSettings){ 29 | this.thisSessionConfigurationFile = currentSettings; 30 | } 31 | 32 | public ConfigurationFile GetConfigurationFile(){ 33 | return this.thisSessionConfigurationFile; 34 | } 35 | 36 | public void SetImaper(Imaper currentImaper){ 37 | this.thisSessionImapFolder = currentImaper; 38 | } 39 | 40 | public Imaper GetImaper(){ 41 | return this.thisSessionImapFolder; 42 | } 43 | 44 | public void SetNotesList(ArrayList currentNotesList){ 45 | this.noteList = currentNotesList; 46 | } 47 | 48 | public ArrayList GetNotesList(){ 49 | return this.noteList; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /ImapNote2/src/main/java/com/Pau/ImapNotes2/Listactivity.java: -------------------------------------------------------------------------------- 1 | package com.Pau.ImapNotes2; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.IOException; 6 | import java.io.InputStreamReader; 7 | import java.text.DateFormat; 8 | import java.util.ArrayList; 9 | import java.util.Date; 10 | import java.util.List; 11 | import java.util.ListIterator; 12 | 13 | import org.apache.commons.io.FileUtils; 14 | 15 | import com.Pau.ImapNotes2.R; 16 | import com.Pau.ImapNotes2.Data.NotesDb; 17 | import com.Pau.ImapNotes2.Miscs.Imaper; 18 | import com.Pau.ImapNotes2.Miscs.OneNote; 19 | import com.Pau.ImapNotes2.Data.ImapNotes2Account; 20 | import com.Pau.ImapNotes2.Miscs.UpdateThread; 21 | import com.Pau.ImapNotes2.Miscs.SyncThread; 22 | import com.Pau.ImapNotes2.Sync.SyncService; 23 | import com.Pau.ImapNotes2.Sync.SyncUtils; 24 | 25 | import android.accounts.Account; 26 | import android.accounts.AccountManager; 27 | import android.accounts.OnAccountsUpdateListener; 28 | import android.app.Activity; 29 | import android.app.AlertDialog; 30 | import android.app.ProgressDialog; 31 | import android.app.SearchManager; 32 | import android.content.BroadcastReceiver; 33 | import android.content.ComponentName; 34 | import android.content.ContentResolver; 35 | import android.content.Context; 36 | import android.content.DialogInterface; 37 | import android.content.Intent; 38 | import android.content.IntentFilter; 39 | import android.content.PeriodicSync; 40 | import android.content.pm.PackageInfo; 41 | import android.os.Bundle; 42 | import android.util.Log; 43 | import android.view.Menu; 44 | import android.view.MenuItem; 45 | import android.view.View; 46 | import android.view.View.OnClickListener; 47 | import android.widget.AdapterView; 48 | import android.widget.AdapterView.OnItemClickListener; 49 | import android.widget.AdapterView.OnItemSelectedListener; 50 | import android.widget.ArrayAdapter; 51 | import android.widget.Button; 52 | import android.widget.Filter; 53 | import android.widget.Filterable; 54 | import android.widget.ListView; 55 | import android.widget.SearchView; 56 | import android.widget.SimpleAdapter; 57 | import android.widget.Spinner; 58 | import android.widget.TextView; 59 | import android.widget.Toast; 60 | 61 | public class Listactivity extends Activity implements OnItemSelectedListener,Filterable { 62 | private static final int SEE_DETAIL = 2; 63 | private static final int DELETE_BUTTON = 3; 64 | private static final int NEW_BUTTON = 4; 65 | private static final int SAVE_BUTTON = 5; 66 | private static final int EDIT_BUTTON = 6; 67 | 68 | private ArrayList noteList; 69 | private NotesListAdapter listToView; 70 | private ArrayAdapter spinnerList; 71 | 72 | private Imaper imapFolder; 73 | private static NotesDb storedNotes = null; 74 | private Spinner accountSpinner; 75 | public static ImapNotes2Account imapNotes2Account; 76 | private static AccountManager accountManager; 77 | private static Account[] accounts; 78 | private static List currentList; 79 | private TextView status = null; 80 | private static String OldStatus; 81 | private Button editAccountButton=null; 82 | private ListView listview; 83 | public static final String AUTHORITY = "com.Pau.ImapNotes2.provider"; 84 | private static final String TAG = "IN_Listactivity"; 85 | 86 | 87 | private OnClickListener clickListenerEditAccount = new View.OnClickListener() { 88 | @Override 89 | public void onClick(View v) { 90 | // Clic on editAccount Button 91 | Intent res = new Intent(); 92 | String mPackage = "com.Pau.ImapNotes2"; 93 | String mClass = ".AccontConfigurationActivity"; 94 | res.setComponent(new ComponentName(mPackage,mPackage+mClass)); 95 | res.putExtra("action", "EDIT_ACCOUNT"); 96 | res.putExtra("accountname", Listactivity.imapNotes2Account.GetAccountname()); 97 | startActivity(res); 98 | } 99 | }; 100 | 101 | /** Called when the activity is first created. */ 102 | @Override 103 | public void onCreate(Bundle savedInstanceState) { 104 | super.onCreate(savedInstanceState); 105 | setContentView(R.layout.main); 106 | 107 | // Accounts spinner 108 | this.accountSpinner = (Spinner) findViewById(R.id.accountSpinner); 109 | Listactivity.currentList = new ArrayList(); 110 | // Spinner item selection Listener 111 | this.accountSpinner.setOnItemSelectedListener(this); 112 | 113 | imapNotes2Account = new ImapNotes2Account(); 114 | Listactivity.accountManager = AccountManager.get(getApplicationContext()); 115 | Listactivity.accountManager.addOnAccountsUpdatedListener((OnAccountsUpdateListener) 116 | new AccountsUpdateListener(), null, true); 117 | 118 | status = (TextView)findViewById(R.id.status); 119 | 120 | this.spinnerList = new ArrayAdapter 121 | (this, android.R.layout.simple_spinner_item,Listactivity.currentList); 122 | spinnerList.setDropDownViewResource 123 | (android.R.layout.simple_spinner_dropdown_item); 124 | this.accountSpinner.setAdapter(spinnerList); 125 | 126 | this.noteList = new ArrayList(); 127 | ((ImapNotes2)this.getApplicationContext()).SetNotesList(this.noteList); 128 | this.listToView = new NotesListAdapter( 129 | getApplicationContext(), 130 | this.noteList, 131 | R.layout.note_element, 132 | new String[]{"title","date"}, 133 | new int[]{R.id.noteTitle, R.id.noteInformation}); 134 | listview = (ListView) findViewById(R.id.notesList); 135 | listview.setAdapter(this.listToView); 136 | 137 | listview.setTextFilterEnabled(true); 138 | 139 | this.imapFolder = new Imaper(); 140 | ((ImapNotes2)this.getApplicationContext()).SetImaper(this.imapFolder); 141 | 142 | if (Listactivity.storedNotes == null) 143 | storedNotes = new NotesDb(getApplicationContext()); 144 | 145 | // When item is clicked, we go to NoteDetailActivity 146 | listview.setOnItemClickListener(new OnItemClickListener() { 147 | public void onItemClick(AdapterView arg0, View widget, int selectedNote, long arg3) { 148 | Intent toDetail = new Intent(widget.getContext(), NoteDetailActivity.class); 149 | toDetail.putExtra("selectedNote", (OneNote)arg0.getItemAtPosition(selectedNote)); 150 | toDetail.putExtra("useSticky", Listactivity.imapNotes2Account.GetUsesticky()); 151 | startActivityForResult(toDetail,SEE_DETAIL); 152 | } 153 | }); 154 | 155 | editAccountButton = (Button) findViewById(R.id.editAccountButton); 156 | editAccountButton.setOnClickListener(clickListenerEditAccount); 157 | 158 | } 159 | 160 | public void onDestroy() { 161 | super.onDestroy(); 162 | // in case of debug, uncomment next instruction 163 | // logcat will be sent by mail 164 | // send mail action is done by the user, so he can refuse 165 | // SendLogcatMail(); 166 | // this.imapFolder.SetPrefs(); 167 | } 168 | 169 | public void onStart() { 170 | super.onStart(); 171 | int len = this.accounts == null ? 0 : this.accounts.length; 172 | if (len > 0) updateAccountSpinner(); 173 | } 174 | 175 | @Override 176 | protected void onResume() { 177 | super.onResume(); 178 | registerReceiver(syncFinishedReceiver, new IntentFilter(SyncService.SYNC_FINISHED)); 179 | } 180 | 181 | @Override 182 | protected void onPause() { 183 | super.onPause(); 184 | unregisterReceiver(syncFinishedReceiver); 185 | } 186 | 187 | private BroadcastReceiver syncFinishedReceiver = new BroadcastReceiver() { 188 | 189 | public void onReceive(Context context, Intent intent) { 190 | String accountname = intent.getStringExtra("ACCOUNTNAME"); 191 | Boolean isChanged = intent.getBooleanExtra("CHANGED", false); 192 | Boolean isSynced = intent.getBooleanExtra("SYNCED", false); 193 | String syncInterval = intent.getStringExtra("SYNCINTERVAL"); 194 | if (accountname.equals(Listactivity.imapNotes2Account.GetAccountname())) { 195 | if (isSynced) { 196 | // Display last sync date 197 | DateFormat dateFormat = 198 | android.text.format.DateFormat.getDateFormat(getApplicationContext()); 199 | Date date = new Date(); 200 | String sdate = DateFormat.getDateTimeInstance(DateFormat.SHORT,DateFormat.SHORT).format(date); 201 | String sinterval = " (interval:" + String.valueOf(syncInterval) + " min)"; 202 | status.setText("Last sync: " + sdate + sinterval); 203 | } else { 204 | status.setText(OldStatus); 205 | } 206 | 207 | if (isChanged) { 208 | if (Listactivity.storedNotes == null) 209 | storedNotes = new NotesDb(getApplicationContext()); 210 | storedNotes.OpenDb(); 211 | storedNotes.GetStoredNotes(noteList, accountname); 212 | listToView.notifyDataSetChanged(); 213 | storedNotes.CloseDb(); 214 | } 215 | } 216 | } 217 | }; 218 | 219 | public void RefreshList(){ 220 | ProgressDialog loadingDialog = ProgressDialog.show(this, "ImapNotes2" , "Refreshing notes list... ", true); 221 | 222 | new SyncThread().execute(this.imapFolder, Listactivity.imapNotes2Account, this.noteList, this.listToView, loadingDialog, this.storedNotes, this.getApplicationContext()); 223 | status.setText("Welcome"); 224 | } 225 | 226 | public void UpdateList(String suid, String noteBody, String color, String action){ 227 | ProgressDialog loadingDialog = ProgressDialog.show(this, "imapnote2" , "Updating notes list... ", true); 228 | 229 | new UpdateThread().execute(this.imapFolder, Listactivity.imapNotes2Account, this.noteList, this.listToView, loadingDialog, suid, noteBody, color, this.getApplicationContext(), action, this.storedNotes); 230 | 231 | } 232 | 233 | public boolean onCreateOptionsMenu(Menu menu){ 234 | getMenuInflater().inflate(R.menu.list, menu); 235 | 236 | // Associate searchable configuration with the SearchView 237 | SearchManager searchManager = 238 | (SearchManager) getSystemService(Context.SEARCH_SERVICE); 239 | SearchView searchView = 240 | (SearchView) menu.findItem(R.id.search).getActionView(); 241 | searchView.setSearchableInfo( 242 | searchManager.getSearchableInfo(getComponentName())); 243 | SearchView.OnQueryTextListener textChangeListener = new SearchView.OnQueryTextListener() { 244 | @Override 245 | public boolean onQueryTextChange(String newText) { 246 | // this is your adapter that will be filtered 247 | listToView.getFilter().filter(newText); 248 | return true; 249 | } 250 | 251 | @Override 252 | public boolean onQueryTextSubmit(String query) { 253 | // this is your adapter that will be filtered 254 | listToView.getFilter().filter(query); 255 | return true; 256 | } 257 | }; 258 | searchView.setOnQueryTextListener(textChangeListener); 259 | 260 | return true; 261 | } 262 | 263 | public boolean onOptionsItemSelected (MenuItem item){ 264 | switch (item.getItemId()){ 265 | case R.id.login: 266 | Intent res = new Intent(); 267 | String mPackage = "com.Pau.ImapNotes2"; 268 | String mClass = ".AccontConfigurationActivity"; 269 | res.setComponent(new ComponentName(mPackage,mPackage+mClass)); 270 | res.putExtra("action", "CREATE_ACCOUNT"); 271 | startActivity(res); 272 | return true; 273 | case R.id.refresh: 274 | this.TriggerSync(this.status); 275 | return true; 276 | case R.id.newnote: 277 | Intent toNew = new Intent(this, NewNoteActivity.class); 278 | toNew.putExtra("usesSticky", Listactivity.imapNotes2Account.GetUsesticky()); 279 | startActivityForResult(toNew,Listactivity.NEW_BUTTON); 280 | return true; 281 | case R.id.about: 282 | try { 283 | ComponentName comp = new ComponentName(this.getApplicationContext(), Listactivity.class); 284 | PackageInfo pinfo = this.getApplicationContext().getPackageManager().getPackageInfo(comp.getPackageName(), 0); 285 | String versionName = "Version: " + pinfo.versionName; 286 | String versionCode = "Code: " + String.valueOf(pinfo.versionCode); 287 | 288 | new AlertDialog.Builder(this) 289 | .setTitle("About ImapNotes2") 290 | .setMessage(versionName + "\n" + versionCode) 291 | .setPositiveButton("OK", new DialogInterface.OnClickListener() { 292 | public void onClick(DialogInterface dialog, int which) { 293 | // Do nothing 294 | } 295 | }) 296 | .show(); 297 | } catch (android.content.pm.PackageManager.NameNotFoundException e) { 298 | Log.d("XXXXX","except"); 299 | } 300 | return true; 301 | default: 302 | return super.onOptionsItemSelected(item); 303 | } 304 | } 305 | 306 | protected void onActivityResult(int requestCode, int resultCode, Intent data){ 307 | switch(requestCode) { 308 | case Listactivity.SEE_DETAIL: 309 | // Returning from NoteDetailActivity 310 | if (resultCode == Listactivity.DELETE_BUTTON) { 311 | // Delete Message asked for 312 | // String suid will contain the Message Imap UID to delete 313 | String suid = data.getStringExtra("DELETE_ITEM_NUM_IMAP"); 314 | this.UpdateList(suid, null, null, "delete"); 315 | } 316 | if (resultCode == Listactivity.EDIT_BUTTON) { 317 | String txt = data.getStringExtra("EDIT_ITEM_TXT"); 318 | String suid = data.getStringExtra("EDIT_ITEM_NUM_IMAP"); 319 | String color = data.getStringExtra("EDIT_ITEM_COLOR"); 320 | //Log.d(TAG,"Received request to delete message:"+suid); 321 | //Log.d(TAG,"Received request to replace message with:"+txt); 322 | this.UpdateList(suid, txt, color, "update"); 323 | } 324 | case Listactivity.NEW_BUTTON: 325 | // Returning from NewNoteActivity 326 | if (resultCode == Listactivity.SAVE_BUTTON) { 327 | String res = data.getStringExtra("SAVE_ITEM"); 328 | //Log.d(TAG,"Received request to save message:"+res); 329 | String color = data.getStringExtra("SAVE_ITEM_COLOR"); 330 | this.UpdateList(null, res, color, "insert"); 331 | } 332 | } 333 | } 334 | 335 | // Spinner item selected listener 336 | @Override 337 | public void onItemSelected(AdapterView parent, View view, int pos, long id) { 338 | ((TextView) this.accountSpinner.getSelectedView()).setBackgroundColor(0xFFB6B6B6); 339 | Account account = Listactivity.accounts[pos]; 340 | // Check periodic sync. If set to 86400 (once a day), set it to 900 (15 minutes) 341 | // this is due to bad upgrade to v4 which handles offline mode and syncing 342 | // Remove this code after V4.0 if version no more used 343 | List currentSyncs = ContentResolver.getPeriodicSyncs (account, AUTHORITY); 344 | for (PeriodicSync onesync : currentSyncs) { 345 | if (onesync.period == 86400) { 346 | ContentResolver.setIsSyncable(account, AUTHORITY, 1); 347 | ContentResolver.setSyncAutomatically(account, AUTHORITY, true); 348 | ContentResolver.addPeriodicSync(account, AUTHORITY, new Bundle(), 60); 349 | Toast.makeText(getApplicationContext(), "Recreating this account is recommended to manage sync interval. Set to 15 minutes in the meantime", 350 | Toast.LENGTH_LONG).show(); 351 | } 352 | } 353 | // End of code 354 | Listactivity.imapNotes2Account.SetAccountname(account.name); 355 | Listactivity.imapNotes2Account.SetUsername(Listactivity.accountManager.getUserData (account, "username")); 356 | String pwd = Listactivity.accountManager.getPassword(account); 357 | Listactivity.imapNotes2Account.SetPassword(pwd); 358 | Listactivity.imapNotes2Account.SetServer(Listactivity.accountManager.getUserData (account, "server")); 359 | Listactivity.imapNotes2Account.SetPortnum(Listactivity.accountManager.getUserData (account, "portnum")); 360 | Listactivity.imapNotes2Account.SetSecurity(Listactivity.accountManager.getUserData (account, "security")); 361 | Listactivity.imapNotes2Account.SetUsesticky(accountManager.getUserData (account, "usesticky")); 362 | Listactivity.imapNotes2Account.SetSyncinterval(Listactivity.accountManager.getUserData (account, "syncinterval")); 363 | Listactivity.imapNotes2Account.SetaccountHasChanged(); 364 | Listactivity.imapNotes2Account.SetAccount(account); 365 | this.RefreshList(); 366 | } 367 | 368 | @Override 369 | public void onNothingSelected(AdapterView parent) { 370 | // TODO Auto-generated method stub 371 | 372 | } 373 | 374 | private void updateAccountSpinner () { 375 | 376 | this.spinnerList.notifyDataSetChanged(); 377 | //this.accountSpinner.setSelection(spinnerList.getPosition(currentAccountname)); 378 | if (this.accountSpinner.getSelectedItemId() == android.widget.AdapterView.INVALID_ROW_ID) { 379 | this.accountSpinner.setSelection(0); 380 | } 381 | 382 | if (Listactivity.currentList.size() == 1) { 383 | Account account = Listactivity.accounts[0]; 384 | Listactivity.imapNotes2Account.SetUsername(Listactivity.accountManager.getUserData (account, "username")); 385 | String pwd = Listactivity.accountManager.getPassword(account); 386 | Listactivity.imapNotes2Account.SetPassword(pwd); 387 | Listactivity.imapNotes2Account.SetServer(Listactivity.accountManager.getUserData (account, "server")); 388 | Listactivity.imapNotes2Account.SetPortnum(Listactivity.accountManager.getUserData (account, "portnum")); 389 | Listactivity.imapNotes2Account.SetSecurity(Listactivity.accountManager.getUserData (account, "security")); 390 | Listactivity.imapNotes2Account.SetUsesticky(accountManager.getUserData (account, "usesticky")); 391 | Listactivity.imapNotes2Account.SetSyncinterval(Listactivity.accountManager.getUserData (account, "syncinterval")); 392 | Listactivity.imapNotes2Account.SetaccountHasChanged(); 393 | } 394 | } 395 | 396 | private class AccountsUpdateListener implements OnAccountsUpdateListener { 397 | private ArrayList newAccounts; 398 | 399 | @Override 400 | public void onAccountsUpdated(Account[] accounts) { 401 | List newList; 402 | Integer newListSize = 0; 403 | //invoked when the AccountManager starts up and whenever the account set changes 404 | this.newAccounts = new ArrayList(); 405 | for (final Account account : accounts) { 406 | if (account.type.equals("com.Pau.ImapNotes2")) { 407 | this.newAccounts.add(account); 408 | } 409 | } 410 | if (this.newAccounts.size() > 0) { 411 | Account[] imapNotes2Accounts = new Account[this.newAccounts.size()] ; 412 | int i = 0; 413 | for (final Account account : this.newAccounts) { 414 | imapNotes2Accounts[i] = account; 415 | i++; 416 | } 417 | Listactivity.accounts = imapNotes2Accounts; 418 | newList = new ArrayList(); 419 | for (Account account: Listactivity.accounts ) { 420 | newList.add(account.name); 421 | } 422 | if (newList.size() == 0) return; 423 | 424 | Boolean equalLists = true; 425 | ListIterator iter = Listactivity.currentList.listIterator(); 426 | while(iter.hasNext()){ 427 | String s = iter.next(); 428 | if (!(newList.contains(s))) { 429 | iter.remove(); 430 | String stringDir = (ImapNotes2.getAppContext()).getFilesDir() + "/" + s; 431 | try { 432 | FileUtils.deleteDirectory(new File (stringDir)); 433 | } catch (IOException e) { 434 | // TODO Auto-generated catch block 435 | e.printStackTrace(); 436 | } 437 | equalLists = false; 438 | } 439 | } 440 | for (String accountName: newList ) { 441 | if (!(Listactivity.currentList.contains(accountName))) { 442 | Listactivity.currentList.add(accountName); 443 | SyncUtils.CreateDirs (accountName, ImapNotes2.getAppContext()); 444 | 445 | equalLists = false; 446 | } 447 | } 448 | if (equalLists) return; 449 | updateAccountSpinner(); 450 | } else { 451 | File filesDir = (ImapNotes2.getAppContext()).getFilesDir(); 452 | try { 453 | FileUtils.cleanDirectory(filesDir); 454 | } catch (IOException e) { 455 | // TODO Auto-generated catch block 456 | e.printStackTrace(); 457 | } 458 | Intent res = new Intent(); 459 | String mPackage = "com.Pau.ImapNotes2"; 460 | String mClass = ".AccontConfigurationActivity"; 461 | res.setComponent(new ComponentName(mPackage,mPackage+mClass)); 462 | startActivity(res); 463 | } 464 | } 465 | } 466 | 467 | // In case of neccessary debug with user approval 468 | // This function will be called from onDestroy 469 | public void SendLogcatMail(){ 470 | String emailData=""; 471 | try { 472 | Process process = Runtime.getRuntime().exec("logcat -d"); 473 | BufferedReader bufferedReader = new BufferedReader( 474 | new InputStreamReader(process.getInputStream())); 475 | 476 | StringBuilder sb=new StringBuilder(); 477 | String line; 478 | while ((line = bufferedReader.readLine()) != null) { 479 | sb.append(line + "\n"); 480 | } 481 | emailData=sb.toString(); 482 | } catch (IOException e) { 483 | // TODO Auto-generated catch block 484 | e.printStackTrace(); 485 | } 486 | 487 | //send file using email 488 | Intent emailIntent = new Intent(Intent.ACTION_SEND); 489 | String to[] = {"nb@dagami.org"}; 490 | emailIntent .putExtra(Intent.EXTRA_EMAIL, to); 491 | // the attachment 492 | emailIntent .putExtra(Intent.EXTRA_TEXT, emailData); 493 | // the mail subject 494 | emailIntent .putExtra(Intent.EXTRA_SUBJECT, "Logcat content for ImapNotes2 debugging"); 495 | emailIntent.setType("message/rfc822"); 496 | startActivity(Intent.createChooser(emailIntent , "Send email...")); 497 | } 498 | 499 | public static void TriggerSync(TextView statusField) { 500 | OldStatus=statusField.getText().toString(); 501 | statusField.setText("Syncing..."); 502 | Account mAccount = Listactivity.imapNotes2Account.GetAccount(); 503 | Bundle settingsBundle = new Bundle(); 504 | settingsBundle.putBoolean( 505 | ContentResolver.SYNC_EXTRAS_MANUAL, true); 506 | settingsBundle.putBoolean( 507 | ContentResolver.SYNC_EXTRAS_EXPEDITED, true); 508 | //Log.d(TAG,"Request a sync for:"+mAccount); 509 | ContentResolver.requestSync(mAccount, AUTHORITY, settingsBundle); 510 | } 511 | 512 | @Override 513 | public Filter getFilter() { 514 | return null; 515 | } 516 | } 517 | 518 | -------------------------------------------------------------------------------- /ImapNote2/src/main/java/com/Pau/ImapNotes2/Miscs/ImapNotes2Result.java: -------------------------------------------------------------------------------- 1 | package com.Pau.ImapNotes2.Miscs; 2 | 3 | import javax.mail.Folder; 4 | 5 | public class ImapNotes2Result { 6 | 7 | public int returnCode; 8 | public String errorMessage; 9 | public Long UIDValidity; 10 | public boolean hasUIDPLUS; 11 | public Folder notesFolder; 12 | 13 | public ImapNotes2Result () { 14 | returnCode = -1; 15 | errorMessage = ""; 16 | UIDValidity = (long) -1; 17 | hasUIDPLUS = true; 18 | notesFolder = null; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ImapNote2/src/main/java/com/Pau/ImapNotes2/Miscs/ImapNotesAuthenticatorService.java: -------------------------------------------------------------------------------- 1 | package com.Pau.ImapNotes2.Miscs; 2 | 3 | import com.Pau.ImapNotes2.AccontConfigurationActivity; 4 | import com.Pau.ImapNotes2.Sync.SyncUtils; 5 | 6 | import android.accounts.AbstractAccountAuthenticator; 7 | import android.accounts.Account; 8 | import android.accounts.AccountAuthenticatorResponse; 9 | import android.accounts.AccountManager; 10 | import android.accounts.NetworkErrorException; 11 | import android.app.Service; 12 | import android.content.Context; 13 | import android.content.Intent; 14 | import android.os.Bundle; 15 | import android.os.IBinder; 16 | 17 | public class ImapNotesAuthenticatorService extends Service{ 18 | 19 | private static final String TAG = "ImapNotesAuthenticationService"; 20 | private Authenticator imapNotesAuthenticator; 21 | 22 | @Override 23 | public void onCreate() { 24 | this.imapNotesAuthenticator = new Authenticator(this); 25 | } 26 | 27 | public IBinder onBind(Intent intent) { 28 | IBinder ret = null; 29 | if (intent.getAction().equals(android.accounts.AccountManager.ACTION_AUTHENTICATOR_INTENT)) 30 | ret = getAuthenticator().getIBinder(); 31 | 32 | return ret; 33 | } 34 | 35 | private Authenticator getAuthenticator() { 36 | if (this.imapNotesAuthenticator == null) 37 | this.imapNotesAuthenticator = new Authenticator(this); 38 | 39 | return this.imapNotesAuthenticator; 40 | } 41 | 42 | private static class Authenticator extends AbstractAccountAuthenticator { 43 | 44 | private Context mContext; 45 | 46 | public Authenticator(Context context) { 47 | super(context); 48 | this.mContext = context; 49 | } 50 | 51 | @Override 52 | public Bundle getAccountRemovalAllowed( 53 | AccountAuthenticatorResponse response, Account account) 54 | throws NetworkErrorException { 55 | Bundle ret = super.getAccountRemovalAllowed(response, account); 56 | if (ret.getBoolean(AccountManager.KEY_BOOLEAN_RESULT)) 57 | SyncUtils.RemoveAccount(this.mContext, account); 58 | /* 59 | mContext.getContentResolver().delete(ListProvider.getClearUri(), 60 | null, null); 61 | */ 62 | return ret; 63 | } 64 | @Override 65 | public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException { 66 | 67 | Intent toLoginActivity = new Intent(this.mContext, AccontConfigurationActivity.class); 68 | toLoginActivity.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response); 69 | Bundle bundle = new Bundle(); 70 | bundle.putParcelable(AccountManager.KEY_INTENT, toLoginActivity); 71 | 72 | return bundle; 73 | } 74 | 75 | @Override 76 | public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException { 77 | 78 | return null; 79 | } 80 | 81 | @Override 82 | public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) { 83 | 84 | return null; 85 | } 86 | 87 | @Override 88 | public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException { 89 | 90 | return null; 91 | } 92 | 93 | @Override 94 | public String getAuthTokenLabel(String authTokenType) { 95 | 96 | return null; 97 | } 98 | 99 | @Override 100 | public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException { 101 | 102 | return null; 103 | } 104 | 105 | @Override 106 | public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException { 107 | 108 | return null; 109 | } 110 | 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /ImapNote2/src/main/java/com/Pau/ImapNotes2/Miscs/Imaper.java: -------------------------------------------------------------------------------- 1 | package com.Pau.ImapNotes2.Miscs; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.IOException; 6 | import java.io.OutputStream; 7 | import java.security.GeneralSecurityException; 8 | import java.util.ArrayList; 9 | import java.util.Properties; 10 | import android.content.Context; 11 | import android.content.SharedPreferences; 12 | import android.util.Log; 13 | import javax.mail.Folder; 14 | import javax.mail.Message; 15 | import javax.mail.MessagingException; 16 | import javax.mail.Session; 17 | import javax.mail.Store; 18 | import javax.mail.Flags; 19 | import com.sun.mail.imap.IMAPFolder; 20 | import com.sun.mail.imap.IMAPStore; 21 | import com.sun.mail.util.MailSSLSocketFactory; 22 | import java.util.regex.*; 23 | 24 | import com.Pau.ImapNotes2.Miscs.Sticky; 25 | import com.Pau.ImapNotes2.ImapNotes2; 26 | import com.Pau.ImapNotes2.Listactivity; 27 | import com.Pau.ImapNotes2.Miscs.ImapNotes2Result; 28 | 29 | public class Imaper { 30 | 31 | private Store store; 32 | private Session session; 33 | private static final String TAG = "IN_Imaper"; 34 | private String proto; 35 | private String acceptcrt; 36 | private static String sfolder = "Notes"; 37 | private String folderoverride; 38 | private Folder notesFolder = null; 39 | private ImapNotes2Result res; 40 | private Long UIDValidity; 41 | private Boolean useProxy = false; 42 | public static final String PREFS_NAME = "PrefsFile"; 43 | 44 | public ImapNotes2Result ConnectToProvider(String username, String password, String server, String portnum, String security, String usesticky, String override) throws MessagingException{ 45 | if (this.IsConnected()) 46 | this.store.close(); 47 | 48 | res = new ImapNotes2Result(); 49 | if (override==null) { 50 | this.folderoverride = ""; 51 | } else { 52 | this.folderoverride = override; 53 | } 54 | this.proto = ""; 55 | this.acceptcrt = ""; 56 | int security_i = Integer.parseInt(security); 57 | switch (security_i) { 58 | case 0: 59 | // None 60 | this.proto = "imap"; 61 | this.acceptcrt = ""; 62 | break; 63 | case 1: 64 | // SSL/TLS 65 | this.proto = "imaps"; 66 | this.acceptcrt = "false"; 67 | break; 68 | case 2: 69 | // SSL/TLS/TRUST ALL 70 | this.proto = "imaps"; 71 | this.acceptcrt = "true"; 72 | break; 73 | case 3: 74 | // STARTTLS 75 | this.proto = "imap"; 76 | this.acceptcrt = "false"; 77 | break; 78 | case 4: 79 | // STARTTLS/TRUST ALL 80 | this.proto = "imap"; 81 | this.acceptcrt = "true"; 82 | break; 83 | ////////////////////// Change this 84 | default: this.proto = "Invalid proto"; 85 | break; 86 | } 87 | MailSSLSocketFactory sf = null; 88 | try { 89 | sf = new MailSSLSocketFactory(); 90 | } catch (GeneralSecurityException e) { 91 | e.printStackTrace(); 92 | this.res.errorMessage = "Can't connect to server"; 93 | this.res.returnCode = -1; 94 | return this.res; 95 | } 96 | 97 | Properties props = new Properties(); 98 | 99 | props.setProperty(String.format("mail.%s.host", this.proto), server); 100 | props.setProperty(String.format("mail.%s.port", this.proto), portnum); 101 | props.setProperty("mail.store.protocol", this.proto); 102 | 103 | if ((this.acceptcrt.equals("true"))) { 104 | sf.setTrustedHosts(new String[] {server}); 105 | if (this.proto.equals("imap")) { 106 | props.put("mail.imap.ssl.socketFactory", sf); 107 | props.put("mail.imap.starttls.enable", "true"); 108 | } 109 | } else if (this.acceptcrt.equals("false")) { 110 | props.put(String.format("mail.%s.ssl.checkserveridentity", this.proto), "true"); 111 | if (this.proto.equals("imap")) { 112 | props.put("mail.imap.starttls.enable", "true"); 113 | } 114 | } 115 | 116 | if (this.proto.equals("imaps")) { 117 | props.put("mail.imaps.socketFactory", sf); 118 | } 119 | 120 | props.setProperty("mail.imap.connectiontimeout","1000"); 121 | if (this.useProxy) { 122 | props.put("mail.imap.socks.host","10.0.2.2"); 123 | props.put("mail.imap.socks.port","1080"); 124 | /* 125 | props.put("proxySet","true"); 126 | props.put("socksProxyHost","10.0.2.2"); 127 | props.put("socksProxyPort","1080"); 128 | props.put("sun.net.spi.nameservice.provider.1", "dns,sun"); 129 | props.put("sun.net.spi.nameservice.nameservers", "192.168.0.99"); 130 | */ 131 | } 132 | this.session = Session.getInstance(props, null); 133 | //this.session.setDebug(true); 134 | this.store = this.session.getStore(this.proto); 135 | try { 136 | this.store.connect(server, username, password); 137 | Boolean hasUIDPLUS = ((IMAPStore) this.store).hasCapability("UIDPLUS"); 138 | //Log.d(TAG, "has UIDPLUS="+hasUIDPLUS); 139 | 140 | Folder[] folders = store.getPersonalNamespaces(); 141 | Folder folder = folders[0]; 142 | //Log.d(TAG,"Personal Namespaces="+folder.getFullName()); 143 | if (this.folderoverride.length() > 0) { 144 | Imaper.sfolder = this.folderoverride; 145 | } else if (folder.getFullName().length() == 0) { 146 | Imaper.sfolder = "Notes"; 147 | } else { 148 | char separator = folder.getSeparator(); 149 | Imaper.sfolder = folder.getFullName() + separator + "Notes"; 150 | } 151 | this.res.errorMessage = ""; 152 | this.res.returnCode = 0; 153 | return this.res; 154 | } catch (Exception e) { 155 | e.printStackTrace(); 156 | Log.d(TAG, e.getMessage()); 157 | this.res.errorMessage = e.getMessage(); 158 | this.res.returnCode = -2; 159 | return this.res; 160 | } 161 | 162 | } 163 | 164 | public boolean IsConnected(){ 165 | return this.store!=null && this.store.isConnected(); 166 | } 167 | 168 | // Put values in shared preferences: 169 | public void SetPrefs() { 170 | SharedPreferences preferences = ImapNotes2.getAppContext().getSharedPreferences(Listactivity.imapNotes2Account.GetAccountname(), Context.MODE_PRIVATE); 171 | SharedPreferences.Editor editor = preferences.edit(); 172 | editor.putString("Name","valid_data"); 173 | editor.putLong("UIDValidity", this.UIDValidity); 174 | editor.apply(); 175 | } 176 | 177 | // Retrieve values from shared preferences: 178 | public void GetPrefs() { 179 | SharedPreferences preferences = (ImapNotes2.getAppContext()).getSharedPreferences(Listactivity.imapNotes2Account.GetAccountname(), Context.MODE_PRIVATE); 180 | String name = preferences.getString("Name", ""); 181 | if(!name.equalsIgnoreCase("")) { 182 | this.UIDValidity = preferences.getLong("UIDValidity", -1); 183 | } 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /ImapNote2/src/main/java/com/Pau/ImapNotes2/Miscs/OneNote.java: -------------------------------------------------------------------------------- 1 | package com.Pau.ImapNotes2.Miscs; 2 | 3 | import java.util.HashMap; 4 | 5 | public class OneNote extends HashMap{ 6 | 7 | /** 8 | * 9 | */ 10 | private static final long serialVersionUID = 1L; 11 | 12 | public OneNote(){ 13 | super(); 14 | this.put("title", "No Title"); 15 | this.put("date", "No Date"); 16 | this.put("uid", "0"); 17 | 18 | } 19 | 20 | public OneNote(String title, String date, String uid){ 21 | super(); 22 | this.put("title", title); 23 | this.put("date", date); 24 | this.put("uid", uid); 25 | 26 | } 27 | 28 | public String GetTitle(){ 29 | return this.get("title"); 30 | } 31 | 32 | public String GetDate(){ 33 | return this.get("date"); 34 | } 35 | 36 | public String GetUid(){ 37 | return this.get("uid"); 38 | } 39 | 40 | public void SetTitle(String title){ 41 | this.put("title", title); 42 | } 43 | 44 | public void SetDate(String date){ 45 | this.put("date", date); 46 | } 47 | 48 | public void SetUid(String uid){ 49 | this.put("uid", uid); 50 | } 51 | 52 | @Override 53 | public String toString() { 54 | return ("Title:"+this.GetTitle()+ 55 | " Date: "+ this.GetDate() + 56 | " Uid: "+ this.GetUid()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /ImapNote2/src/main/java/com/Pau/ImapNotes2/Miscs/Sticky.java: -------------------------------------------------------------------------------- 1 | package com.Pau.ImapNotes2.Miscs; 2 | 3 | public class Sticky { 4 | 5 | private static String text; 6 | private static String position; 7 | private static String color; 8 | 9 | public Sticky() { 10 | Sticky.text = ""; 11 | Sticky.position = "0 0 0 0"; 12 | Sticky.color = "YELLOW"; 13 | } 14 | 15 | public Sticky(String text, String position, String color) { 16 | Sticky.text = text; 17 | Sticky.position = position; 18 | Sticky.color = color; 19 | } 20 | 21 | public String GetPosition(){ 22 | return Sticky.position; 23 | } 24 | 25 | public String GetText(){ 26 | return Sticky.text; 27 | } 28 | 29 | public String GetColor(){ 30 | return Sticky.color; 31 | } 32 | 33 | public void SetText(String text){ 34 | Sticky.text = text; 35 | } 36 | 37 | public void SetPosition(String position){ 38 | Sticky.position = position; 39 | } 40 | 41 | public void SetColor(String color){ 42 | Sticky.color = color; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ImapNote2/src/main/java/com/Pau/ImapNotes2/Miscs/SyncThread.java: -------------------------------------------------------------------------------- 1 | package com.Pau.ImapNotes2.Miscs; 2 | 3 | import java.util.ArrayList; 4 | 5 | import com.Pau.ImapNotes2.Listactivity; 6 | import com.Pau.ImapNotes2.NotesListAdapter; 7 | import com.Pau.ImapNotes2.Data.ImapNotes2Account; 8 | import com.Pau.ImapNotes2.Data.NotesDb; 9 | 10 | import android.app.ProgressDialog; 11 | import android.content.Context; 12 | import android.os.AsyncTask; 13 | import android.util.Log; 14 | import android.widget.SimpleAdapter; 15 | import android.widget.Toast; 16 | 17 | public class SyncThread extends AsyncTask { 18 | NotesListAdapter adapter; 19 | ArrayList notesList; 20 | NotesDb storedNotes; 21 | boolean bool_to_return; 22 | ImapNotes2Result res = new ImapNotes2Result(); 23 | Context ctx; 24 | private static final String TAG = "SyncThread"; 25 | 26 | @Override 27 | protected Boolean doInBackground(Object... stuffs) { 28 | String username = null; 29 | String password = null; 30 | String server = null; 31 | String portnum = null; 32 | String security = null; 33 | String usesticky = null; 34 | this.adapter = ((NotesListAdapter)stuffs[3]); 35 | this.notesList = ((ArrayList)stuffs[2]); 36 | this.storedNotes = ((NotesDb)stuffs[5]); 37 | this.ctx = (Context)stuffs[6]; 38 | username = ((ImapNotes2Account)stuffs[1]).GetUsername(); 39 | password = ((ImapNotes2Account)stuffs[1]).GetPassword(); 40 | server = ((ImapNotes2Account)stuffs[1]).GetServer(); 41 | portnum = ((ImapNotes2Account)stuffs[1]).GetPortnum(); 42 | security = ((ImapNotes2Account)stuffs[1]).GetSecurity(); 43 | usesticky = ((ImapNotes2Account)stuffs[1]).GetUsesticky(); 44 | 45 | 46 | if (this.storedNotes == null) this.storedNotes = new NotesDb(this.ctx); 47 | this.storedNotes.OpenDb(); 48 | this.storedNotes.GetStoredNotes(this.notesList, Listactivity.imapNotes2Account.GetAccountname()); 49 | this.storedNotes.CloseDb(); 50 | ((ProgressDialog)stuffs[4]).dismiss(); 51 | return true; 52 | } 53 | 54 | protected void onPostExecute(Boolean result){ 55 | if(result){ 56 | this.adapter.notifyDataSetChanged(); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /ImapNote2/src/main/java/com/Pau/ImapNotes2/Miscs/UpdateThread.java: -------------------------------------------------------------------------------- 1 | package com.Pau.ImapNotes2.Miscs; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.IOException; 6 | import java.io.OutputStream; 7 | import java.text.DateFormat; 8 | import java.text.SimpleDateFormat; 9 | import java.util.ArrayList; 10 | import java.util.Date; 11 | import java.util.Properties; 12 | import java.util.UUID; 13 | 14 | import javax.mail.Flags; 15 | import javax.mail.MessagingException; 16 | import javax.mail.Session; 17 | import javax.mail.internet.MimeMessage; 18 | import javax.mail.internet.MailDateFormat; 19 | 20 | import com.Pau.ImapNotes2.ImapNotes2; 21 | import com.Pau.ImapNotes2.Listactivity; 22 | import com.Pau.ImapNotes2.NotesListAdapter; 23 | import com.Pau.ImapNotes2.Data.ImapNotes2Account; 24 | import com.Pau.ImapNotes2.Data.NotesDb; 25 | 26 | import android.app.ProgressDialog; 27 | import android.content.Context; 28 | import android.os.AsyncTask; 29 | import android.text.Html; 30 | import android.util.Log; 31 | import android.widget.SimpleAdapter; 32 | 33 | public class UpdateThread extends AsyncTask{ 34 | NotesListAdapter adapter; 35 | ArrayList notesList; 36 | String suid; 37 | String noteBody; 38 | String color; 39 | Imaper imapFolder; 40 | boolean bool_to_return; 41 | OneNote currentNote = null; 42 | NotesDb storedNotes; 43 | Context ctx; 44 | ProgressDialog pDialog; 45 | String body = null; 46 | String action; 47 | private static final String TAG = "UpdateThread"; 48 | 49 | @Override 50 | protected Boolean doInBackground(Object... stuffs) { 51 | this.adapter = ((NotesListAdapter)stuffs[3]); 52 | this.notesList = ((ArrayList)stuffs[2]); 53 | this.suid = ((String)stuffs[5]); 54 | this.noteBody = ((String)stuffs[6]); 55 | this.color = ((String)stuffs[7]); 56 | this.imapFolder = ((Imaper)stuffs[0]); 57 | this.ctx = (Context)stuffs[8]; 58 | this.action = (String)stuffs[9]; 59 | this.storedNotes = (NotesDb)stuffs[10]; 60 | 61 | try { 62 | // Do we have a note to remove? 63 | if (this.action.equals("delete") || this.action.equals("update")) { 64 | //Log.d(TAG,"Received request to delete message #"+suid); 65 | // Here we delete the note from the local notes list 66 | //Log.d(TAG,"Delete note in Listview"); 67 | this.notesList.remove(getIndexByNumber(this.suid)); 68 | MoveMailToDeleted(this.suid); 69 | this.storedNotes.OpenDb(); 70 | this.storedNotes.DeleteANote(this.suid, Listactivity.imapNotes2Account.GetAccountname()); 71 | this.storedNotes.CloseDb(); 72 | this.bool_to_return = true; 73 | } 74 | 75 | // Do we have a note to add? 76 | if (this.action.equals("insert") || this.action.equals("update")) { 77 | //Log.d(TAG,"Sticky ? "+((ImapNotes2Account)stuffs[1]).GetUsesticky()); 78 | //Log.d(TAG,"Color:"+this.color); 79 | //Log.d(TAG,"Received request to add new message"+this.noteBody+"==="); 80 | String noteTxt = Html.fromHtml(this.noteBody).toString(); 81 | String[] tok = noteTxt.split("\n", 2); 82 | String title = tok[0]; 83 | String position = "0 0 0 0"; 84 | if (((ImapNotes2Account)stuffs[1]).GetUsesticky().equals("true")) 85 | body = noteTxt.replaceAll("\n", "\\\\n"); 86 | else 87 | body = "" + this.noteBody + ""; 88 | 89 | 90 | String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; 91 | Date date = new Date(); 92 | SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT); 93 | String stringDate = sdf.format(date); 94 | this.currentNote = new OneNote(title, stringDate, ""); 95 | // Add note to database 96 | if (this.storedNotes == null) this.storedNotes = new NotesDb(this.ctx); 97 | this.storedNotes.OpenDb(); 98 | this.suid = this.storedNotes.GetTempNumber(Listactivity.imapNotes2Account.GetAccountname()); 99 | this.currentNote.SetUid(this.suid); 100 | // Here we ask to add the new note to the "new" folder 101 | // Must be done AFTER uid has been set in currenteNote 102 | WriteMailToNew(currentNote, 103 | ((ImapNotes2Account)stuffs[1]).GetUsesticky(), body); 104 | this.storedNotes.InsertANoteInDb(this.currentNote, Listactivity.imapNotes2Account.GetAccountname()); 105 | this.storedNotes.CloseDb(); 106 | // Add note to noteList but chage date format before 107 | DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(this.ctx); 108 | String sdate = DateFormat.getDateTimeInstance().format(date); 109 | this.currentNote.SetDate(sdate); 110 | this.notesList.add(0,this.currentNote); 111 | this.bool_to_return = true; 112 | } 113 | 114 | } catch (Exception e) { 115 | e.printStackTrace(); 116 | this.bool_to_return=false; 117 | } finally { 118 | ((ProgressDialog)stuffs[4]).dismiss(); 119 | } 120 | return this.bool_to_return; 121 | } 122 | 123 | protected void onPostExecute(Boolean result){ 124 | if (result) { 125 | if (this.bool_to_return) /* note added or removed */ 126 | this.adapter.notifyDataSetChanged(); 127 | } 128 | } 129 | 130 | public int getIndexByNumber(String pNumber) { 131 | for(OneNote _item : this.notesList) 132 | { 133 | if(_item.GetUid().equals(pNumber)) 134 | return this.notesList.indexOf(_item); 135 | } 136 | return -1; 137 | } 138 | 139 | private void MoveMailToDeleted (String suid) { 140 | String directory = (ImapNotes2.getAppContext()).getFilesDir() + "/" + 141 | Listactivity.imapNotes2Account.GetAccountname(); 142 | String positiveUid = suid.substring(1); 143 | File from = new File (directory, suid); 144 | File to = new File (directory + "/deleted/" + suid); 145 | if (!from.exists()) { 146 | from = new File (directory + "/new", positiveUid); 147 | from.delete(); 148 | } else { 149 | from.renameTo(to); 150 | } 151 | } 152 | 153 | public void WriteMailToNew(OneNote note, String usesticky, String noteBody) throws MessagingException, IOException { 154 | String body = null; 155 | 156 | // Here we add the new note to the "new" folder 157 | //Log.d(TAG,"Add new note"); 158 | Properties props = new Properties(); 159 | Session session = Session.getDefaultInstance(props, null); 160 | MimeMessage message = new MimeMessage(session); 161 | if (usesticky.equals("true")) { 162 | body = "BEGIN:STICKYNOTE\nCOLOR:" + this.color + "\nTEXT:" + noteBody + 163 | "\nPOSITION:0 0 0 0\nEND:STICKYNOTE"; 164 | message.setText(body); 165 | message.setHeader("Content-Transfer-Encoding", "8bit"); 166 | message.setHeader("Content-Type","text/x-stickynote; charset=\"utf-8\""); 167 | } else { 168 | message.setHeader("X-Uniform-Type-Identifier","com.apple.mail-note"); 169 | UUID uuid = UUID.randomUUID(); 170 | message.setHeader("X-Universally-Unique-Identifier", uuid.toString()); 171 | body = noteBody; 172 | body = body.replaceFirst("

", "

"); 173 | body = body.replaceFirst("

", "

"); 174 | body = body.replaceAll("

", "


"); 175 | body = body.replaceAll("

", "


"); 176 | body = body.replaceAll("

", "
"); 177 | body = body.replaceAll("
\n", "
"); 178 | message.setText(body, "utf-8", "html"); 179 | message.setFlag(Flags.Flag.SEEN,true); 180 | } 181 | message.setSubject(note.GetTitle()); 182 | MailDateFormat mailDateFormat = new MailDateFormat(); 183 | // Remove (CET) or (GMT+1) part as asked in github issue #13 184 | String headerDate = (mailDateFormat.format(new Date())).replaceAll("\\(.*$", ""); 185 | message.addHeader("Date", headerDate); 186 | //déterminer l'uid temporaire 187 | String uid = Integer.toString(Math.abs(Integer.parseInt(note.GetUid()))); 188 | File directory = new File ((ImapNotes2.getAppContext()).getFilesDir() + "/" + 189 | Listactivity.imapNotes2Account.GetAccountname() + "/new"); 190 | //message.setFrom(new InternetAddress("ImapNotes2", Listactivity.imapNotes2Account.GetAccountname())); 191 | message.setFrom(Listactivity.imapNotes2Account.GetAccountname()); 192 | File outfile = new File (directory, uid); 193 | OutputStream str = new FileOutputStream(outfile); 194 | message.writeTo(str); 195 | 196 | } 197 | 198 | } 199 | -------------------------------------------------------------------------------- /ImapNote2/src/main/java/com/Pau/ImapNotes2/NewNoteActivity.java: -------------------------------------------------------------------------------- 1 | package com.Pau.ImapNotes2; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.graphics.Color; 6 | import android.os.Bundle; 7 | import android.support.v4.app.NavUtils; 8 | import android.text.Html; 9 | import android.view.Menu; 10 | import android.view.MenuItem; 11 | import android.widget.EditText; 12 | 13 | public class NewNoteActivity extends Activity{ 14 | 15 | private static final int SAVE_BUTTON = 5; 16 | private static final String TAG = "IN_NewNoteActivity"; 17 | private String sticky; 18 | private String color = "NONE"; 19 | 20 | public void onCreate(Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | setContentView(R.layout.new_note); 23 | getActionBar().setDisplayHomeAsUpEnabled(true); 24 | this.ResetColors(); 25 | this.sticky = (String)getIntent().getExtras().get("usesSticky"); 26 | } 27 | 28 | private void ResetColors(){ 29 | ((EditText)findViewById(R.id.editNote)).setBackgroundColor(Color.TRANSPARENT); 30 | ((EditText)findViewById(R.id.editNote)).setTextColor(Color.BLACK); 31 | } 32 | 33 | public boolean onCreateOptionsMenu(Menu menu){ 34 | getMenuInflater().inflate(R.menu.newnote, menu); 35 | return true; 36 | } 37 | 38 | public boolean onOptionsItemSelected (MenuItem item){ 39 | switch (item.getItemId()){ 40 | case R.id.save: 41 | Intent intent=new Intent(); 42 | intent.putExtra("SAVE_ITEM",Html.toHtml(((EditText)findViewById(R.id.editNote)).getText())); 43 | if (this.sticky.equals("true")) { 44 | this.color="YELLOW"; 45 | } 46 | intent.putExtra("SAVE_ITEM_COLOR",this.color); 47 | setResult(SAVE_BUTTON, intent); 48 | finish();//finishing activity 49 | return true; 50 | case android.R.id.home: 51 | NavUtils.navigateUpFromSameTask(this); 52 | return true; 53 | default: 54 | return super.onOptionsItemSelected(item); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ImapNote2/src/main/java/com/Pau/ImapNotes2/NoteDetailActivity.java: -------------------------------------------------------------------------------- 1 | package com.Pau.ImapNotes2; 2 | 3 | import java.util.HashMap; 4 | import javax.mail.Message; 5 | import javax.mail.MessagingException; 6 | import javax.mail.Multipart; 7 | import javax.mail.Part; 8 | import javax.mail.internet.ContentType; 9 | import javax.mail.internet.MimeMessage; 10 | 11 | import org.apache.commons.io.IOUtils; 12 | 13 | import com.Pau.ImapNotes2.Miscs.OneNote; 14 | import com.Pau.ImapNotes2.Miscs.Sticky; 15 | import com.Pau.ImapNotes2.Sync.SyncUtils; 16 | 17 | import java.io.File; 18 | import java.io.FileOutputStream; 19 | import java.io.IOException; 20 | import java.io.InputStream; 21 | import java.io.OutputStream; 22 | 23 | import android.app.Activity; 24 | import android.content.Intent; 25 | import android.graphics.Color; 26 | import android.os.Bundle; 27 | import android.support.v4.app.NavUtils; 28 | import android.text.Html; 29 | import android.text.Spanned; 30 | import android.util.Log; 31 | import android.view.Menu; 32 | import android.view.MenuItem; 33 | import android.view.View; 34 | import android.view.WindowManager; 35 | import android.widget.EditText; 36 | 37 | public class NoteDetailActivity extends Activity { 38 | 39 | private static final int DELETE_BUTTON = 3; 40 | private static final int EDIT_BUTTON = 6; 41 | private HashMap hm; 42 | private String usesticky; 43 | private Sticky sticky; 44 | private String stringres; 45 | private String color; 46 | private String position; 47 | private int realColor = R.id.yellow; 48 | private Boolean isClicked = false; 49 | private Message message; 50 | private String suid; // uid as string 51 | private final static int ROOT_AND_NEW = 3; 52 | private static final String TAG = "IN_NoteDetailActivity"; 53 | 54 | public void onCreate(Bundle savedInstanceState) { 55 | super.onCreate(savedInstanceState); 56 | setContentView(R.layout.note_detail); 57 | getActionBar().setDisplayHomeAsUpEnabled(true); 58 | // Don't display keyboard when on note detail, only if user touches the screen 59 | getWindow().setSoftInputMode( 60 | WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN 61 | ); 62 | 63 | this.hm = (HashMap)getIntent().getExtras().get("selectedNote"); 64 | this.usesticky = (String)getIntent().getExtras().get("useSticky"); 65 | 66 | suid = this.hm.get("uid").toString(); 67 | String rootDir = (ImapNotes2.getAppContext()).getFilesDir() + "/" + 68 | Listactivity.imapNotes2Account.GetAccountname(); 69 | message = SyncUtils.ReadMailFromFile(suid, ROOT_AND_NEW, true, rootDir); 70 | sticky = GetInfoFromMessage(message); 71 | stringres = sticky.GetText(); 72 | position = sticky.GetPosition(); 73 | color = sticky.GetColor(); 74 | Spanned plainText = Html.fromHtml(stringres); 75 | ((EditText)findViewById(R.id.bodyView)).setText(plainText); 76 | this.ResetColors(); 77 | //invalidateOptionsMenu(); 78 | } 79 | 80 | public void onClick(View v){ 81 | this.isClicked = true; 82 | } 83 | 84 | private void ResetColors(){ 85 | ((EditText)findViewById(R.id.bodyView)).setBackgroundColor(Color.TRANSPARENT); 86 | ((EditText)findViewById(R.id.bodyView)).setTextColor(Color.BLACK); 87 | Colors currentColor = Colors.valueOf(color); 88 | switch (currentColor) { 89 | case BLUE: 90 | (findViewById(R.id.scrollView)).setBackgroundColor(0xFFA6CAFD); 91 | this.realColor = R.id.blue; 92 | break; 93 | case WHITE: 94 | (findViewById(R.id.scrollView)).setBackgroundColor(0xFFFFFFFF); 95 | this.realColor = R.id.white; 96 | break; 97 | case YELLOW: 98 | (findViewById(R.id.scrollView)).setBackgroundColor(0xFFFFFFCC); 99 | this.realColor = R.id.yellow; 100 | break; 101 | case PINK: 102 | (findViewById(R.id.scrollView)).setBackgroundColor(0xFFFFCCCC); 103 | this.realColor = R.id.pink; 104 | break; 105 | case GREEN: 106 | (findViewById(R.id.scrollView)).setBackgroundColor(0xFFCCFFCC); 107 | this.realColor = R.id.green; 108 | break; 109 | default: 110 | (findViewById(R.id.scrollView)).setBackgroundColor(Color.TRANSPARENT); 111 | } 112 | invalidateOptionsMenu(); 113 | } 114 | 115 | public boolean onCreateOptionsMenu(Menu menu){ 116 | getMenuInflater().inflate(R.menu.detail, menu); 117 | return true; 118 | } 119 | 120 | @Override 121 | public boolean onPrepareOptionsMenu(Menu menu) { 122 | MenuItem item= menu.findItem(R.id.color); 123 | super.onPrepareOptionsMenu(menu); 124 | //depending on your conditions, either enable/disable 125 | if (this.usesticky.equals("true")) { 126 | item.setVisible(true); 127 | } else { 128 | item.setVisible(false); 129 | } 130 | menu.findItem(this.realColor).setChecked(true); 131 | return true; 132 | } 133 | 134 | public boolean onOptionsItemSelected (MenuItem item){ 135 | Intent intent=new Intent(); 136 | switch (item.getItemId()){ 137 | case R.id.delete: 138 | //Log.d(TAG,"We ask to delete Message #"+this.currentNote.get("number")); 139 | intent.putExtra("DELETE_ITEM_NUM_IMAP",suid); 140 | setResult(NoteDetailActivity.DELETE_BUTTON, intent); 141 | finish();//finishing activity 142 | return true; 143 | case R.id.save: 144 | //Log.d(TAG,"We ask to modify Message #"+this.currentNote.get("number")); 145 | intent.putExtra("EDIT_ITEM_NUM_IMAP",suid); 146 | intent.putExtra("EDIT_ITEM_TXT", 147 | Html.toHtml(((EditText)findViewById(R.id.bodyView)).getText())); 148 | if (!this.usesticky.equals("true")) { 149 | this.color="NONE"; 150 | } 151 | intent.putExtra("EDIT_ITEM_COLOR",this.color); 152 | setResult(NoteDetailActivity.EDIT_BUTTON, intent); 153 | finish();//finishing activity 154 | return true; 155 | case android.R.id.home: 156 | NavUtils.navigateUpFromSameTask(this); 157 | return true; 158 | case R.id.blue: 159 | item.setChecked(true); 160 | this.color = "BLUE"; 161 | (findViewById(R.id.scrollView)).setBackgroundColor(0xFFA6CAFD); 162 | return true; 163 | case R.id.white: 164 | item.setChecked(true); 165 | this.color = "WHITE"; 166 | (findViewById(R.id.scrollView)).setBackgroundColor(0xFFFFFFFF); 167 | return true; 168 | case R.id.yellow: 169 | item.setChecked(true); 170 | this.color = "YELLOW"; 171 | (findViewById(R.id.scrollView)).setBackgroundColor(0xFFFFFFCC); 172 | return true; 173 | case R.id.pink: 174 | item.setChecked(true); 175 | this.color = "PINK"; 176 | (findViewById(R.id.scrollView)).setBackgroundColor(0xFFFFCCCC); 177 | return true; 178 | case R.id.green: 179 | item.setChecked(true); 180 | this.color = "GREEN"; 181 | (findViewById(R.id.scrollView)).setBackgroundColor(0xFFCCFFCC); 182 | return true; 183 | default: 184 | return super.onOptionsItemSelected(item); 185 | } 186 | } 187 | 188 | public enum Colors { 189 | BLUE, 190 | WHITE, 191 | YELLOW, 192 | PINK, 193 | GREEN, 194 | NONE 195 | } 196 | 197 | private Sticky GetInfoFromMessage (Message message) { 198 | ContentType contentType = null; 199 | String stringres = null; 200 | InputStream iis = null; 201 | String color = "NONE"; 202 | String charset; 203 | Sticky sticky = null; 204 | try { 205 | //Log.d(TAG, "Contenttype as string:"+message.getContentType()); 206 | contentType = new ContentType(message.getContentType() ); 207 | charset = contentType.getParameter("charset"); 208 | iis = (InputStream)message.getContent(); 209 | stringres = IOUtils.toString(iis, charset); 210 | } catch (Exception e) { 211 | // TODO Auto-generated catch block 212 | e.printStackTrace(); 213 | } 214 | 215 | //Log.d(TAG,"contentType:"+contentType); 216 | if (contentType.match("text/x-stickynote")) { 217 | sticky = SyncUtils.ReadStickynote(stringres); 218 | } else if (contentType.match("TEXT/HTML")) { 219 | sticky = ReadHtmlnote(stringres); 220 | } else if (contentType.match("TEXT/PLAIN")) { 221 | sticky = ReadPlainnote(stringres); 222 | } else if (contentType.match("multipart/related")) { 223 | // All next is a workaround 224 | // All function need to be rewritten to handle correctly multipart and images 225 | if (contentType.getParameter("type").equalsIgnoreCase("TEXT/HTML")) { 226 | sticky = ReadHtmlnote(stringres); 227 | } else if (contentType.getParameter("type").equalsIgnoreCase("TEXT/PLAIN")) { 228 | sticky = ReadPlainnote(stringres); 229 | } 230 | } else if (contentType.getParameter("BOUNDARY") != null) { 231 | sticky = ReadHtmlnote(stringres); 232 | } 233 | return sticky; 234 | } 235 | 236 | private void GetPart(Part message) throws Exception { 237 | if (message.isMimeType("text/plain")) { 238 | Log.d(TAG,"+++ isMimeType text/plain (contentType):"+message.getContentType()); 239 | } else if (message.isMimeType("multipart/*")) { 240 | Log.d(TAG,"+++ isMimeType multipart/* (contentType):"+message.getContentType()); 241 | Object content = message.getContent(); 242 | Multipart mp = (Multipart) content; 243 | int count = mp.getCount(); 244 | for (int i = 0; i < count; i++) GetPart(mp.getBodyPart(i)); 245 | } else if (message.isMimeType("message/rfc822")) { 246 | Log.d(TAG,"+++ isMimeType message/rfc822/* (contentType):"+message.getContentType()); 247 | GetPart((Part) message.getContent()); 248 | } else if (message.isMimeType("image/jpeg")) { 249 | Log.d(TAG,"+++ isMimeType image/jpeg (contentType):"+message.getContentType()); 250 | } else if (message.getContentType().contains("image/")) { 251 | Log.d(TAG,"+++ isMimeType image/jpeg (contentType):"+message.getContentType()); 252 | } else { 253 | Object o = message.getContent(); 254 | if (o instanceof String) { 255 | Log.d(TAG,"+++ instanceof String"); 256 | } else if (o instanceof InputStream) { 257 | Log.d(TAG,"+++ instanceof InputStream"); 258 | } else Log.d(TAG,"+++ instanceof ???"); 259 | } 260 | } 261 | 262 | private Sticky ReadHtmlnote(String stringres) { 263 | // Log.d(TAG,"From server (html):"+stringres); 264 | Spanned spanres = Html.fromHtml(stringres); 265 | stringres = Html.toHtml(spanres); 266 | stringres = stringres.replaceFirst("

", ""); 267 | stringres = stringres.replaceFirst("

", ""); 268 | stringres = stringres.replaceAll("

", "
"); 269 | stringres = stringres.replaceAll("

", "
"); 270 | stringres = stringres.replaceAll("

", ""); 271 | 272 | return new Sticky(stringres, "", "NONE"); 273 | } 274 | 275 | private Sticky ReadPlainnote(String stringres) { 276 | // Log.d(TAG,"From server (plain):"+stringres); 277 | stringres = stringres.replaceAll("\n", "
"); 278 | 279 | return new Sticky(stringres, "", "NONE"); 280 | } 281 | 282 | private void WriteMailToFile (String suid, Message message) { 283 | String directory = (ImapNotes2.getAppContext()).getFilesDir() + "/" + 284 | Listactivity.imapNotes2Account.GetAccountname(); 285 | try { 286 | File outfile = new File (directory, suid); 287 | OutputStream str = new FileOutputStream(outfile); 288 | message.writeTo(str); 289 | } catch (Exception e) { 290 | // TODO Auto-generated catch block 291 | e.printStackTrace(); 292 | } 293 | } 294 | 295 | 296 | 297 | } 298 | -------------------------------------------------------------------------------- /ImapNote2/src/main/java/com/Pau/ImapNotes2/NotesListAdapter.java: -------------------------------------------------------------------------------- 1 | package com.Pau.ImapNotes2; 2 | 3 | /* 4 | * Copyright (C) 2006 The Android Open Source Project 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.content.Context; 20 | import android.view.View; 21 | import android.view.ViewGroup; 22 | import android.widget.BaseAdapter; 23 | import android.widget.Checkable; 24 | import android.widget.Filter; 25 | import android.widget.Filterable; 26 | import android.widget.ImageView; 27 | import android.widget.TextView; 28 | import android.view.LayoutInflater; 29 | import android.net.Uri; 30 | 31 | import java.util.ArrayList; 32 | import java.util.List; 33 | import java.util.Map; 34 | 35 | /** 36 | * An easy adapter to map static data to views defined in an XML file. You can specify the data 37 | * backing the list as an ArrayList of Maps. Each entry in the ArrayList corresponds to one row 38 | * in the list. The Maps contain the data for each row. You also specify an XML file that 39 | * defines the views used to display the row, and a mapping from keys in the Map to specific 40 | * views. 41 | * 42 | * Binding data to views occurs in two phases. First, if a 43 | * {@link android.widget.SimpleAdapter.ViewBinder} is available, 44 | * {@link ViewBinder#setViewValue(android.view.View, Object, String)} 45 | * is invoked. If the returned value is true, binding has occurred. 46 | * If the returned value is false, the following views are then tried in order: 47 | *
    48 | *
  • A view that implements Checkable (e.g. CheckBox). The expected bind value is a boolean. 49 | *
  • TextView. The expected bind value is a string and {@link #setViewText(TextView, String)} 50 | * is invoked. 51 | *
  • ImageView. The expected bind value is a resource id or a string and 52 | * {@link #setViewImage(ImageView, int)} or {@link #setViewImage(ImageView, String)} is invoked. 53 | *
54 | * If no appropriate binding can be found, an {@link IllegalStateException} is thrown. 55 | */ 56 | public class NotesListAdapter extends BaseAdapter implements Filterable { 57 | private int[] mTo; 58 | private String[] mFrom; 59 | private ViewBinder mViewBinder; 60 | 61 | private List> mData; 62 | 63 | private int mResource; 64 | private int mDropDownResource; 65 | private LayoutInflater mInflater; 66 | 67 | private SimpleFilter mFilter; 68 | private ArrayList> mUnfilteredData; 69 | 70 | /** 71 | * Constructor 72 | * 73 | * @param context The context where the View associated with this SimpleAdapter is running 74 | * @param data A List of Maps. Each entry in the List corresponds to one row in the list. The 75 | * Maps contain the data for each row, and should include all the entries specified in 76 | * "from" 77 | * @param resource Resource identifier of a view layout that defines the views for this list 78 | * item. The layout file should include at least those named views defined in "to" 79 | * @param from A list of column names that will be added to the Map associated with each 80 | * item. 81 | * @param to The views that should display column in the "from" parameter. These should all be 82 | * TextViews. The first N views in this list are given the values of the first N columns 83 | * in the from parameter. 84 | */ 85 | public NotesListAdapter(Context context, List> data, 86 | int resource, String[] from, int[] to) { 87 | mData = data; 88 | mResource = mDropDownResource = resource; 89 | mFrom = from; 90 | mTo = to; 91 | mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 92 | } 93 | 94 | 95 | /** 96 | * @see android.widget.Adapter#getCount() 97 | */ 98 | public int getCount() { 99 | return mData.size(); 100 | } 101 | 102 | /** 103 | * @see android.widget.Adapter#getItem(int) 104 | */ 105 | public Object getItem(int position) { 106 | return mData.get(position); 107 | } 108 | 109 | /** 110 | * @see android.widget.Adapter#getItemId(int) 111 | */ 112 | public long getItemId(int position) { 113 | return position; 114 | } 115 | 116 | /** 117 | * @see android.widget.Adapter#getView(int, View, ViewGroup) 118 | */ 119 | public View getView(int position, View convertView, ViewGroup parent) { 120 | return createViewFromResource(position, convertView, parent, mResource); 121 | } 122 | 123 | private View createViewFromResource(int position, View convertView, 124 | ViewGroup parent, int resource) { 125 | View v; 126 | if (convertView == null) { 127 | v = mInflater.inflate(resource, parent, false); 128 | } else { 129 | v = convertView; 130 | } 131 | 132 | bindView(position, v); 133 | 134 | return v; 135 | } 136 | 137 | /** 138 | *

Sets the layout resource to create the drop down views.

139 | * 140 | * @param resource the layout resource defining the drop down views 141 | * @see #getDropDownView(int, android.view.View, android.view.ViewGroup) 142 | */ 143 | public void setDropDownViewResource(int resource) { 144 | this.mDropDownResource = resource; 145 | } 146 | 147 | @Override 148 | public View getDropDownView(int position, View convertView, ViewGroup parent) { 149 | return createViewFromResource(position, convertView, parent, mDropDownResource); 150 | } 151 | 152 | private void bindView(int position, View view) { 153 | final Map dataSet = mData.get(position); 154 | if (dataSet == null) { 155 | return; 156 | } 157 | 158 | final ViewBinder binder = mViewBinder; 159 | final String[] from = mFrom; 160 | final int[] to = mTo; 161 | final int count = to.length; 162 | 163 | for (int i = 0; i < count; i++) { 164 | final View v = view.findViewById(to[i]); 165 | if (v != null) { 166 | final Object data = dataSet.get(from[i]); 167 | String text = data == null ? "" : data.toString(); 168 | if (text == null) { 169 | text = ""; 170 | } 171 | 172 | boolean bound = false; 173 | if (binder != null) { 174 | bound = binder.setViewValue(v, data, text); 175 | } 176 | 177 | if (!bound) { 178 | if (v instanceof Checkable) { 179 | if (data instanceof Boolean) { 180 | ((Checkable) v).setChecked((Boolean) data); 181 | } else if (v instanceof TextView) { 182 | // Note: keep the instanceof TextView check at the bottom of these 183 | // ifs since a lot of views are TextViews (e.g. CheckBoxes). 184 | setViewText((TextView) v, text); 185 | } else { 186 | throw new IllegalStateException(v.getClass().getName() + 187 | " should be bound to a Boolean, not a " + 188 | (data == null ? "" : data.getClass())); 189 | } 190 | } else if (v instanceof TextView) { 191 | // Note: keep the instanceof TextView check at the bottom of these 192 | // ifs since a lot of views are TextViews (e.g. CheckBoxes). 193 | setViewText((TextView) v, text); 194 | } else if (v instanceof ImageView) { 195 | if (data instanceof Integer) { 196 | setViewImage((ImageView) v, (Integer) data); 197 | } else { 198 | setViewImage((ImageView) v, text); 199 | } 200 | } else { 201 | throw new IllegalStateException(v.getClass().getName() + " is not a " + 202 | " view that can be bounds by this SimpleAdapter"); 203 | } 204 | } 205 | } 206 | } 207 | } 208 | 209 | /** 210 | * Returns the {@link ViewBinder} used to bind data to views. 211 | * 212 | * @return a ViewBinder or null if the binder does not exist 213 | * 214 | * @see #setViewBinder(android.widget.SimpleAdapter.ViewBinder) 215 | */ 216 | public ViewBinder getViewBinder() { 217 | return mViewBinder; 218 | } 219 | 220 | /** 221 | * Sets the binder used to bind data to views. 222 | * 223 | * @param viewBinder the binder used to bind data to views, can be null to 224 | * remove the existing binder 225 | * 226 | * @see #getViewBinder() 227 | */ 228 | public void setViewBinder(ViewBinder viewBinder) { 229 | mViewBinder = viewBinder; 230 | } 231 | 232 | /** 233 | * Called by bindView() to set the image for an ImageView but only if 234 | * there is no existing ViewBinder or if the existing ViewBinder cannot 235 | * handle binding to an ImageView. 236 | * 237 | * This method is called instead of {@link #setViewImage(ImageView, String)} 238 | * if the supplied data is an int or Integer. 239 | * 240 | * @param v ImageView to receive an image 241 | * @param value the value retrieved from the data set 242 | * 243 | * @see #setViewImage(ImageView, String) 244 | */ 245 | public void setViewImage(ImageView v, int value) { 246 | v.setImageResource(value); 247 | } 248 | 249 | /** 250 | * Called by bindView() to set the image for an ImageView but only if 251 | * there is no existing ViewBinder or if the existing ViewBinder cannot 252 | * handle binding to an ImageView. 253 | * 254 | * By default, the value will be treated as an image resource. If the 255 | * value cannot be used as an image resource, the value is used as an 256 | * image Uri. 257 | * 258 | * This method is called instead of {@link #setViewImage(ImageView, int)} 259 | * if the supplied data is not an int or Integer. 260 | * 261 | * @param v ImageView to receive an image 262 | * @param value the value retrieved from the data set 263 | * 264 | * @see #setViewImage(ImageView, int) 265 | */ 266 | public void setViewImage(ImageView v, String value) { 267 | try { 268 | v.setImageResource(Integer.parseInt(value)); 269 | } catch (NumberFormatException nfe) { 270 | v.setImageURI(Uri.parse(value)); 271 | } 272 | } 273 | 274 | /** 275 | * Called by bindView() to set the text for a TextView but only if 276 | * there is no existing ViewBinder or if the existing ViewBinder cannot 277 | * handle binding to a TextView. 278 | * 279 | * @param v TextView to receive text 280 | * @param text the text to be set for the TextView 281 | */ 282 | public void setViewText(TextView v, String text) { 283 | v.setText(text); 284 | } 285 | 286 | public Filter getFilter() { 287 | if (mFilter == null) { 288 | mFilter = new SimpleFilter(); 289 | } 290 | return mFilter; 291 | } 292 | 293 | /** 294 | * This class can be used by external clients of SimpleAdapter to bind 295 | * values to views. 296 | * 297 | * You should use this class to bind values to views that are not 298 | * directly supported by SimpleAdapter or to change the way binding 299 | * occurs for views supported by SimpleAdapter. 300 | * 301 | * @see SimpleAdapter#setViewImage(ImageView, int) 302 | * @see SimpleAdapter#setViewImage(ImageView, String) 303 | * @see SimpleAdapter#setViewText(TextView, String) 304 | */ 305 | public static interface ViewBinder { 306 | /** 307 | * Binds the specified data to the specified view. 308 | * 309 | * When binding is handled by this ViewBinder, this method must return true. 310 | * If this method returns false, SimpleAdapter will attempts to handle 311 | * the binding on its own. 312 | * 313 | * @param view the view to bind the data to 314 | * @param data the data to bind to the view 315 | * @param textRepresentation a safe String representation of the supplied data: 316 | * it is either the result of data.toString() or an empty String but it 317 | * is never null 318 | * 319 | * @return true if the data was bound to the view, false otherwise 320 | */ 321 | boolean setViewValue(View view, Object data, String textRepresentation); 322 | } 323 | 324 | /** 325 | *

An array filters constrains the content of the array adapter with 326 | * a prefix. Each item that does not start with the supplied prefix 327 | * is removed from the list.

328 | */ 329 | private class SimpleFilter extends Filter { 330 | 331 | @Override 332 | protected FilterResults performFiltering(CharSequence prefix) { 333 | FilterResults results = new FilterResults(); 334 | 335 | if (mUnfilteredData == null) { 336 | mUnfilteredData = new ArrayList>(mData); 337 | } 338 | 339 | if (prefix == null || prefix.length() == 0) { 340 | ArrayList> list = mUnfilteredData; 341 | results.values = list; 342 | results.count = list.size(); 343 | } else { 344 | String prefixString = prefix.toString().toLowerCase(); 345 | 346 | ArrayList> unfilteredValues = mUnfilteredData; 347 | int count = unfilteredValues.size(); 348 | 349 | ArrayList> newValues = new ArrayList>(count); 350 | 351 | for (int i = 0; i < count; i++) { 352 | Map h = unfilteredValues.get(i); 353 | if (h != null) { 354 | 355 | int len = mTo.length; 356 | 357 | for (int j=0; j>) results.values; 379 | if (results.count > 0) { 380 | notifyDataSetChanged(); 381 | } else { 382 | notifyDataSetInvalidated(); 383 | } 384 | } 385 | } 386 | } 387 | -------------------------------------------------------------------------------- /ImapNote2/src/main/java/com/Pau/ImapNotes2/Sync/StubProvider.java: -------------------------------------------------------------------------------- 1 | package com.Pau.ImapNotes2.Sync; 2 | 3 | import android.content.ContentProvider; 4 | import android.content.ContentValues; 5 | import android.database.Cursor; 6 | import android.net.Uri; 7 | 8 | /* 9 | * Define an implementation of ContentProvider that stubs out 10 | * all methods 11 | */ 12 | public class StubProvider extends ContentProvider { 13 | /* 14 | * Always return true, indicating that the 15 | * provider loaded correctly. 16 | */ 17 | @Override 18 | public boolean onCreate() { 19 | return true; 20 | } 21 | /* 22 | * Return no type for MIME type 23 | */ 24 | @Override 25 | public String getType(Uri uri) { 26 | return null; 27 | } 28 | /* 29 | * query() always returns no results 30 | * 31 | */ 32 | @Override 33 | public Cursor query( 34 | Uri uri, 35 | String[] projection, 36 | String selection, 37 | String[] selectionArgs, 38 | String sortOrder) { 39 | return null; 40 | } 41 | /* 42 | * insert() always returns null (no URI) 43 | */ 44 | @Override 45 | public Uri insert(Uri uri, ContentValues values) { 46 | return null; 47 | } 48 | /* 49 | * delete() always returns "no rows affected" (0) 50 | */ 51 | @Override 52 | public int delete(Uri uri, String selection, String[] selectionArgs) { 53 | return 0; 54 | } 55 | /* 56 | * update() always returns "no rows affected" (0) 57 | */ 58 | public int update( 59 | Uri uri, 60 | ContentValues values, 61 | String selection, 62 | String[] selectionArgs) { 63 | return 0; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /ImapNote2/src/main/java/com/Pau/ImapNotes2/Sync/SyncAdapter.java: -------------------------------------------------------------------------------- 1 | package com.Pau.ImapNotes2.Sync; 2 | 3 | import android.accounts.Account; 4 | import android.accounts.AccountManager; 5 | import android.content.AbstractThreadedSyncAdapter; 6 | import android.content.ContentProviderClient; 7 | import android.content.ContentResolver; 8 | import android.content.Context; 9 | import android.content.Intent; 10 | import android.content.SyncResult; 11 | import android.os.Bundle; 12 | import android.util.Log; 13 | 14 | import java.io.File; 15 | import java.io.IOException; 16 | import javax.mail.Flags; 17 | import javax.mail.Message; 18 | import javax.mail.MessagingException; 19 | import javax.mail.internet.MimeMessage; 20 | 21 | import com.Pau.ImapNotes2.Data.NotesDb; 22 | import com.Pau.ImapNotes2.Miscs.ImapNotes2Result; 23 | import com.Pau.ImapNotes2.Sync.SyncUtils; 24 | import com.sun.mail.imap.AppendUID; 25 | 26 | class SyncAdapter extends AbstractThreadedSyncAdapter { 27 | public static final String TAG = "SyncAdapter"; 28 | private static Context context; 29 | private static Boolean isChanged; 30 | private static Boolean isSynced; 31 | private NotesDb storedNotes; 32 | private String[] listOfNew; 33 | private String[] listOfDeleted; 34 | private static Account account; 35 | private Long UIDValidity = (long) -1; 36 | private static ImapNotes2Result res; 37 | private final static int NEW = 1; 38 | private final static int DELETED = 2; 39 | 40 | private final ContentResolver mContentResolver; 41 | 42 | public SyncAdapter(Context context, boolean autoInitialize) { 43 | super(context, autoInitialize); 44 | mContentResolver = context.getContentResolver(); 45 | this.context = context; 46 | } 47 | 48 | public SyncAdapter(Context context, boolean autoInitialize, 49 | boolean allowParallelSyncs) { 50 | super(context, autoInitialize, allowParallelSyncs); 51 | mContentResolver = context.getContentResolver(); 52 | this.context = context; 53 | } 54 | 55 | @Override 56 | public void onPerformSync(Account account, Bundle extras, String authority, 57 | ContentProviderClient provider, SyncResult syncResult) { 58 | //Log.d(TAG, "Beginning network synchronization of account: "+account.name); 59 | this.account = account; 60 | isChanged = false; 61 | isSynced = false; 62 | String syncinterval; 63 | 64 | SyncUtils.CreateDirs (account.name, this.context); 65 | 66 | storedNotes = new NotesDb(this.context); 67 | storedNotes.OpenDb(); 68 | 69 | AccountManager am = AccountManager.get(this.context); 70 | syncinterval = am.getUserData(account, "syncinterval"); 71 | /* 72 | // Temporary workaround for a bug 73 | // Portnum was put into account manager sync interval (143 or 993 or ... minutes) 74 | if (syncinterval != null) 75 | if (syncinterval.equals("143") || syncinterval.equals("993")) am.setUserData(account, "syncinterval", "15"); 76 | else am.setUserData(account, "syncinterval", "15"); 77 | */ 78 | 79 | // Connect to remote and get UIDValidity 80 | this.res = ConnectToRemote(); 81 | if (this.res.returnCode != 0) { 82 | storedNotes.CloseDb(); 83 | 84 | // Notify Listactivity that it's finished, but it can't refresh display 85 | Intent i = new Intent(SyncService.SYNC_FINISHED); 86 | i.putExtra("ACCOUNTNAME",account.name); 87 | isChanged = false; 88 | isSynced = false; 89 | i.putExtra("CHANGED", isChanged); 90 | i.putExtra("SYNCED", isSynced); 91 | i.putExtra("SYNCINTERVAL", syncinterval); 92 | context.sendBroadcast(i); 93 | return; 94 | } 95 | // Compare UIDValidity to old saved one 96 | if (!(this.res.UIDValidity.equals 97 | (SyncUtils.GetUIDValidity(this.account, this.context)))) { 98 | // Replace local data by remote 99 | try { 100 | // delete notes in NotesDb for this account 101 | storedNotes.ClearDb(account.name); 102 | // delete notes in folders for this account and recreate dirs 103 | SyncUtils.ClearHomeDir(account, this.context); 104 | SyncUtils.CreateDirs (account.name, this.context); 105 | // Get all notes from remote and replace local 106 | SyncUtils.GetNotes(account,this.res.notesFolder,this.context,storedNotes); 107 | storedNotes.CloseDb(); 108 | } catch (MessagingException e) { 109 | // TODO Auto-generated catch block 110 | e.printStackTrace(); 111 | } catch (IOException e) { 112 | // TODO Auto-generated catch block 113 | e.printStackTrace(); 114 | } 115 | SyncUtils.SetUIDValidity(account, this.res.UIDValidity, this.context); 116 | // Notify Listactivity that it's finished, and that it can refresh display 117 | Intent i = new Intent(SyncService.SYNC_FINISHED); 118 | i.putExtra("ACCOUNTNAME",account.name); 119 | isChanged = true; 120 | isSynced = true; 121 | i.putExtra("CHANGED", isChanged); 122 | i.putExtra("SYNCED", isSynced); 123 | i.putExtra("SYNCINTERVAL", syncinterval); 124 | context.sendBroadcast(i); 125 | return; 126 | } 127 | 128 | // Send new local messages to remote, move them to local folder 129 | // and update uids in database 130 | boolean newNotesManaged = handleNewNotes(); 131 | if (newNotesManaged) isChanged = true; 132 | 133 | // Delete on remote messages that are deleted locally (if necessary) 134 | boolean deletedNotesManaged = handleDeletedNotes(); 135 | if (deletedNotesManaged) isChanged = true; 136 | 137 | // handle notes created or removed on remote 138 | boolean remoteNotesManaged = false; 139 | String usesticky = am.getUserData(account, "usesticky"); 140 | try { 141 | remoteNotesManaged = SyncUtils.handleRemoteNotes(context, res.notesFolder, storedNotes, account.name, usesticky); 142 | } catch (MessagingException e) { 143 | // TODO Auto-generated catch block 144 | e.printStackTrace(); 145 | } catch (IOException e) { 146 | // TODO Auto-generated catch block 147 | e.printStackTrace(); 148 | } 149 | if (remoteNotesManaged) isChanged = true; 150 | 151 | storedNotes.CloseDb(); 152 | 153 | // Disconnect from remote 154 | SyncUtils.DisconnectFromRemote(); 155 | //Log.d(TAG, "Network synchronization complete of account: "+account.name); 156 | // Notify Listactivity that it's finished, and that it can refresh display 157 | Intent i = new Intent(SyncService.SYNC_FINISHED); 158 | i.putExtra("ACCOUNTNAME",account.name); 159 | i.putExtra("CHANGED", isChanged); 160 | isSynced = true; 161 | i.putExtra("SYNCED", isSynced); 162 | i.putExtra("SYNCINTERVAL", syncinterval); 163 | context.sendBroadcast(i); 164 | } 165 | 166 | ImapNotes2Result ConnectToRemote() { 167 | AccountManager am = AccountManager.get(this.context); 168 | ImapNotes2Result res = null; 169 | try { 170 | res = SyncUtils.ConnectToRemote( 171 | am.getUserData(account, "username"), 172 | am.getPassword(account), 173 | am.getUserData(account, "server"), 174 | am.getUserData(account, "portnum"), 175 | am.getUserData(account, "security"), 176 | am.getUserData(account, "usesticky"), 177 | am.getUserData(account, "imapfolder")); 178 | } catch (MessagingException e) { 179 | // TODO Auto-generated catch block 180 | e.printStackTrace(); 181 | } 182 | if (res.returnCode != 0) { 183 | Log.d(TAG,"Connection problem !!!"); 184 | } 185 | return res; 186 | } 187 | 188 | private boolean handleNewNotes() { 189 | Message message = null; 190 | boolean newNotesManaged = false; 191 | AppendUID[] uids = null; 192 | String rootString = context.getFilesDir() + "/" + account.name; 193 | File rootDir = new File (rootString); 194 | File dirNew = new File (rootDir + "/new"); 195 | listOfNew = dirNew.list(); 196 | for (String fileNew : listOfNew) { 197 | //Log.d(TAG,"New Note to process:"+fileNew); 198 | newNotesManaged = true; 199 | // Read local new message from file 200 | message = SyncUtils.ReadMailFromFile(fileNew, NEW, false, rootString); 201 | try { 202 | message.setFlag(Flags.Flag.SEEN,true); // set message as seen 203 | } catch (MessagingException e) { 204 | // TODO Auto-generated catch block 205 | e.printStackTrace(); 206 | } 207 | // Send this new message to remote 208 | final MimeMessage[] msg = {(MimeMessage)message}; 209 | 210 | try { 211 | uids = SyncUtils.sendMessageToRemote(msg); 212 | } catch (MessagingException e) { 213 | // TODO Auto-generated catch block 214 | e.printStackTrace(); 215 | } catch (IOException e) { 216 | // TODO Auto-generated catch block 217 | e.printStackTrace(); 218 | } 219 | // Update uid in database entry 220 | String newuid = Long.toString(uids[0].uid); 221 | storedNotes.UpdateANote(fileNew,newuid,account.name); 222 | // move new note from new dir, one level up 223 | File fileInNew = new File (dirNew, fileNew); 224 | File to = new File (rootDir, newuid); 225 | fileInNew.renameTo(to); 226 | } 227 | return newNotesManaged; 228 | } 229 | 230 | private boolean handleDeletedNotes() { 231 | Message message = null; 232 | boolean deletedNotesManaged = false; 233 | String rootString = context.getFilesDir() + "/" + account.name; 234 | File rootDir = new File (rootString); 235 | File dirDeleted = new File (rootDir + "/deleted"); 236 | listOfDeleted = dirDeleted.list(); 237 | for (String fileDeleted : listOfDeleted) { 238 | try { 239 | SyncUtils.DeleteNote(this.res.notesFolder, Integer.parseInt(fileDeleted)); 240 | } catch (Exception e) { 241 | e.printStackTrace(); 242 | } 243 | 244 | // remove file from deleted 245 | File toDelete = new File (dirDeleted, fileDeleted); 246 | toDelete.delete(); 247 | deletedNotesManaged = true; 248 | } 249 | return deletedNotesManaged; 250 | } 251 | 252 | } 253 | -------------------------------------------------------------------------------- /ImapNote2/src/main/java/com/Pau/ImapNotes2/Sync/SyncService.java: -------------------------------------------------------------------------------- 1 | package com.Pau.ImapNotes2.Sync; 2 | 3 | import android.app.Service; 4 | import android.content.Intent; 5 | import android.os.IBinder; 6 | import android.util.Log; 7 | 8 | public class SyncService extends Service { 9 | public static final String SYNC_FINISHED = "SYNC_FINISHED"; 10 | private static final String TAG = "SyncService"; 11 | 12 | private static final Object sSyncAdapterLock = new Object(); 13 | private static SyncAdapter sSyncAdapter = null; 14 | 15 | @Override 16 | public void onCreate() { 17 | super.onCreate(); 18 | Log.d(TAG, "Service created"); 19 | synchronized (sSyncAdapterLock) { 20 | if (sSyncAdapter == null) { 21 | sSyncAdapter = new SyncAdapter(getApplicationContext(), true); 22 | } 23 | } 24 | } 25 | 26 | @Override 27 | public void onDestroy() { 28 | super.onDestroy(); 29 | Log.d(TAG, "Service destroyed"); 30 | } 31 | 32 | @Override 33 | public IBinder onBind(Intent intent) { 34 | Log.d(TAG, "Service is returning IBinder"); 35 | return sSyncAdapter.getSyncAdapterBinder(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ImapNote2/src/main/java/com/Pau/ImapNotes2/Sync/SyncUtils.java: -------------------------------------------------------------------------------- 1 | package com.Pau.ImapNotes2.Sync; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.FileNotFoundException; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.io.OutputStream; 10 | import java.security.GeneralSecurityException; 11 | import java.text.SimpleDateFormat; 12 | import java.util.ArrayList; 13 | import java.util.Arrays; 14 | import java.util.Date; 15 | import java.util.Properties; 16 | import java.util.regex.Matcher; 17 | import java.util.regex.Pattern; 18 | 19 | import javax.mail.Flags; 20 | import javax.mail.Folder; 21 | import javax.mail.MessagingException; 22 | import javax.mail.Store; 23 | import javax.mail.UIDFolder; 24 | import javax.mail.internet.MimeMessage; 25 | 26 | import org.apache.commons.io.FileUtils; 27 | 28 | import javax.mail.Message; 29 | import javax.mail.Session; 30 | import com.Pau.ImapNotes2.Data.NotesDb; 31 | import com.Pau.ImapNotes2.Miscs.ImapNotes2Result; 32 | import com.Pau.ImapNotes2.Miscs.OneNote; 33 | import com.Pau.ImapNotes2.Miscs.Sticky; 34 | import com.sun.mail.util.MailSSLSocketFactory; 35 | 36 | import com.sun.mail.imap.IMAPStore; 37 | import com.sun.mail.imap.AppendUID; 38 | import com.sun.mail.imap.IMAPFolder; 39 | 40 | import android.accounts.Account; 41 | import android.content.Context; 42 | import android.content.SharedPreferences; 43 | import android.util.Log; 44 | 45 | public class SyncUtils { 46 | 47 | static Store store; 48 | static Session session; 49 | static final String TAG = "IN_SyncUtils"; 50 | static String proto; 51 | static String acceptcrt; 52 | static String sfolder = "Notes"; 53 | static private String folderoverride; 54 | static Folder notesFolder = null; 55 | static ImapNotes2Result res; 56 | static Long UIDValidity; 57 | private final static int NEW = 1; 58 | private final static int DELETED = 2; 59 | private final static int ROOT_AND_NEW = 3; 60 | private static Boolean useProxy = false; 61 | 62 | public static ImapNotes2Result ConnectToRemote(String username, String password, String server, String portnum, String security, String usesticky, String override) throws MessagingException{ 63 | if (IsConnected()) 64 | store.close(); 65 | 66 | res = new ImapNotes2Result(); 67 | if (override==null) { 68 | folderoverride = ""; 69 | } else { 70 | folderoverride = override; 71 | } 72 | proto = ""; 73 | acceptcrt = ""; 74 | int security_i = Integer.parseInt(security); 75 | switch (security_i) { 76 | case 0: 77 | // None 78 | proto = "imap"; 79 | acceptcrt = ""; 80 | break; 81 | case 1: 82 | // SSL/TLS 83 | proto = "imaps"; 84 | acceptcrt = "false"; 85 | break; 86 | case 2: 87 | // SSL/TLS/TRUST ALL 88 | proto = "imaps"; 89 | acceptcrt = "true"; 90 | break; 91 | case 3: 92 | // STARTTLS 93 | proto = "imap"; 94 | acceptcrt = "false"; 95 | break; 96 | case 4: 97 | // STARTTLS/TRUST ALL 98 | proto = "imap"; 99 | acceptcrt = "true"; 100 | break; 101 | ////////////////////// Change this 102 | default: proto = "Invalid proto"; 103 | break; 104 | } 105 | MailSSLSocketFactory sf = null; 106 | try { 107 | sf = new MailSSLSocketFactory(); 108 | } catch (GeneralSecurityException e) { 109 | e.printStackTrace(); 110 | res.errorMessage = "Can't connect to server"; 111 | res.returnCode = -1; 112 | return res; 113 | } 114 | 115 | Properties props = new Properties(); 116 | 117 | props.setProperty(String.format("mail.%s.host", proto), server); 118 | props.setProperty(String.format("mail.%s.port", proto), portnum); 119 | props.setProperty("mail.store.protocol", proto); 120 | 121 | if ((acceptcrt.equals("true"))) { 122 | sf.setTrustedHosts(new String[] {server}); 123 | if (proto.equals("imap")) { 124 | props.put("mail.imap.ssl.socketFactory", sf); 125 | props.put("mail.imap.starttls.enable", "true"); 126 | } 127 | } else if (acceptcrt.equals("false")) { 128 | props.put(String.format("mail.%s.ssl.checkserveridentity", proto), "true"); 129 | if (proto.equals("imap")) { 130 | props.put("mail.imap.starttls.enable", "true"); 131 | } 132 | } 133 | 134 | if (proto.equals("imaps")) { 135 | props.put("mail.imaps.socketFactory", sf); 136 | } 137 | 138 | props.setProperty("mail.imap.connectiontimeout","1000"); 139 | if (useProxy) { 140 | props.put("mail.imap.socks.host","10.0.2.2"); 141 | props.put("mail.imap.socks.port","1080"); 142 | } 143 | session = Session.getInstance(props, null); 144 | //this.session.setDebug(true); 145 | store = session.getStore(proto); 146 | try { 147 | store.connect(server, username, password); 148 | res.hasUIDPLUS = ((IMAPStore) store).hasCapability("UIDPLUS"); 149 | //Log.d(TAG, "has UIDPLUS="+res.hasUIDPLUS); 150 | 151 | Folder[] folders = store.getPersonalNamespaces(); 152 | Folder folder = folders[0]; 153 | //Log.d(TAG,"Personal Namespaces="+folder.getFullName()); 154 | if (folderoverride.length() > 0) { 155 | sfolder = folderoverride; 156 | } else if (folder.getFullName().length() == 0) { 157 | sfolder = "Notes"; 158 | } else { 159 | char separator = folder.getSeparator(); 160 | sfolder = folder.getFullName() + separator + "Notes"; 161 | } 162 | // Get UIDValidity 163 | notesFolder = store.getFolder(sfolder); 164 | res.UIDValidity = ((IMAPFolder) notesFolder).getUIDValidity(); 165 | res.errorMessage = ""; 166 | res.returnCode = 0; 167 | res.notesFolder = notesFolder; 168 | return res; 169 | } catch (Exception e) { 170 | Log.d(TAG, e.getMessage()); 171 | res.errorMessage = e.getMessage(); 172 | res.returnCode = -2; 173 | return res; 174 | } 175 | 176 | } 177 | 178 | public static void GetNotes(Account account, Folder notesFolder, Context ctx, NotesDb storedNotes) throws MessagingException, IOException{ 179 | Long UIDM; 180 | Message notesMessage; 181 | File directory = new File (ctx.getFilesDir() + "/" + account.name); 182 | if (notesFolder.isOpen()) { 183 | if ((notesFolder.getMode() & Folder.READ_ONLY) != 0) 184 | notesFolder.open(Folder.READ_ONLY); 185 | } else { 186 | notesFolder.open(Folder.READ_ONLY); 187 | } 188 | UIDValidity = GetUIDValidity(account, ctx); 189 | SetUIDValidity(account, UIDValidity, ctx); 190 | Message[] notesMessages = notesFolder.getMessages(); 191 | //Log.d(TAG,"number of messages in folder="+(notesMessages.length)); 192 | for(int index=notesMessages.length-1; index>=0; index--) { 193 | notesMessage = notesMessages[index]; 194 | // write every message in files/{accountname} directory 195 | // filename is the original message uid 196 | UIDM=((IMAPFolder)notesFolder).getUID(notesMessage); 197 | String suid = UIDM.toString(); 198 | File outfile = new File (directory, suid); 199 | GetOneNote(outfile, notesMessage, storedNotes, account.name, suid, true); 200 | } 201 | } 202 | 203 | public static Sticky ReadStickynote(String stringres) { 204 | String color=new String(""); 205 | String position=new String(""); 206 | String text=new String(""); 207 | Pattern p = null; 208 | Matcher m = null; 209 | 210 | p = Pattern.compile("^COLOR:(.*?)$",Pattern.MULTILINE); 211 | m = p.matcher(stringres); 212 | if (m.find()) { color = m.group(1); } 213 | 214 | p = Pattern.compile("^POSITION:(.*?)$",Pattern.MULTILINE); 215 | m = p.matcher(stringres); 216 | if (m.find()) { position = m.group(1); } 217 | 218 | p = Pattern.compile("TEXT:(.*?)(END:|POSITION:)",Pattern.DOTALL); 219 | m = p.matcher(stringres); 220 | if (m.find()) { 221 | text = m.group(1); 222 | // Kerio Connect puts CR+LF+space every 78 characters from line 2 223 | // first line seem to be smaller. We remove these characters 224 | text = text.replaceAll("\r\n ", ""); 225 | // newline in Kerio is the string (not the character) "\n" 226 | text = text.replaceAll("\\\\n", "
"); 227 | } 228 | return new Sticky(text, position, color); 229 | } 230 | 231 | public static boolean IsConnected(){ 232 | return store!=null && store.isConnected(); 233 | } 234 | 235 | public static void DeleteNote(Folder notesFolder, int numMessage) throws MessagingException, IOException { 236 | notesFolder = store.getFolder(sfolder); 237 | if (notesFolder.isOpen()) { 238 | if ((notesFolder.getMode() & Folder.READ_WRITE) != 0) 239 | notesFolder.open(Folder.READ_WRITE); 240 | } else { 241 | notesFolder.open(Folder.READ_WRITE); 242 | } 243 | 244 | //Log.d(TAG,"UID to remove:"+numMessage); 245 | Message[] msgs = {((IMAPFolder)notesFolder).getMessageByUID(numMessage)}; 246 | notesFolder.setFlags(msgs, new Flags(Flags.Flag.DELETED), true); 247 | ((IMAPFolder)notesFolder).expunge(msgs); 248 | } 249 | 250 | // Put values in shared preferences 251 | public static void SetUIDValidity(Account account, Long UIDValidity, Context ctx) { 252 | SharedPreferences preferences = ctx.getSharedPreferences(account.name, Context.MODE_MULTI_PROCESS); 253 | SharedPreferences.Editor editor = preferences.edit(); 254 | editor.putString("Name","valid_data"); 255 | //Log.d(TAG, "UIDValidity set to in shared_prefs:"+UIDValidity); 256 | editor.putLong("UIDValidity", UIDValidity); 257 | editor.apply(); 258 | } 259 | 260 | // Retrieve values from shared preferences: 261 | public static Long GetUIDValidity(Account account, Context ctx) { 262 | UIDValidity = (long) -1; 263 | SharedPreferences preferences = ctx.getSharedPreferences(account.name, Context.MODE_MULTI_PROCESS); 264 | String name = preferences.getString("Name", ""); 265 | if(!name.equalsIgnoreCase("")) { 266 | UIDValidity = preferences.getLong("UIDValidity", -1); 267 | //Log.d(TAG, "UIDValidity got from shared_prefs:"+UIDValidity); 268 | } 269 | return UIDValidity; 270 | } 271 | 272 | public static void DisconnectFromRemote() { 273 | try { 274 | store.close(); 275 | } catch (MessagingException e) { 276 | // TODO Auto-generated catch block 277 | e.printStackTrace(); 278 | } 279 | } 280 | 281 | public static Message ReadMailFromFile (String uid, int where, boolean removeMinus, String nameDir) { 282 | File mailFile; 283 | Message message = null; 284 | mailFile = new File (nameDir,uid); 285 | 286 | switch (where){ 287 | case NEW: 288 | nameDir = nameDir + "/new"; 289 | if (removeMinus) uid = uid.substring(1); 290 | break; 291 | case DELETED: 292 | nameDir = nameDir + "/deleted"; 293 | break; 294 | case ROOT_AND_NEW: 295 | if (!mailFile.exists()) { 296 | nameDir = nameDir + "/new"; 297 | if (removeMinus) uid = uid.substring(1); 298 | } 299 | break; 300 | default: 301 | break; 302 | } 303 | 304 | mailFile = new File (nameDir,uid); 305 | InputStream mailFileInputStream = null; 306 | try { 307 | mailFileInputStream = new FileInputStream(mailFile); 308 | } catch (FileNotFoundException e1) { 309 | // TODO Auto-generated catch block 310 | e1.printStackTrace(); 311 | } 312 | try { 313 | Properties props = new Properties(); 314 | Session session = Session.getDefaultInstance(props, null); 315 | message = new MimeMessage(session, mailFileInputStream); 316 | } catch (MessagingException e) { 317 | // TODO Auto-generated catch block 318 | e.printStackTrace(); 319 | } 320 | return message; 321 | } 322 | 323 | public static AppendUID[] sendMessageToRemote (Message[] message) throws MessagingException, IOException { 324 | notesFolder = store.getFolder(sfolder); 325 | if (notesFolder.isOpen()) { 326 | if ((notesFolder.getMode() & Folder.READ_WRITE) != 0) 327 | notesFolder.open(Folder.READ_WRITE); 328 | } else { 329 | notesFolder.open(Folder.READ_WRITE); 330 | } 331 | AppendUID[] uids = ((IMAPFolder) notesFolder).appendUIDMessages(message); 332 | return uids; 333 | } 334 | 335 | public static void ClearHomeDir(Account account, Context ctx) { 336 | File directory = new File (ctx.getFilesDir() + "/" + account.name); 337 | try { 338 | FileUtils.deleteDirectory(directory); 339 | } catch (IOException e) { 340 | // TODO Auto-generated catch block 341 | e.printStackTrace(); 342 | } 343 | } 344 | 345 | public static void CreateDirs (String accountName, Context ctx) { 346 | String stringDir = ctx.getFilesDir() + "/" + accountName; 347 | File directory = new File (stringDir); 348 | directory.mkdirs(); 349 | directory = new File (stringDir + "/new"); 350 | directory.mkdirs(); 351 | directory = new File (stringDir + "/deleted"); 352 | directory.mkdirs(); 353 | } 354 | 355 | public static void GetOneNote(File outfile, Message notesMessage, NotesDb storedNotes, String accountName, String suid, boolean updateDb) { 356 | OutputStream str=null; 357 | 358 | try { 359 | str = new FileOutputStream(outfile); 360 | } catch (FileNotFoundException e) { 361 | // TODO Auto-generated catch block 362 | e.printStackTrace(); 363 | } 364 | 365 | try { 366 | notesMessage.writeTo(str); 367 | } catch (IOException e) { 368 | // TODO Auto-generated catch block 369 | e.printStackTrace(); 370 | } catch (MessagingException e) { 371 | // TODO Auto-generated catch block 372 | e.printStackTrace(); 373 | } 374 | 375 | if (!(updateDb)) return; 376 | 377 | String title = null; 378 | String[] rawvalue = null; 379 | // Some servers (such as posteo.de) don't encode non us-ascii characters in subject 380 | // This is a workaround to handle them 381 | // "lä ö ë" subject should be stored as =?charset?encoding?encoded-text?= 382 | // either =?utf-8?B?bMOkIMO2IMOr?= -> Quoted printable 383 | // or =?utf-8?Q?l=C3=A4 =C3=B6 =C3=AB?= -> Base64 384 | try { rawvalue = notesMessage.getHeader("Subject"); } catch (Exception e) {e.printStackTrace(); }; 385 | try { title = notesMessage.getSubject(); } catch (Exception e) {e.printStackTrace();} 386 | if (rawvalue[0].length() >= 2) { 387 | if (!(rawvalue[0].substring(0,2).equals("=?"))) { 388 | try { title = new String ( title.getBytes("ISO-8859-1")); } catch (Exception e) {e.printStackTrace();} 389 | } 390 | } else { 391 | try { title = new String ( title.getBytes("ISO-8859-1")); } catch (Exception e) {e.printStackTrace();} 392 | } 393 | 394 | // Get INTERNALDATE 395 | String internaldate = null; 396 | Date MessageInternaldate = null; 397 | try { 398 | MessageInternaldate = notesMessage.getReceivedDate(); 399 | } catch (MessagingException e) { 400 | // TODO Auto-generated catch block 401 | e.printStackTrace(); 402 | } 403 | String DATE_FORMAT = "yyyy-MM-dd HH:MM:ss"; 404 | SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT); 405 | internaldate = sdf.format(MessageInternaldate); 406 | 407 | OneNote aNote = new OneNote( 408 | title, 409 | internaldate, 410 | suid); 411 | storedNotes.InsertANoteInDb(aNote, accountName); 412 | } 413 | 414 | public static boolean handleRemoteNotes (Context context, Folder notesFolder, NotesDb storedNotes, String accountName, String usesticky) 415 | throws MessagingException, IOException { 416 | 417 | Message notesMessage; 418 | boolean result = false; 419 | ArrayList uids = new ArrayList(); 420 | ArrayList localListOfNotes = new ArrayList(); 421 | String remoteInternaldate; 422 | String localInternaldate; 423 | Flags flags; 424 | Boolean deleted; 425 | 426 | if (notesFolder.isOpen()) { 427 | if ((notesFolder.getMode() & Folder.READ_ONLY) != 0) 428 | notesFolder.open(Folder.READ_WRITE); 429 | } else { 430 | notesFolder.open(Folder.READ_WRITE); 431 | } 432 | 433 | // Get local list of notes uids 434 | String rootString = context.getFilesDir() + "/" + accountName; 435 | File rootDir = new File (rootString); 436 | File[] files = rootDir.listFiles(); 437 | for (File file : files) { 438 | if (file.isFile()) { 439 | localListOfNotes.add(file.getName()); 440 | } 441 | } 442 | 443 | // Add to local device, new notes added to remote 444 | Message[] notesMessages = ((IMAPFolder)notesFolder).getMessagesByUID(1, UIDFolder.LASTUID); 445 | for(int index=notesMessages.length-1; index>=0; index--) { 446 | notesMessage = notesMessages[index]; 447 | Long uid = ((IMAPFolder)notesFolder).getUID(notesMessage); 448 | // Get FLAGS 449 | flags = notesMessage.getFlags(); 450 | deleted = notesMessage.isSet(Flags.Flag.DELETED); 451 | // Buils remote list while in the loop, but only if not deleted on remote 452 | if (!deleted) { 453 | uids.add(((IMAPFolder)notesFolder).getUID(notesMessage)); 454 | } 455 | String suid = uid.toString(); 456 | if (!(localListOfNotes.contains(suid))) { 457 | File outfile = new File (rootDir, suid); 458 | GetOneNote(outfile, notesMessage, storedNotes, accountName, suid, true); 459 | result = true; 460 | } else if (usesticky.equals("true")) { 461 | //Log.d (TAG,"MANAGE STICKY"); 462 | remoteInternaldate = notesMessage.getSentDate().toLocaleString(); 463 | localInternaldate = storedNotes.GetDate(suid, accountName); 464 | if (!(remoteInternaldate.equals(localInternaldate))) { 465 | File outfile = new File (rootDir, suid); 466 | GetOneNote(outfile, notesMessage, storedNotes, accountName, suid, false); 467 | result = true; 468 | } 469 | } 470 | } 471 | 472 | // Remove from local device, notes removed from remote 473 | for(String suid : localListOfNotes) { 474 | int uid = Integer.valueOf(suid); 475 | if (!(uids.contains(new Long(uid)))) { 476 | // remove file from deleted 477 | File toDelete = new File (rootDir, suid); 478 | toDelete.delete(); 479 | // Remove note from database 480 | storedNotes.DeleteANote(suid, accountName); 481 | result = true; 482 | } 483 | } 484 | 485 | return result; 486 | } 487 | 488 | public static void RemoveAccount(Context context, Account account) { 489 | // remove Shared Preference file 490 | String rootString = context.getFilesDir().getParent() + 491 | File.separator + "shared_prefs"; 492 | File rootDir = new File (rootString); 493 | File toDelete = new File (rootDir, account.name + ".xml"); 494 | toDelete.delete(); 495 | // Remove all files and sub directories 496 | File filesDir = context.getFilesDir(); 497 | File[] files = filesDir.listFiles(); 498 | for (int i = 0; i < files.length; i++) { 499 | files[i].delete(); 500 | } 501 | // Delete account name entries in database 502 | NotesDb storedNotes = new NotesDb(context); 503 | storedNotes.OpenDb(); 504 | storedNotes.ClearDb(account.name); 505 | storedNotes.CloseDb(); 506 | } 507 | } 508 | -------------------------------------------------------------------------------- /ImapNote2/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N0ury/ImapNote2/73cc32655583237223b437777516bb0c88dcd633/ImapNote2/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /ImapNote2/src/main/res/drawable-mdpi/ic_action_about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N0ury/ImapNote2/73cc32655583237223b437777516bb0c88dcd633/ImapNote2/src/main/res/drawable-mdpi/ic_action_about.png -------------------------------------------------------------------------------- /ImapNote2/src/main/res/drawable-mdpi/ic_action_color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N0ury/ImapNote2/73cc32655583237223b437777516bb0c88dcd633/ImapNote2/src/main/res/drawable-mdpi/ic_action_color.png -------------------------------------------------------------------------------- /ImapNote2/src/main/res/drawable-mdpi/ic_action_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N0ury/ImapNote2/73cc32655583237223b437777516bb0c88dcd633/ImapNote2/src/main/res/drawable-mdpi/ic_action_delete.png -------------------------------------------------------------------------------- /ImapNote2/src/main/res/drawable-mdpi/ic_action_login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N0ury/ImapNote2/73cc32655583237223b437777516bb0c88dcd633/ImapNote2/src/main/res/drawable-mdpi/ic_action_login.png -------------------------------------------------------------------------------- /ImapNote2/src/main/res/drawable-mdpi/ic_action_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N0ury/ImapNote2/73cc32655583237223b437777516bb0c88dcd633/ImapNote2/src/main/res/drawable-mdpi/ic_action_new.png -------------------------------------------------------------------------------- /ImapNote2/src/main/res/drawable-mdpi/ic_action_refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N0ury/ImapNote2/73cc32655583237223b437777516bb0c88dcd633/ImapNote2/src/main/res/drawable-mdpi/ic_action_refresh.png -------------------------------------------------------------------------------- /ImapNote2/src/main/res/drawable-mdpi/ic_action_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N0ury/ImapNote2/73cc32655583237223b437777516bb0c88dcd633/ImapNote2/src/main/res/drawable-mdpi/ic_action_save.png -------------------------------------------------------------------------------- /ImapNote2/src/main/res/drawable-mdpi/ic_action_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N0ury/ImapNote2/73cc32655583237223b437777516bb0c88dcd633/ImapNote2/src/main/res/drawable-mdpi/ic_action_search.png -------------------------------------------------------------------------------- /ImapNote2/src/main/res/drawable-mdpi/ic_action_user_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N0ury/ImapNote2/73cc32655583237223b437777516bb0c88dcd633/ImapNote2/src/main/res/drawable-mdpi/ic_action_user_edit.png -------------------------------------------------------------------------------- /ImapNote2/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N0ury/ImapNote2/73cc32655583237223b437777516bb0c88dcd633/ImapNote2/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /ImapNote2/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N0ury/ImapNote2/73cc32655583237223b437777516bb0c88dcd633/ImapNote2/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ImapNote2/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N0ury/ImapNote2/73cc32655583237223b437777516bb0c88dcd633/ImapNote2/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ImapNote2/src/main/res/layout/account_selection.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 21 | 22 | 23 | 30 | 31 | 32 | 39 | 40 | 41 | 42 | 43 | 44 | 51 | 52 | 53 | 60 | 61 | 62 | 69 | 70 | 71 | 77 | 78 | 79 | 86 | 87 | 88 | 95 | 96 | 97 | 104 | 105 | 106 | 110 | 111 | 112 | 119 | 120 | 129 | 130 | 137 | 138 | 139 | 149 | 150 | 151 | 152 | 159 | 160 | 167 | 168 | 173 | 174 | 182 | 183 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | -------------------------------------------------------------------------------- /ImapNote2/src/main/res/layout/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 16 | 17 | 25 | 26 | 27 | 28 | 31 | 32 | 37 | 38 |