Beispiel #1
0
  /**
   * Chooses files that match the specified pattern.
   *
   * @param file file filter
   * @param content content filter
   * @param root root directory
   * @return sorted file paths
   * @throws InterruptedException interruption
   */
  String[] filter(final String file, final String content, final IOFile root)
      throws InterruptedException {

    final long id = ++filterId;
    final TreeSet<String> results = new TreeSet<>();
    final int[] search = new TokenParser(Token.lc(Token.token(content))).toArray();

    // glob pattern
    final ProjectCache pc = cache(root);
    if (file.contains("*") || file.contains("?")) {
      final Pattern pt = Pattern.compile(IOFile.regex(file));
      for (final String path : pc) {
        final int offset = offset(path, true);
        if (pt.matcher(path.substring(offset)).matches() && filterContent(path, search)) {
          results.add(path);
          if (results.size() >= MAXHITS) break;
        }
        if (id != filterId) throw new InterruptedException();
      }
    } else {
      // starts-with, contains, camel case
      final String pttrn = file.toLowerCase(Locale.ENGLISH).replace('\\', '/');
      final HashSet<String> exclude = new HashSet<>();
      final boolean pathSearch = pttrn.indexOf('/') != -1;
      for (int i = 0; i < (pathSearch ? 2 : 3); i++) {
        filter(pttrn, search, i, results, exclude, pathSearch, pc, id);
      }
    }
    return results.toArray(new String[results.size()]);
  }
Beispiel #2
0
  /**
   * Constructor, specifying the server host:port combination, login data and an output stream.
   *
   * @param host server name
   * @param port server port
   * @param user user name
   * @param pass password
   * @param output client output; if set to {@code null}, results will be returned as strings.
   * @throws IOException I/O exception
   */
  public ClientSession(
      final String host,
      final int port,
      final String user,
      final String pass,
      final OutputStream output)
      throws IOException {

    super(output);
    ehost = host;
    socket = new Socket();
    try {
      // limit timeout to five seconds
      socket.connect(new InetSocketAddress(host, port), 5000);
    } catch (final IllegalArgumentException ex) {
      throw new BaseXException(ex);
    }
    sin = socket.getInputStream();

    // receive timestamp
    final BufferInput bi = new BufferInput(sin);
    final String ts = bi.readString();

    // send user name and hashed password/timestamp
    sout = PrintOutput.get(socket.getOutputStream());
    send(user);
    send(Token.md5(Token.md5(pass) + ts));
    sout.flush();

    // receive success flag
    if (!ok(bi)) throw new LoginException();
  }
Beispiel #3
0
  /**
   * Searches a string in a file.
   *
   * @param path file path
   * @param search codepoints of search string
   * @return success flag
   */
  private static boolean filterContent(final String path, final int[] search) {
    final int cl = search.length;
    if (cl == 0) return true;

    try (final TextInput ti = new TextInput(new IOFile(path))) {
      final IntList il = new IntList(cl - 1);
      int c = 0;
      while (true) {
        if (!il.isEmpty()) {
          if (il.remove(0) == search[c++]) continue;
          c = 0;
        }
        while (true) {
          final int cp = ti.read();
          if (cp == -1 || !XMLToken.valid(cp)) return false;
          final int lc = Token.lc(cp);
          if (c > 0) il.add(lc);
          if (lc == search[c]) {
            if (++c == cl) return true;
          } else {
            c = 0;
            break;
          }
        }
      }
    } catch (final IOException ex) {
      // file may not be accessible
      Util.debug(ex);
      return false;
    }
  }
Beispiel #4
0
 /**
  * Sets the output text.
  *
  * @param text output text
  * @param size text size
  */
 public final void setText(final byte[] text, final int size) {
   byte[] txt = text;
   if (Token.contains(text, '\r')) {
     // remove carriage returns
     int ns = 0;
     for (int r = 0; r < size; ++r) {
       final byte b = text[r];
       if (b != '\r') text[ns++] = b;
     }
     // new text is different...
     txt = Arrays.copyOf(text, ns);
   } else if (text.length != size) {
     txt = Arrays.copyOf(text, size);
   }
   if (editor.text(txt)) {
     if (hist != null) hist.store(txt, editor.pos(), 0);
   }
   if (isShowing()) resizeCode.invokeLater();
 }
Beispiel #5
0
  /**
   * Refreshes the view after a file has been saved.
   *
   * @param root root directory
   * @param ctx database context
   * @throws InterruptedException interruption
   */
  void parse(final IOFile root, final Context ctx) throws InterruptedException {
    final long id = ++parseId;
    final HashSet<String> parsed = new HashSet<>();
    final TreeMap<String, InputInfo> errs = new TreeMap<>();

    // collect files to be parsed
    final ProjectCache pc = cache(root);
    final StringList mods = new StringList(), lmods = new StringList();
    for (final String path : pc) {
      final IOFile file = new IOFile(path);
      if (file.hasSuffix(IO.XQSUFFIXES)) (file.hasSuffix(IO.XQMSUFFIX) ? lmods : mods).add(path);
    }
    mods.add(lmods);

    // parse modules
    for (final String path : mods) {
      if (id != parseId) throw new InterruptedException();
      if (parsed.contains(path)) continue;

      final IOFile file = new IOFile(path);
      try (final TextInput ti = new TextInput(file)) {
        // parse query
        try (final QueryContext qc = new QueryContext(ctx)) {
          final String input = ti.cache().toString();
          final boolean lib = QueryProcessor.isLibrary(input);
          qc.parse(input, lib, path, null);
          // parsing was successful: remember path
          parsed.add(path);
          for (final byte[] mod : qc.modParsed) parsed.add(Token.string(mod));
        } catch (final QueryException ex) {
          // parsing failed: remember path
          final InputInfo ii = ex.info();
          errs.put(path, ii);
          parsed.add(ii.path());
        }
      } catch (final IOException ex) {
        // file may not be accessible
        Util.debug(ex);
      }
    }
    errors = errs;
  }
Beispiel #6
0
 /**
  * Sends a string to the server.
  *
  * @param s string to be sent
  * @throws IOException I/O exception
  */
 protected void send(final String s) throws IOException {
   sout.write(Token.token(s));
   sout.write(0);
 }
Beispiel #7
0
/**
 * Functions on archives.
 *
 * @author BaseX Team 2005-12, BSD License
 * @author Christian Gruen
 */
public class FNArchive extends StandardFunc {
  /** Archive namespace. */
  private static final Atts NS = new Atts(ARCHIVE, ARCHIVEURI);
  /** Element: Entry. */
  private static final QNm Q_ENTRY = new QNm("archive:entry", ARCHIVEURI);
  /** Element: options. */
  private static final QNm Q_OPTIONS = new QNm("archive:options", ARCHIVEURI);
  /** Option: algorithm. */
  private static final QNm Q_FORMAT = new QNm("archive:format", ARCHIVEURI);
  /** Option: algorithm. */
  private static final QNm Q_ALGORITHM = new QNm("archive:algorithm", ARCHIVEURI);
  /** Root node test. */
  private static final ExtTest TEST = new ExtTest(NodeType.ELM, Q_ENTRY);

  /** Level. */
  private static final QNm Q_LEVEL = new QNm("compression-level");
  /** Encoding. */
  private static final QNm Q_ENCODING = new QNm("encoding");
  /** Last modified. */
  private static final QNm Q_LAST_MOD = new QNm("last-modified");
  /** Compressed size. */
  private static final QNm Q_COMP_SIZE = new QNm("compressed-size");
  /** Uncompressed size. */
  private static final QNm Q_SIZE = new QNm("size");
  /** Value. */
  private static final QNm Q_VALUE = new QNm("value");

  /** Option: format. */
  private static final byte[] FORMAT = Token.token("format");
  /** Option: algorithm. */
  private static final byte[] ALGORITHM = Token.token("algorithm");
  /** Option: algorithm: deflate. */
  private static final byte[] DEFLATE = Token.token("deflate");
  /** Option: algorithm: stored. */
  private static final byte[] STORED = Token.token("stored");
  /** Option: algorithm: unknown. */
  private static final byte[] UNKNOWN = Token.token("unknown");

  /**
   * Constructor.
   *
   * @param ii input info
   * @param f function definition
   * @param e arguments
   */
  public FNArchive(final InputInfo ii, final Function f, final Expr... e) {
    super(ii, f, e);
  }

  @Override
  public Iter iter(final QueryContext ctx) throws QueryException {
    switch (sig) {
      case _ARCHIVE_ENTRIES:
        return entries(ctx);
      case _ARCHIVE_EXTRACT_TEXT:
        return extractText(ctx);
      case _ARCHIVE_EXTRACT_BINARY:
        return extractBinary(ctx);
      default:
        return super.iter(ctx);
    }
  }

  @Override
  public Item item(final QueryContext ctx, final InputInfo ii) throws QueryException {
    checkCreate(ctx);
    switch (sig) {
      case _ARCHIVE_CREATE:
        return create(ctx);
      case _ARCHIVE_UPDATE:
        return update(ctx);
      case _ARCHIVE_DELETE:
        return delete(ctx);
      case _ARCHIVE_OPTIONS:
        return options(ctx);
      default:
        return super.item(ctx, ii);
    }
  }

  /**
   * Creates a new archive.
   *
   * @param ctx query context
   * @return archive
   * @throws QueryException query exception
   */
  private B64 create(final QueryContext ctx) throws QueryException {
    final Iter entr = ctx.iter(expr[0]);
    final Iter cont = ctx.iter(expr[1]);
    final Item opt = expr.length > 2 ? expr[2].item(ctx, info) : null;
    final TokenMap map = new FuncParams(Q_OPTIONS, info).parse(opt);

    final byte[] f = map.get(FORMAT);
    final String format = f != null ? string(lc(f)) : "zip";
    final ArchiveOut out = ArchiveOut.get(format, info);
    // check algorithm
    final byte[] alg = map.get(ALGORITHM);
    int level = ZipEntry.DEFLATED;
    if (alg != null) {
      if (format.equals("zip") && !eq(alg, STORED, DEFLATE)
          || format.equals("gzip") && !eq(alg, DEFLATE)) {
        ARCH_SUPP.thrw(info, ALGORITHM, alg);
      }
      if (eq(alg, STORED)) level = ZipEntry.STORED;
      else if (eq(alg, DEFLATE)) level = ZipEntry.DEFLATED;
    }
    out.level(level);

    try {
      int e = 0;
      int c = 0;
      Item en, cn;
      while (true) {
        en = entr.next();
        cn = cont.next();
        if (en == null || cn == null) break;
        if (out instanceof GZIPOut && c > 0)
          ARCH_ONE.thrw(info, format.toUpperCase(Locale.ENGLISH));
        add(checkElmStr(en), cn, out, level);
        e++;
        c++;
      }
      // count remaining entries
      if (cn != null) do c++; while (cont.next() != null);
      if (en != null) do e++; while (entr.next() != null);
      if (e != c) throw ARCH_DIFF.thrw(info, e, c);
    } catch (final IOException ex) {
      Util.debug(ex);
      throw ARCH_FAIL.thrw(info, ex);
    } finally {
      out.close();
    }
    return new B64(out.toArray());
  }

  /**
   * Returns the options of an archive.
   *
   * @param ctx query context
   * @return entries
   * @throws QueryException query exception
   */
  private FElem options(final QueryContext ctx) throws QueryException {
    final B64 archive = (B64) checkType(checkItem(expr[0], ctx), AtomType.B64);
    String format = null;
    int level = -1;

    final ArchiveIn arch = ArchiveIn.get(archive.input(info), info);
    try {
      format = arch.format();
      while (arch.more()) {
        final ZipEntry ze = arch.entry();
        if (ze.isDirectory()) continue;
        level = ze.getMethod();
        break;
      }
    } catch (final IOException ex) {
      Util.debug(ex);
      ARCH_FAIL.thrw(info, ex);
    } finally {
      arch.close();
    }

    // create result element
    final FElem e = new FElem(Q_OPTIONS, NS);
    if (format != null) e.add(new FElem(Q_FORMAT).add(Q_VALUE, format));
    if (level >= 0) {
      final byte[] lvl = level == 8 ? DEFLATE : level == 0 ? STORED : UNKNOWN;
      e.add(new FElem(Q_ALGORITHM).add(Q_VALUE, lvl));
    }
    return e;
  }

  /**
   * Returns the entries of an archive.
   *
   * @param ctx query context
   * @return entries
   * @throws QueryException query exception
   */
  private Iter entries(final QueryContext ctx) throws QueryException {
    final B64 archive = (B64) checkType(checkItem(expr[0], ctx), AtomType.B64);

    final ValueBuilder vb = new ValueBuilder();
    final ArchiveIn in = ArchiveIn.get(archive.input(info), info);
    try {
      while (in.more()) {
        final ZipEntry ze = in.entry();
        if (ze.isDirectory()) continue;
        final FElem e = new FElem(Q_ENTRY, NS);
        long s = ze.getSize();
        if (s != -1) e.add(Q_SIZE, token(s));
        s = ze.getTime();
        if (s != -1) e.add(Q_LAST_MOD, new Dtm(s, info).string(info));
        s = ze.getCompressedSize();
        if (s != -1) e.add(Q_COMP_SIZE, token(s));
        e.add(ze.getName());
        vb.add(e);
      }
      return vb;
    } catch (final IOException ex) {
      Util.debug(ex);
      throw ARCH_FAIL.thrw(info, ex);
    } finally {
      in.close();
    }
  }

  /**
   * Extracts text entries.
   *
   * @param ctx query context
   * @return text entry
   * @throws QueryException query exception
   */
  private ValueBuilder extractText(final QueryContext ctx) throws QueryException {
    final String enc = encoding(2, ARCH_ENCODING, ctx);
    final ValueBuilder vb = new ValueBuilder();
    for (final byte[] b : extract(ctx)) vb.add(Str.get(encode(b, enc)));
    return vb;
  }

  /**
   * Extracts binary entries.
   *
   * @param ctx query context
   * @return binary entry
   * @throws QueryException query exception
   */
  private ValueBuilder extractBinary(final QueryContext ctx) throws QueryException {
    final ValueBuilder vb = new ValueBuilder();
    for (final byte[] b : extract(ctx)) vb.add(new B64(b));
    return vb;
  }

  /**
   * Updates an archive.
   *
   * @param ctx query context
   * @return updated archive
   * @throws QueryException query exception
   */
  private B64 update(final QueryContext ctx) throws QueryException {
    final B64 archive = (B64) checkType(checkItem(expr[0], ctx), AtomType.B64);
    // entries to be updated
    final TokenObjMap<Item[]> hm = new TokenObjMap<Item[]>();

    final Iter entr = ctx.iter(expr[1]);
    final Iter cont = ctx.iter(expr[2]);
    int e = 0;
    int c = 0;
    Item en, cn;
    while (true) {
      en = entr.next();
      cn = cont.next();
      if (en == null || cn == null) break;
      hm.add(checkElmStr(en).string(info), new Item[] {en, cn});
      e++;
      c++;
    }
    // count remaining entries
    if (cn != null) do c++; while (cont.next() != null);
    if (en != null) do e++; while (entr.next() != null);
    if (e != c) ARCH_DIFF.thrw(info, e, c);

    final ArchiveIn in = ArchiveIn.get(archive.input(info), info);
    final ArchiveOut out = ArchiveOut.get(in.format(), info);
    try {
      if (in instanceof GZIPIn) ARCH_MODIFY.thrw(info, in.format().toUpperCase(Locale.ENGLISH));
      // delete entries to be updated
      while (in.more()) if (!hm.contains(token(in.entry().getName()))) out.write(in);
      // add new and updated entries
      for (final byte[] h : hm) {
        if (h == null) continue;
        final Item[] it = hm.get(h);
        add(it[0], it[1], out, ZipEntry.DEFLATED);
      }
    } catch (final IOException ex) {
      Util.debug(ex);
      ARCH_FAIL.thrw(info, ex);
    } finally {
      in.close();
      out.close();
    }
    return new B64(out.toArray());
  }

  /**
   * Deletes files from an archive.
   *
   * @param ctx query context
   * @return updated archive
   * @throws QueryException query exception
   */
  private B64 delete(final QueryContext ctx) throws QueryException {
    final B64 archive = (B64) checkType(checkItem(expr[0], ctx), AtomType.B64);
    // entries to be deleted
    final TokenObjMap<Item[]> hm = new TokenObjMap<Item[]>();
    final Iter names = ctx.iter(expr[1]);
    for (Item en; (en = names.next()) != null; ) {
      hm.add(checkElmStr(en).string(info), null);
    }

    final ArchiveIn in = ArchiveIn.get(archive.input(info), info);
    final ArchiveOut out = ArchiveOut.get(in.format(), info);
    try {
      if (in instanceof GZIPIn) ARCH_MODIFY.thrw(info, in.format().toUpperCase(Locale.ENGLISH));
      while (in.more()) if (!hm.contains(token(in.entry().getName()))) out.write(in);
    } catch (final IOException ex) {
      Util.debug(ex);
      ARCH_FAIL.thrw(info, ex);
    } finally {
      in.close();
      out.close();
    }
    return new B64(out.toArray());
  }

  /**
   * Extracts entries from the archive.
   *
   * @param ctx query context
   * @return text entries
   * @throws QueryException query exception
   */
  private TokenList extract(final QueryContext ctx) throws QueryException {
    final B64 archive = (B64) checkType(checkItem(expr[0], ctx), AtomType.B64);
    TokenSet hs = null;
    if (expr.length > 1) {
      // filter result to specified entries
      hs = new TokenSet();
      final Iter names = ctx.iter(expr[1]);
      for (Item en; (en = names.next()) != null; ) {
        hs.add(checkElmStr(en).string(info));
      }
    }

    final TokenList tl = new TokenList();
    final ArchiveIn in = ArchiveIn.get(archive.input(info), info);
    try {
      while (in.more()) {
        final ZipEntry ze = in.entry();
        if (ze.isDirectory()) continue;
        if (hs == null || hs.delete(token(ze.getName())) != 0) tl.add(in.read());
      }
    } catch (final IOException ex) {
      Util.debug(ex);
      ARCH_FAIL.thrw(info, ex);
    } finally {
      in.close();
    }
    return tl;
  }

  /**
   * Adds the specified entry to the output stream.
   *
   * @param entry entry descriptor
   * @param con contents
   * @param out output archive
   * @param level default compression level
   * @throws QueryException query exception
   * @throws IOException I/O exception
   */
  private void add(final Item entry, final Item con, final ArchiveOut out, final int level)
      throws QueryException, IOException {

    // create new zip entry
    final String name = string(entry.string(info));
    if (name.isEmpty()) ARCH_EMPTY.thrw(info);
    final ZipEntry ze = new ZipEntry(name);
    String en = null;

    // compression level
    byte[] lvl = null;
    if (entry instanceof ANode) {
      final ANode el = (ANode) entry;
      lvl = el.attribute(Q_LEVEL);

      // last modified
      final byte[] mod = el.attribute(Q_LAST_MOD);
      if (mod != null) {
        try {
          ze.setTime(new Int(new Dtm(mod, info)).itr());
        } catch (final QueryException qe) {
          ARCH_DATETIME.thrw(info, mod);
        }
      }

      // encoding
      final byte[] enc = el.attribute(Q_ENCODING);
      if (enc != null) {
        en = string(enc);
        if (!Charset.isSupported(en)) ARCH_ENCODING.thrw(info, enc);
      }
    }

    // data to be compressed
    byte[] val = checkStrBin(con);
    if (con instanceof AStr && en != null && en != Token.UTF8) val = encode(val, en);

    try {
      out.level(lvl == null ? level : toInt(lvl));
    } catch (final IllegalArgumentException ex) {
      ARCH_LEVEL.thrw(info, lvl);
    }
    out.write(ze, val);
  }

  /**
   * Encodes the specified string to another encoding.
   *
   * @param val value to be encoded
   * @param en encoding
   * @return encoded string
   * @throws QueryException query exception
   */
  private byte[] encode(final byte[] val, final String en) throws QueryException {
    try {
      return FNConvert.toString(new ArrayInput(val), en);
    } catch (final IOException ex) {
      throw ARCH_ENCODE.thrw(info, ex);
    }
  }

  /**
   * Checks if the specified item is a string or element.
   *
   * @param it item to be checked
   * @return item
   * @throws QueryException query exception
   */
  private Item checkElmStr(final Item it) throws QueryException {
    if (it instanceof AStr || TEST.eq(it)) return it;
    throw ELMSTRTYPE.thrw(info, Q_ENTRY.string(), it.type);
  }
}