@Override
 public void openItem(int position) {
   if (position == 0) {
     Uri uri_to_go = null;
     if (parentLink == SLS) uri_to_go = Uri.parse(HomeAdapter.DEFAULT_LOC);
     else {
       // 0000-0000:folder%2Fsubfolder
       uri_to_go = getParent(uri);
       if (uri_to_go == null) uri_to_go = Uri.parse(HomeAdapter.DEFAULT_LOC);
     }
     String pos_to = null;
     String cur_path = getPath(uri, true);
     if (cur_path != null) pos_to = cur_path.substring(cur_path.lastIndexOf('/'));
     commander.Navigate(uri_to_go, null, pos_to);
   } else {
     Item item = items[position - 1];
     if (item.dir) commander.Navigate((Uri) item.origin, null, null);
     else {
       Uri to_open;
       String full_name = getItemName(position, true);
       if (full_name != null && full_name.charAt(0) == '/')
         to_open = Uri.parse(Utils.escapePath(full_name));
       else to_open = (Uri) item.origin;
       commander.Open(to_open, null);
     }
   }
 }
 @Override
 public void run() {
   try {
     Init(null);
     cr = ctx.getContentResolver();
     int cnt = deleteFiles(dirUri, mList);
     sendResult(Utils.getOpReport(ctx, cnt, R.string.deleted));
   } catch (Exception e) {
     sendProgress(e.getMessage(), Commander.OPERATION_FAILED_REFRESH_REQUIRED);
   }
 }
  @Override
  public void onClick(DialogInterface idialog, int whichButton) {
    if (whichButton == DialogInterface.BUTTON_POSITIVE) {
      try {
        f.setComment(ce.getText().toString());
        String path = pe.getText().toString().trim();
        if (se != null) {
          Uri.Builder uri_b = uri.buildUpon();
          if (ftp) {
            uri_b.encodedQuery("");
            Object esio = en.getSelectedItem();
            if (esio instanceof String) {
              String enc_s = (String) esio;
              if (Utils.str(enc_s) && !"Default".equals(enc_s)) {
                enc_s = enc_s.substring(0, enc_s.indexOf("\n"));
                uri_b.appendQueryParameter("e", enc_s);
              }
            }
            if (active_ftp_cb.isChecked()) uri_b.appendQueryParameter("a", "true");
          }
          String serv = se.getText().toString().trim();
          f.setUri(
              uri_b
                  .encodedAuthority(Utils.encodeToAuthority(serv))
                  .encodedPath(Utils.escapePath(path))
                  .build());
          Log.i(TAG, "Uri:" + f.getUri());
          String domain = de != null ? de.getText().toString().trim() : "";
          String usernm = ue.getText().toString().trim();
          f.setCredentials(
              domain.length() > 0 ? domain + ";" + usernm : usernm, we.getText().toString().trim());
        } else {
          f.setUri(uri.buildUpon().encodedPath(Utils.escapePath(path)).build());
        }

        owner.invalidate();
      } catch (Exception e) {
        Log.e(TAG, null, e);
      }
    }
  }
  public final String getPath(Uri u, boolean dir) {
    try {
      final List<String> paths = u.getPathSegments();
      if (paths.size() < 4) return null;
      String path_part = paths.get(3);
      int col_pos = path_part.lastIndexOf(':');
      String volume, path_root = null, sub_path, full_path;
      volume = paths.get(1);
      sub_path = path_part.substring(col_pos + 1);

      if (volume.startsWith("primary"))
        return Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + sub_path;
      else {
        try {
          File probe;
          volume = volume.substring(0, volume.length() - 1);
          if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            full_path = "/mnt/media_rw/" + volume + "/" + sub_path;
            probe = new File(full_path);
            if (dir ? probe.isDirectory() : probe.isFile()) return full_path;
          } else {
            path_root = Utils.getSecondaryStorage();
            if (path_root != null) {
              full_path = Utils.mbAddSl(path_root) + sub_path;
              probe = new File(full_path);
              if (dir ? probe.isDirectory() : probe.isFile()) return full_path;
            }
          }
        } catch (Exception e) {
        }
        if (path_root == null) path_root = volume; // better than nothing
      }
      return path_root + "/" + sub_path;
    } catch (Exception e) {
      Log.e(TAG, "Can't get the real location of " + u, e);
    }
    return null;
  }
 @Override
 public boolean receiveItems(String[] uris, int move_mode) {
   try {
     if (uris == null || uris.length == 0) return false;
     File[] list = Utils.getListOfFiles(uris);
     if (list != null) {
       notify(Commander.OPERATION_STARTED);
       commander.startEngine(new CopyToEngine(list, move_mode));
       return true;
     }
   } catch (Exception e) {
     e.printStackTrace();
   }
   return false;
 }
 @Override
 public void run() {
   try {
     Init(null);
     cr = ctx.getContentResolver();
     int cnt = copyFiles(mList, destFolder);
     if (recipient != null) {
       sendReceiveReq(destFolder);
       return;
     }
     sendResult(Utils.getOpReport(owner.ctx, cnt, move ? R.string.moved : R.string.copied));
   } catch (Exception e) {
     sendProgress(e.getMessage(), Commander.OPERATION_FAILED_REFRESH_REQUIRED);
   }
 }
    @Override
    public void run() {
      sendProgress(ctx.getString(R.string.preparing), 0, 0);
      try {
        int l = iList.length;
        wakeLock.acquire();
        int num = copyFiles(iList, mDest);

        wakeLock.release();
        String report = Utils.getOpReport(ctx, num, move ? R.string.moved : R.string.copied);
        sendResult(report);
      } catch (Exception e) {
        sendProgress(e.getMessage(), Commander.OPERATION_FAILED_REFRESH_REQUIRED);
        return;
      }
    }
  protected void startThumbnailCreation() {
    if (thumbnail_size_perc <= 0) return;
    // Log.i( TAG, "thumbnails " + thumbnail_size_perc );
    String path = getPath(uri, true);
    if (path == null || path.charAt(0) != '/') return;

    if (tht != null) tht.interrupt();

    Handler h =
        new Handler() {
          public void handleMessage(Message msg) {
            notifyDataSetChanged();
          }
        };
    tht = new ThumbnailsThread(this, h, Utils.mbAddSl(path), items);
    tht.start();
  }
 @Override
 public void populateContextMenu(
     ContextMenu menu, AdapterView.AdapterContextMenuInfo acmi, int num) {
   try {
     if (acmi.position != 0) {
       Item item = (Item) getItem(acmi.position);
       if (!item.dir && ".zip".equals(Utils.getFileExt(item.name))) {
         menu.add(0, R.id.open, 0, R.string.open);
         menu.add(0, R.id.extract, 0, R.string.extract_zip);
       }
       if (item.dir && num == 1 && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO)
         menu.add(0, R.id.rescan_dir, 0, R.string.rescan);
     }
     super.populateContextMenu(menu, acmi, num);
   } catch (Exception e) {
     Log.e(TAG, "", e);
   }
 }
    @Override
    public void run() {
      sendProgress(ctx.getString(R.string.preparing), 0, 0);
      try {
        int l = fList.length;
        wakeLock.acquire();
        int num = copyFiles(fList, mDest);

        if (del_src_dir) {
          File src_dir = fList[0].getParentFile();
          if (src_dir != null) src_dir.delete();
        }
        wakeLock.release();
        // XXX: assume (move && !del_src_dir)==true when copy from app: to the FS
        if (delerr_counter == counter) move = false; // report as copy
        String report =
            Utils.getOpReport(ctx, num, move && !del_src_dir ? R.string.moved : R.string.copied);
        sendResult(report);
      } catch (Exception e) {
        sendProgress(e.getMessage(), Commander.OPERATION_FAILED_REFRESH_REQUIRED);
        return;
      }
    }
  public FavDialog(Context c, Favorite f_, FavsAdapter owner_) {
    try {
      owner = owner_;
      f = f_;
      uri = f.getUri();
      if (uri == null) return;
      LayoutInflater factory = LayoutInflater.from(c);
      View fdv = factory.inflate(R.layout.server, null);
      if (fdv == null) return;
      View bb = fdv.findViewById(R.id.buttons_block);
      bb.setVisibility(View.GONE);
      View cb = fdv.findViewById(R.id.comment_block);
      cb.setVisibility(View.VISIBLE);
      ce = (EditText) cb.findViewById(R.id.comment_edit);
      ce.setText(f.getComment());

      pe = (EditText) fdv.findViewById(R.id.path_edit);
      String path = uri.getPath();
      /*
      String quer = uri.getQuery();
      if( quer != null )
          path += "?" + quer;
      String frag = uri.getFragment();
      if( frag != null )
          path += "#" + frag;
      */
      pe.setText(path);

      String schm = uri.getScheme();
      View sb = fdv.findViewById(R.id.server_block);
      View db = fdv.findViewById(R.id.domainbrowse_block);
      View ib = fdv.findViewById(R.id.credentials_block);
      View fb = fdv.findViewById(R.id.ftp_block);

      sftp = "sftp".equals(schm);
      ftp = "ftp".equals(schm);
      smb = "smb".equals(schm);
      if (ftp || smb || sftp) {
        se = (EditText) sb.findViewById(R.id.server_edit);
        String host = uri.getHost();
        if (host != null) {
          int port = uri.getPort();
          if (port > 0) host += ":" + port;
          se.setText(host);
        }
        if (ftp || sftp) {
          db.setVisibility(View.GONE);
        }
        String username = f.getUserName();

        if (smb && username != null) {
          int sep = username.indexOf('\\');
          if (sep < 0) sep = username.indexOf(';');
          de = (EditText) ib.findViewById(R.id.domain_edit);
          if (sep >= 0) {
            de.setText(username.substring(0, sep));
            username = username.substring(sep + 1);
          }
        }
        ue = (EditText) ib.findViewById(R.id.username_edit);
        ue.setText(username);
        we = (EditText) ib.findViewById(R.id.password_edit);
        we.setText(f.getPassword());
        fb.setVisibility(ftp ? View.VISIBLE : View.GONE);
        if (ftp) {
          en = (Spinner) fb.findViewById(R.id.encoding);
          ArrayAdapter<CharSequence> adapter =
              ArrayAdapter.createFromResource(
                  c, R.array.encoding, android.R.layout.simple_spinner_item);
          adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
          en.setAdapter(adapter);
          try {
            String enc_s = uri.getQueryParameter("e");
            if (Utils.str(enc_s) && !"Default".equals(enc_s)) {
              for (int i = 0; i < adapter.getCount(); i++)
                if (adapter.getItem(i).toString().indexOf(enc_s) == 0) {
                  en.setSelection(i);
                  break;
                }
            }
          } catch (Exception e) {
            Log.e(TAG, "", e);
          }
          active_ftp_cb = (CheckBox) fb.findViewById(R.id.active);
          String a_s = uri.getQueryParameter("a");
          active_ftp_cb.setChecked("true".equals(a_s));
        }
      } else {
        sb.setVisibility(View.GONE);
        db.setVisibility(View.GONE);
        ib.setVisibility(View.GONE);
        fb.setVisibility(View.GONE);
      }

      new AlertDialog.Builder(c)
          .setTitle(c.getString(R.string.fav_dialog))
          .setView(fdv)
          .setPositiveButton(R.string.dialog_ok, this)
          .setNegativeButton(R.string.dialog_cancel, this)
          .show();
    } catch (Exception e) {
      Log.e(TAG, null, e);
    }
  }
    private final int copyFiles(File[] list, Uri dest) throws InterruptedException {
      File file = null;
      for (int i = 0; i < list.length; i++) {
        InputStream is = null;
        OutputStream os = null;
        file = list[i];
        if (file == null) {
          error(ctx.getString(R.string.unkn_err));
          break;
        }
        Uri dest_uri = null;
        try {
          if (isStopReq()) {
            error(ctx.getString(R.string.canceled));
            break;
          }
          String fn = file.getName();
          String to_append = "%2f" + Utils.escapePath(fn);
          dest_uri = dest.buildUpon().encodedPath(dest.getEncodedPath() + to_append).build();
          String mime = getMime(dest_uri);
          if (file.isDirectory()) {
            if (depth++ > 40) {
              error(ctx.getString(R.string.too_deep_hierarchy));
              break;
            }
            if (mime != null) {
              if (!Document.MIME_TYPE_DIR.equals(mime)) {
                error(ctx.getString(R.string.cant_md));
                break;
              }
            } else {
              DocumentsContract.createDocument(cr, dest, Document.MIME_TYPE_DIR, fn);
            }
            copyFiles(file.listFiles(), dest_uri);
            if (errMsg != null) break;
            depth--;
            counter++;
          } else {
            if (mime != null) {
              int res = askOnFileExist(ctx.getString(R.string.file_exist, fn), commander);
              if (res == Commander.SKIP) continue;
              if (res == Commander.ABORT) break;
              if (res == Commander.REPLACE) {
                File dest_file = new File(getPath(dest_uri, false));
                if (dest_file.equals(file)) {
                  Log.w(TAG, "Not going to copy file to itself");
                  continue;
                }
                Log.v(TAG, "Overwritting file " + fn);
                DocumentsContract.deleteDocument(cr, dest_uri);
              }
            } else mime = Utils.getMimeByExt(Utils.getFileExt(fn));
            dest_uri = DocumentsContract.createDocument(cr, dest, mime, fn);
            if (dest_uri == null) {
              error(ctx.getString(R.string.cant_create, fn, ""));
              break;
            }
            String dest_path = dest_uri.getPath();
            if (dest_path.indexOf(fn, dest_path.length() - fn.length() - 1) < 0) // SAF suxx
            dest_uri = DocumentsContract.renameDocument(cr, dest_uri, fn);

            is = new FileInputStream(file);
            os = cr.openOutputStream(dest_uri);
            long copied = 0, size = file.length();

            long start_time = 0;
            int speed = 0;
            int so_far = (int) (totalBytes * conv);

            String sz_s = Utils.getHumanSize(size);
            int fnl = fn.length();
            String rep_s =
                ctx.getString(
                    R.string.copying, fnl > CUT_LEN ? "\u2026" + fn.substring(fnl - CUT_LEN) : fn);
            int n = 0;
            long nn = 0;

            while (true) {
              if (nn == 0) {
                start_time = System.currentTimeMillis();
                sendProgress(
                    rep_s + sizeOfsize(copied, sz_s), so_far, (int) (totalBytes * conv), speed);
              }
              n = is.read(buf);
              if (n < 0) {
                long time_delta = System.currentTimeMillis() - start_time;
                if (time_delta > 0) {
                  speed = (int) (MILLI * nn / time_delta);
                  sendProgress(
                      rep_s + sizeOfsize(copied, sz_s), so_far, (int) (totalBytes * conv), speed);
                }
                break;
              }
              os.write(buf, 0, n);
              nn += n;
              copied += n;
              totalBytes += n;
              if (isStopReq()) {
                Log.d(TAG, "Interrupted!");
                error(ctx.getString(R.string.canceled));
                return counter;
              }
              long time_delta = System.currentTimeMillis() - start_time;
              if (time_delta > DELAY) {
                speed = (int) (MILLI * nn / time_delta);
                // Log.v( TAG, "bytes: " + nn + " time: " + time_delta + " speed: " + speed );
                nn = 0;
              }
            }
            is.close();
            os.close();
            is = null;
            os = null;
            /*
            ContentValues cv = new ContentValues();
            cv.put( Document.COLUMN_LAST_MODIFIED, file.lastModified() );
            cr.update( dest_uri, cv, null, null ); //throws..
            */
            if (i >= list.length - 1)
              sendProgress(
                  ctx.getString(R.string.copied_f, fn) + sizeOfsize(copied, sz_s),
                  (int) (totalBytes * conv));
            counter++;
          }
          if (move) {
            if (!file.delete()) {
              sendProgress(ctx.getString(R.string.cant_del, fn), -1);
              delerr_counter++;
            }
          }
        } catch (Exception e) {
          Log.e(TAG, "", e);
          error(ctx.getString(R.string.rtexcept, file.getAbsolutePath(), e.getMessage()));
        } finally {
          try {
            if (is != null) is.close();
            if (os != null) os.close();
          } catch (IOException e) {
            error(ctx.getString(R.string.acc_err, file.getAbsolutePath(), e.getMessage()));
          }
        }
      }
      return counter;
    }
    private final int copyFiles(Item[] l, File dest) throws Exception {
      if (l == null) return 0;
      int cnt = 0;
      int num = l.length;
      for (int i = 0; i < num; i++) {
        sleep(1);
        if (isStopReq()) throw new Exception(s(R.string.canceled));
        Item item = l[i];
        String fn = item.name;
        sendProgress(ctx.getString(R.string.copying, fn), 0);
        File dest_file = new File(dest, fn);
        Uri u = (Uri) item.origin;
        boolean ok = false;
        if (item.dir) {
          if (!dest_file.exists()) dest_file.mkdir();
          ArrayList<SAFItem> tmp_list = getChildren(u);
          SAFItem[] sub_items = new SAFItem[tmp_list.size()];
          tmp_list.toArray(sub_items);
          cnt += copyFiles(sub_items, dest_file);
          if (errMsg != null) break;
          ok = true;
        } else {
          if (dest_file.exists()) {
            int res =
                askOnFileExist(
                    owner.ctx.getString(R.string.file_exist, dest_file.getAbsolutePath()),
                    owner.commander);
            if (res == Commander.ABORT) {
              error(owner.ctx.getString(R.string.interrupted));
              break;
            }
            if (res == Commander.SKIP) continue;
            if (res == Commander.REPLACE) {
              if (!dest_file.delete()) {
                error(owner.ctx.getString(R.string.cant_del, dest_file.getAbsoluteFile()));
                break;
              }
            }
          }
          int fnl = fn.length();
          String rep_s =
              owner.ctx.getString(
                  R.string.copying, fnl > CUT_LEN ? "\u2026" + fn.substring(fnl - CUT_LEN) : fn);

          long copied = 0, size = item.size;
          String sz_s = Utils.getHumanSize(size, false);
          double conv = 100. / size;
          int n;
          OutputStream os = null;
          InputStream is = null;
          try {
            os = new FileOutputStream(dest_file);
            is = cr.openInputStream(u);
            while ((n = is.read(buf)) != -1) {
              os.write(buf, 0, n);
              copied += n;
              sendProgress(rep_s + sizeOfsize(copied, sz_s), (int) (copied * conv));
              Thread.sleep(1);
            }
            ok = true;
          } catch (Exception e) {
            e.printStackTrace();
          } finally {
            if (is != null) is.close();
            if (os != null) os.close();
          }
          try {
            dest_file.setLastModified(item.date.getTime());
          } catch (Exception e) {
          }
        }
        if (move && ok) DocumentsContract.deleteDocument(cr, u);
        cnt++;
      }
      return cnt;
    }