public GlobPattern(ByteList bytelist, int flags) { this( bytelist.getUnsafeBytes(), bytelist.getBegin(), bytelist.getBegin() + bytelist.getRealSize(), flags); }
/* * Process {}'s (example: Dir.glob("{jruby,jython}/README*") */ private static int push_braces(String cwd, List<ByteList> result, GlobPattern pattern) { pattern.reset(); int lbrace = pattern.indexOf((byte) '{'); // index of left-most brace int rbrace = pattern.findClosingIndexOf(lbrace); // index of right-most brace // No or mismatched braces..Move along..nothing to see here if (lbrace == -1 || rbrace == -1) return push_globs(cwd, result, pattern); // Peel onion...make subpatterns out of outer layer of glob and recall with each subpattern // Example: foo{a{c},b}bar -> fooa{c}bar, foobbar ByteList buf = new ByteList(20); int middleRegionIndex; int i = lbrace; while (pattern.bytes[i] != '}') { middleRegionIndex = i + 1; for (i = middleRegionIndex; i < pattern.end && pattern.bytes[i] != '}' && pattern.bytes[i] != ','; i++) { if (pattern.bytes[i] == '{') i = pattern.findClosingIndexOf(i); // skip inner braces } buf.length(0); buf.append(pattern.bytes, pattern.begin, lbrace - pattern.begin); buf.append(pattern.bytes, middleRegionIndex, i - middleRegionIndex); buf.append(pattern.bytes, rbrace + 1, pattern.end - (rbrace + 1)); int status = push_braces( cwd, result, new GlobPattern( buf.getUnsafeBytes(), buf.getBegin(), buf.getRealSize(), pattern.flags)); if (status != 0) return status; } return 0; // All braces pushed.. }
private static int glob_helper( String cwd, byte[] bytes, int begin, int end, int sub, int flags, GlobFunc func, GlobArgs arg) { int p, m; int status = 0; byte[] newpath = null; File st; p = sub != -1 ? sub : begin; if (!has_magic(bytes, p, end, flags)) { if (DOSISH || (flags & FNM_NOESCAPE) == 0) { newpath = new byte[end]; System.arraycopy(bytes, 0, newpath, 0, end); if (sub != -1) { p = (sub - begin); end = remove_backslashes(newpath, p, end); sub = p; } else { end = remove_backslashes(newpath, 0, end); bytes = newpath; } } if (bytes[begin] == '/' || (DOSISH && begin + 2 < end && bytes[begin + 1] == ':' && isdirsep(bytes[begin + 2]))) { if (new JavaSecuredFile(newStringFromUTF8(bytes, begin, end - begin)).exists()) { status = func.call(bytes, begin, end - begin, arg); } } else if (isJarFilePath(bytes, begin, end)) { int ix = end; for (int i = 0; i < end; i++) { if (bytes[begin + i] == '!') { ix = i; break; } } st = new JavaSecuredFile(newStringFromUTF8(bytes, begin + 5, ix - 5)); try { String jar = newStringFromUTF8(bytes, begin + ix + 1, end - (ix + 1)); JarFile jf = new JarFile(st); if (jar.startsWith("/")) jar = jar.substring(1); ZipEntry entry = RubyFile.getDirOrFileEntry(jf, jar); if (entry != null) { status = func.call(bytes, begin, end, arg); } } catch (Exception e) { } } else if ((end - begin) > 0) { // Length check is a hack. We should not be reeiving "" as a filename ever. if (new JavaSecuredFile(cwd, newStringFromUTF8(bytes, begin, end - begin)).exists()) { status = func.call(bytes, begin, end - begin, arg); } } return status; } ByteList buf = new ByteList(20); List<ByteList> link = new ArrayList<ByteList>(); mainLoop: while (p != -1 && status == 0) { if (bytes[p] == '/') p++; m = strchr(bytes, p, end, (byte) '/'); if (has_magic(bytes, p, m == -1 ? end : m, flags)) { finalize: do { byte[] base = extract_path(bytes, begin, p); byte[] dir = begin == p ? new byte[] {'.'} : base; byte[] magic = extract_elem(bytes, p, end); boolean recursive = false; String jar = null; JarFile jf = null; if (dir[0] == '/' || (DOSISH && 2 < dir.length && dir[1] == ':' && isdirsep(dir[2]))) { st = new JavaSecuredFile(newStringFromUTF8(dir)); } else if (isJarFilePath(dir, 0, dir.length)) { int ix = dir.length; for (int i = 0; i < dir.length; i++) { if (dir[i] == '!') { ix = i; break; } } st = new JavaSecuredFile(newStringFromUTF8(dir, 5, ix - 5)); jar = newStringFromUTF8(dir, ix + 1, dir.length - (ix + 1)); try { jf = new JarFile(st); if (jar.startsWith("/")) jar = jar.substring(1); if (jf.getEntry(jar + "/") != null) jar = jar + "/"; } catch (Exception e) { jar = null; jf = null; } } else { st = new JavaSecuredFile(cwd, newStringFromUTF8(dir)); } if ((jf != null && ("".equals(jar) || (jf.getJarEntry(jar) != null && jf.getJarEntry(jar).isDirectory()))) || st.isDirectory()) { if (m != -1 && Arrays.equals(magic, DOUBLE_STAR)) { int n = base.length; recursive = true; buf.length(0); buf.append(base); buf.append(bytes, (base.length > 0 ? m : m + 1), end - (base.length > 0 ? m : m + 1)); status = glob_helper( cwd, buf.getUnsafeBytes(), buf.getBegin(), buf.getRealSize(), n, flags, func, arg); if (status != 0) { break finalize; } } } else { break mainLoop; } if (jar == null) { String[] dirp = files(st); for (int i = 0; i < dirp.length; i++) { if (recursive) { byte[] bs = getBytesInUTF8(dirp[i]); if (fnmatch(STAR, 0, 1, bs, 0, bs.length, flags) != 0) { continue; } buf.length(0); buf.append(base); buf.append(BASE(base) ? SLASH : EMPTY); buf.append(getBytesInUTF8(dirp[i])); if (buf.getUnsafeBytes()[0] == '/' || (DOSISH && 2 < buf.getRealSize() && buf.getUnsafeBytes()[1] == ':' && isdirsep(buf.getUnsafeBytes()[2]))) { st = new JavaSecuredFile( newStringFromUTF8( buf.getUnsafeBytes(), buf.getBegin(), buf.getRealSize())); } else { st = new JavaSecuredFile( cwd, newStringFromUTF8( buf.getUnsafeBytes(), buf.getBegin(), buf.getRealSize())); } if (st.isDirectory() && !".".equals(dirp[i]) && !"..".equals(dirp[i])) { int t = buf.getRealSize(); buf.append(SLASH); buf.append(DOUBLE_STAR); buf.append(bytes, m, end - m); status = glob_helper( cwd, buf.getUnsafeBytes(), buf.getBegin(), buf.getRealSize(), t, flags, func, arg); if (status != 0) { break; } } continue; } byte[] bs = getBytesInUTF8(dirp[i]); if (fnmatch(magic, 0, magic.length, bs, 0, bs.length, flags) == 0) { buf.length(0); buf.append(base); buf.append(BASE(base) ? SLASH : EMPTY); buf.append(getBytesInUTF8(dirp[i])); if (m == -1) { status = func.call(buf.getUnsafeBytes(), 0, buf.getRealSize(), arg); if (status != 0) { break; } continue; } link.add(buf); buf = new ByteList(20); } } } else { try { List<JarEntry> dirp = new ArrayList<JarEntry>(); for (Enumeration<JarEntry> eje = jf.entries(); eje.hasMoreElements(); ) { JarEntry je = eje.nextElement(); String name = je.getName(); int ix = name.indexOf('/', jar.length()); if (ix == -1 || ix == name.length() - 1) { if ("/".equals(jar) || (name.startsWith(jar) && name.length() > jar.length())) { dirp.add(je); } } } for (JarEntry je : dirp) { byte[] bs = getBytesInUTF8(je.getName()); int len = bs.length; if (je.isDirectory()) { len--; } if (recursive) { if (fnmatch(STAR, 0, 1, bs, 0, len, flags) != 0) { continue; } buf.length(0); buf.append(base, 0, base.length - jar.length()); buf.append(BASE(base) ? SLASH : EMPTY); buf.append(bs, 0, len); if (je.isDirectory()) { int t = buf.getRealSize(); buf.append(SLASH); buf.append(DOUBLE_STAR); buf.append(bytes, m, end - m); status = glob_helper( cwd, buf.getUnsafeBytes(), buf.getBegin(), buf.getRealSize(), t, flags, func, arg); if (status != 0) { break; } } continue; } if (fnmatch(magic, 0, magic.length, bs, 0, len, flags) == 0) { buf.length(0); buf.append(base, 0, base.length - jar.length()); buf.append(BASE(base) ? SLASH : EMPTY); buf.append(bs, 0, len); if (m == -1) { status = func.call(buf.getUnsafeBytes(), 0, buf.getRealSize(), arg); if (status != 0) { break; } continue; } link.add(buf); buf = new ByteList(20); } } } catch (Exception e) { } } } while (false); if (link.size() > 0) { for (ByteList b : link) { if (status == 0) { if (b.getUnsafeBytes()[0] == '/' || (DOSISH && 2 < b.getRealSize() && b.getUnsafeBytes()[1] == ':' && isdirsep(b.getUnsafeBytes()[2]))) { st = new JavaSecuredFile(newStringFromUTF8(b.getUnsafeBytes(), 0, b.getRealSize())); } else { st = new JavaSecuredFile( cwd, newStringFromUTF8(b.getUnsafeBytes(), 0, b.getRealSize())); } if (st.isDirectory()) { int len = b.getRealSize(); buf.length(0); buf.append(b); buf.append(bytes, m, end - m); status = glob_helper( cwd, buf.getUnsafeBytes(), 0, buf.getRealSize(), len, flags, func, arg); } } } break mainLoop; } } p = m; } return status; }