0001: /*
0002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
0003: *
0004: * This file is part of Resin(R) Open Source
0005: *
0006: * Each copy or derived work must preserve the copyright notice and this
0007: * notice unmodified.
0008: *
0009: * Resin Open Source is free software; you can redistribute it and/or modify
0010: * it under the terms of the GNU General Public License as published by
0011: * the Free Software Foundation; either version 2 of the License, or
0012: * (at your option) any later version.
0013: *
0014: * Resin Open Source is distributed in the hope that it will be useful,
0015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
0017: * of NON-INFRINGEMENT. See the GNU General Public License for more
0018: * details.
0019: *
0020: * You should have received a copy of the GNU General Public License
0021: * along with Resin Open Source; if not, write to the
0022: *
0023: * Free Software Foundation, Inc.
0024: * 59 Temple Place, Suite 330
0025: * Boston, MA 02111-1307 USA
0026: *
0027: * @author Scott Ferguson
0028: */
0029:
0030: package com.caucho.quercus.lib.file;
0031:
0032: import com.caucho.quercus.QuercusModuleException;
0033: import com.caucho.quercus.annotation.NotNull;
0034: import com.caucho.quercus.annotation.Optional;
0035: import com.caucho.quercus.annotation.ReturnNullAsFalse;
0036: import com.caucho.quercus.env.*;
0037: import com.caucho.quercus.lib.UrlModule;
0038: import com.caucho.quercus.lib.string.StringModule;
0039: import com.caucho.quercus.module.AbstractQuercusModule;
0040: import com.caucho.quercus.module.IniDefinitions;
0041: import com.caucho.quercus.module.IniDefinition;
0042: import com.caucho.util.Alarm;
0043: import com.caucho.util.L10N;
0044: import com.caucho.vfs.Path;
0045: import com.caucho.vfs.ReadStream;
0046: import com.caucho.vfs.TempBuffer;
0047: import com.caucho.vfs.WriteStream;
0048: import com.caucho.vfs.LockableStream;
0049:
0050: import java.io.IOException;
0051: import java.io.InputStream;
0052: import java.util.Arrays;
0053: import java.util.HashMap;
0054: import java.util.Map;
0055: import java.util.logging.Level;
0056: import java.util.logging.Logger;
0057: import java.util.regex.Matcher;
0058: import java.util.regex.Pattern;
0059: import java.util.regex.PatternSyntaxException;
0060:
0061: /**
0062: * Information and actions for about files
0063: */
0064: public class FileModule extends AbstractQuercusModule {
0065: private static final L10N L = new L10N(FileModule.class);
0066: private static final Logger log = Logger.getLogger(FileModule.class
0067: .getName());
0068:
0069: public static final String DIRECTORY_SEPARATOR = ""
0070: + Path.getFileSeparatorChar();
0071: public static final String PATH_SEPARATOR = ""
0072: + Path.getPathSeparatorChar();
0073:
0074: public static final int UPLOAD_ERR_OK = 0;
0075: public static final int UPLOAD_ERR_INI_SIZE = 1;
0076: public static final int UPLOAD_ERR_FORM_SIZE = 2;
0077: public static final int UPLOAD_ERR_PARTIAL = 3;
0078: public static final int UPLOAD_ERR_NO_FILE = 4;
0079: public static final int UPLOAD_ERR_NO_TMP_DIR = 6;
0080: public static final int UPLOAD_ERR_CANT_WRITE = 7;
0081: public static final int UPLOAD_ERR_EXTENSION = 8;
0082:
0083: public static final int FILE_USE_INCLUDE_PATH = 1;
0084: public static final int FILE_APPEND = 8;
0085:
0086: public static final int LOCK_SH = 1;
0087: public static final int LOCK_EX = 2;
0088: public static final int LOCK_UN = 3;
0089: public static final int LOCK_NB = 4;
0090:
0091: public static final int FNM_PATHNAME = 1;
0092: public static final int FNM_NOESCAPE = 2;
0093: public static final int FNM_PERIOD = 4;
0094: public static final int FNM_CASEFOLD = 16;
0095:
0096: public static final int GLOB_MARK = 1;
0097: public static final int GLOB_NOSORT = 2;
0098: public static final int GLOB_NOCHECK = 4;
0099: public static final int GLOB_NOESCAPE = 8;
0100: public static final int GLOB_BRACE = 16;
0101: public static final int GLOB_ONLYDIR = 32;
0102: public static final int GLOB_ERR = 64;
0103:
0104: public static final int PATHINFO_DIRNAME = 1;
0105: public static final int PATHINFO_BASENAME = 2;
0106: public static final int PATHINFO_EXTENSION = 4;
0107: public static final int PATHINFO_FILENAME = 8;
0108:
0109: private static final IniDefinitions _iniDefinitions = new IniDefinitions();
0110:
0111: private static final HashMap<String, Value> _constMap = new HashMap<String, Value>();
0112:
0113: /**
0114: * Returns the default quercus.ini values.
0115: */
0116: public IniDefinitions getIniDefinitions() {
0117: return _iniDefinitions;
0118: }
0119:
0120: /**
0121: * Returns the constants defined by this module.
0122: */
0123: public Map<String, Value> getConstMap() {
0124: return _constMap;
0125: }
0126:
0127: /**
0128: * Returns the base name of a string.
0129: */
0130: public static Value basename(StringValue path, @Optional
0131: StringValue suffix) {
0132: int len = path.length();
0133:
0134: if (len == 0)
0135: return path;
0136:
0137: else if (path.charAt(len - 1) == '/')
0138: len -= 1;
0139: else if (path.charAt(len - 1) == '\\')
0140: len -= 1;
0141:
0142: int p = path.lastIndexOf('/', len - 1);
0143:
0144: if (p < 0)
0145: p = path.lastIndexOf('\\', len - 1);
0146:
0147: StringValue file;
0148:
0149: if (p < 0)
0150: file = path.substring(0, len);
0151: else
0152: file = path.substring(p + 1, len);
0153:
0154: if (suffix != null && file.endsWith(suffix))
0155: file = file.substring(0, file.length() - suffix.length());
0156:
0157: return file;
0158: }
0159:
0160: /**
0161: * Changes the working directory
0162: *
0163: * @param path the path to change to
0164: */
0165: public static boolean chdir(Env env, Path path) {
0166: if (path.isDirectory()) {
0167: env.setPwd(path);
0168: return true;
0169: } else {
0170: env.warning(L.l("{0} is not a directory", path
0171: .getFullPath()));
0172:
0173: return false;
0174: }
0175: }
0176:
0177: /**
0178: * Changes the working directory, forming a virtual root
0179: *
0180: * @param path the path to change to
0181: */
0182: public static boolean chroot(Env env, Path path) {
0183: if (path.isDirectory()) {
0184:
0185: env.setPwd(path.createRoot());
0186:
0187: return true;
0188: } else {
0189: env.warning(L.l("{0} is not a directory", path
0190: .getFullPath()));
0191:
0192: return false;
0193: }
0194: }
0195:
0196: /**
0197: * Changes the group of the file.
0198: *
0199: * @param env the PHP executing environment
0200: * @param file the file to change the group of
0201: * @param group the group id to change to
0202: */
0203: public static boolean chgrp(Env env, Path file, Value group) {
0204: if (!file.canRead()) {
0205: env.warning(L.l("{0} cannot be read", file.getFullPath()));
0206:
0207: return false;
0208: }
0209:
0210: // quercus/160i
0211:
0212: try {
0213: // XXX: safe_mode
0214:
0215: if (group instanceof LongValue)
0216: file.changeGroup(group.toInt());
0217: else
0218: file.changeGroup(group.toString());
0219:
0220: return true;
0221: } catch (IOException e) {
0222: log.log(Level.FINE, e.toString(), e);
0223:
0224: return false;
0225: }
0226: }
0227:
0228: /**
0229: * Changes the permissions of the file.
0230: *
0231: * @param env the PHP executing environment
0232: * @param file the file to change the group of
0233: * @param mode the mode id to change to
0234: */
0235: public static boolean chmod(Env env, Path file, int mode) {
0236: if (!file.canRead()) {
0237: // XXX: gallery?
0238: env.warning(L.l("{0} cannot be read", file.getFullPath()));
0239:
0240: return false;
0241: }
0242:
0243: // quercus/160j
0244: file.chmod(mode);
0245:
0246: return true;
0247: }
0248:
0249: /**
0250: * Changes the ownership of the file.
0251: *
0252: * @param env the PHP executing environment
0253: * @param file the file to change the group of
0254: * @param user the user id to change to
0255: */
0256: public static boolean chown(Env env, Path file, Value user) {
0257: if (!file.canRead()) {
0258: env.warning(L.l("{0} cannot be read", file.getFullPath()));
0259:
0260: return false;
0261: }
0262:
0263: try {
0264: // XXX: safe_mode
0265:
0266: if (user instanceof LongValue)
0267: file.changeOwner(user.toInt());
0268: else
0269: file.changeOwner(user.toString());
0270:
0271: return true;
0272: } catch (IOException e) {
0273: log.log(Level.FINE, e.toString(), e);
0274:
0275: return false;
0276: }
0277: }
0278:
0279: /**
0280: * Clears the stat cache for the file
0281: *
0282: * @param env the PHP executing environment
0283: */
0284: public static Value clearstatcache(Env env) {
0285: // quercus/160l
0286:
0287: // XXX: stubbed
0288:
0289: return NullValue.NULL;
0290: }
0291:
0292: /**
0293: * Copies a file to the destination.
0294: *
0295: * @param src the source path
0296: * @param dst the destination path
0297: */
0298: public static boolean copy(Env env, Path src, Path dst) {
0299: // quercus/1603
0300:
0301: try {
0302: if (!src.canRead() || !src.isFile()) {
0303: env.warning(L
0304: .l("{0} cannot be read", src.getFullPath()));
0305:
0306: return false;
0307: }
0308:
0309: WriteStream os = dst.openWrite();
0310:
0311: try {
0312: src.writeToStream(os);
0313: } finally {
0314: os.close();
0315: }
0316:
0317: return true;
0318: } catch (IOException e) {
0319: log.log(Level.FINE, e.toString(), e);
0320:
0321: return false;
0322: }
0323: }
0324:
0325: /**
0326: * Opens a directory
0327: *
0328: * @param path the path to change to
0329: */
0330: @ReturnNullAsFalse
0331: public static Directory dir(Env env, Path path) {
0332: try {
0333: if (!path.isDirectory()) {
0334: env.warning(L.l("{0} is not a directory", path
0335: .getFullPath()));
0336:
0337: return null;
0338: }
0339:
0340: return new Directory(env, path);
0341:
0342: /*
0343: DirectoryValue dir = new DirectoryValue(path);
0344:
0345: env.addClose(dir);
0346:
0347: return dir;
0348: */
0349: } catch (IOException e) {
0350: throw new QuercusModuleException(e);
0351: }
0352: }
0353:
0354: /**
0355: * Returns the directory name of a string.
0356: */
0357: public StringValue dirname(Env env, StringValue path) {
0358: int len = path.length();
0359:
0360: if (len == 0)
0361: return env.createString(".");
0362: else if (len == 1 && path.charAt(0) == '/')
0363: return path;
0364:
0365: int p = path.lastIndexOf('/', len - 2);
0366:
0367: // php/1601 (for Windows)
0368: p = Math.max(p, path.lastIndexOf('\\', len - 2));
0369:
0370: if (p == 0)
0371: return env.createString("/");
0372: else if (p > 0)
0373: return path.substring(0, p);
0374:
0375: p = path.lastIndexOf('\\', len - 2);
0376:
0377: if (p == 0)
0378: return env.createString("\\");
0379: else if (p > 0)
0380: return path.substring(0, p);
0381:
0382: return env.createString(".");
0383: }
0384:
0385: /**
0386: * Returns the free space for disk partition containing the directory
0387: *
0388: * @param directory the disk directory
0389: */
0390: public static Value disk_free_space(Env env, Path directory) {
0391: // quercus/160m
0392:
0393: if (!directory.canRead()) {
0394: env.warning(L.l("{0} cannot be read", directory
0395: .getFullPath()));
0396:
0397: return BooleanValue.FALSE;
0398: }
0399:
0400: return new DoubleValue(directory.getDiskSpaceFree());
0401: }
0402:
0403: /**
0404: * Returns the total space for disk partition containing the directory
0405: *
0406: * @param directory the disk directory
0407: */
0408: public static Value disk_total_space(Env env, Path directory) {
0409: // quercus/160n
0410:
0411: if (!directory.canRead()) {
0412: env.warning(L.l("{0} cannot be read", directory
0413: .getFullPath()));
0414:
0415: return BooleanValue.FALSE;
0416: }
0417:
0418: return new DoubleValue(directory.getDiskSpaceTotal());
0419: }
0420:
0421: /**
0422: * Returns the total space for disk partition containing the directory
0423: *
0424: * @param directory the disk directory
0425: */
0426: public static Value diskfreespace(Env env, Path directory) {
0427: return disk_free_space(env, directory);
0428: }
0429:
0430: /**
0431: * Closes a file.
0432: */
0433: public static boolean fclose(Env env, @NotNull
0434: BinaryStream s) {
0435: if (s == null)
0436: return false;
0437:
0438: s.close();
0439:
0440: return true;
0441: }
0442:
0443: /**
0444: * Checks for the end of file.
0445: */
0446: public static boolean feof(Env env, @NotNull
0447: BinaryInput is) {
0448: if (is == null)
0449: return false;
0450:
0451: return is.isEOF();
0452: }
0453:
0454: /**
0455: * Flushes a file.
0456: */
0457: public static boolean fflush(Env env, @NotNull
0458: BinaryOutput os) {
0459: if (os == null)
0460: return false;
0461:
0462: try {
0463: os.flush();
0464:
0465: return true;
0466: } catch (IOException e) {
0467: return false;
0468: }
0469: }
0470:
0471: /**
0472: * Returns the next character as a byte
0473: */
0474: public static Value fgetc(Env env, @NotNull
0475: BinaryInput is) {
0476: try {
0477: if (is == null)
0478: return BooleanValue.FALSE;
0479:
0480: // XXX: char for i18n and mode = "t"
0481:
0482: // php/1612
0483: int ch = is.read();
0484:
0485: if (ch >= 0) {
0486: StringValue v = env.createBinaryBuilder(1);
0487:
0488: v.append((char) ch);
0489:
0490: return v;
0491: } else
0492: return BooleanValue.FALSE;
0493: } catch (IOException e) {
0494: throw new QuercusModuleException(e);
0495: }
0496: }
0497:
0498: /**
0499: * Parses a comma-separated-value line from a file.
0500: *
0501: * @param file the file to read
0502: * @param length the maximum line length
0503: * @param delimiter optional comma replacement
0504: * @param enclosure optional quote replacement
0505: */
0506: public Value fgetcsv(Env env, @NotNull
0507: BinaryInput is, @Optional
0508: int length, @Optional
0509: String delimiter, @Optional
0510: String enclosure) {
0511: // php/1619
0512:
0513: try {
0514: if (is == null)
0515: return BooleanValue.FALSE;
0516:
0517: // XXX: length is never used
0518: if (length <= 0)
0519: length = Integer.MAX_VALUE;
0520:
0521: int comma = ',';
0522:
0523: if (delimiter != null && delimiter.length() > 0)
0524: comma = delimiter.charAt(0);
0525:
0526: int quote = '"';
0527:
0528: if (enclosure != null && enclosure.length() > 0)
0529: quote = enclosure.charAt(0);
0530:
0531: ArrayValue array = new ArrayValueImpl();
0532:
0533: int ch;
0534:
0535: while (true) {
0536: // scan whitespace
0537: while (true) {
0538: ch = is.read();
0539:
0540: if (ch < 0 || ch == '\n')
0541: return array;
0542: else if (ch == '\r') {
0543: is.readOptionalLinefeed();
0544: return array;
0545: } else if (ch == ' ' || ch == '\t')
0546: continue;
0547: else
0548: break;
0549: }
0550:
0551: StringValue sb = env.createBinaryBuilder();
0552:
0553: if (ch == quote) {
0554: for (ch = is.read(); ch >= 0; ch = is.read()) {
0555: if (ch == quote) {
0556: ch = is.read();
0557:
0558: if (ch == quote)
0559: sb.append((char) ch);
0560: else
0561: break;
0562: } else
0563: sb.append((char) ch);
0564: }
0565:
0566: array.append(sb);
0567:
0568: for (; ch >= 0 && ch == ' ' || ch == '\t'; ch = is
0569: .read()) {
0570: }
0571: } else {
0572: for (; ch >= 0 && ch != comma && ch != '\r'
0573: && ch != '\n'; ch = is.read()) {
0574: sb.append((char) ch);
0575: }
0576:
0577: array.append(sb);
0578: }
0579:
0580: if (ch < 0)
0581: return array;
0582: else if (ch == '\n')
0583: return array;
0584: else if (ch == '\r') {
0585: is.readOptionalLinefeed();
0586: return array;
0587: } else if (ch == comma) {
0588: } else {
0589: env.warning("expected comma");
0590: }
0591: }
0592: } catch (IOException e) {
0593: throw new QuercusModuleException(e);
0594: }
0595: }
0596:
0597: /**
0598: * Returns the next line
0599: */
0600: public static Value fgets(Env env, @NotNull
0601: BinaryInput is, @Optional("0x7fffffff")
0602: int length) {
0603: // php/1615
0604:
0605: try {
0606: if (is == null)
0607: return BooleanValue.FALSE;
0608:
0609: StringValue value = is.readLine(length);
0610:
0611: if (value != null)
0612: return value;
0613: else
0614: return BooleanValue.FALSE;
0615: } catch (IOException e) {
0616: throw new QuercusModuleException(e);
0617: }
0618: }
0619:
0620: /**
0621: * Returns the next line stripping tags
0622: */
0623: public static Value fgetss(Env env, BinaryInput is,
0624: @Optional("0x7fffffff")
0625: int length, @Optional
0626: String allowedTags) {
0627: // php/161a
0628:
0629: try {
0630: if (is == null) {
0631: env.warning(L.l("{0} is null", "handle"));
0632: return BooleanValue.FALSE;
0633: }
0634:
0635: StringValue value = is.readLine(length);
0636:
0637: if (value != null)
0638: return StringModule.strip_tags(value, allowedTags);
0639: else
0640: return BooleanValue.FALSE;
0641: } catch (IOException e) {
0642: throw new QuercusModuleException(e);
0643: }
0644: }
0645:
0646: /**
0647: * Parses the file, returning it in an array. Binary-safe.
0648: *
0649: * @param filename the file's name
0650: * @param useIncludePath if 1, use the include path
0651: * @param context the resource context
0652: */
0653: public static Value file(Env env, StringValue filename, @Optional
0654: boolean useIncludePath, @Optional
0655: Value context) {
0656: if (filename.length() == 0)
0657: return BooleanValue.FALSE;
0658:
0659: try {
0660: BinaryStream stream = fopen(env, filename, "r",
0661: useIncludePath, context);
0662:
0663: if (stream == null)
0664: return BooleanValue.FALSE;
0665:
0666: BinaryInput is = (BinaryInput) stream;
0667:
0668: ArrayValue result = new ArrayValueImpl();
0669:
0670: try {
0671: while (true) {
0672: StringValue bb = env.createBinaryBuilder();
0673:
0674: for (int ch = is.read(); ch >= 0; ch = is.read()) {
0675: if (ch == '\n') {
0676: bb.appendByte(ch);
0677: break;
0678: } else if (ch == '\r') {
0679: bb.appendByte('\r');
0680:
0681: int ch2 = is.read();
0682:
0683: if (ch2 == '\n')
0684: bb.appendByte('\n');
0685: else
0686: is.unread();
0687:
0688: break;
0689: } else
0690: bb.appendByte(ch);
0691: }
0692:
0693: if (bb.length() > 0)
0694: result.append(bb);
0695: else
0696: return result;
0697: }
0698: } finally {
0699: is.close();
0700: }
0701: } catch (IOException e) {
0702: throw new QuercusModuleException(e);
0703: }
0704: }
0705:
0706: /**
0707: * Returns the file access time
0708: *
0709: * @param path the path to check
0710: */
0711: public static Value fileatime(Env env, Path path) {
0712: if (!path.canRead()) {
0713: env.warning(L.l("{0} cannot be read", path.getFullPath()));
0714: return BooleanValue.FALSE;
0715: }
0716:
0717: long time = path.getLastAccessTime();
0718:
0719: if (time <= 24 * 3600 * 1000L)
0720: return BooleanValue.FALSE;
0721: else
0722: return new LongValue(time / 1000L);
0723: }
0724:
0725: /**
0726: * Returns the file create time
0727: *
0728: * @param path the path to check
0729: */
0730: public static Value filectime(Env env, Path path) {
0731: if (!path.canRead()) {
0732: env.warning(L.l("{0} cannot be read", path.getFullPath()));
0733: return BooleanValue.FALSE;
0734: }
0735:
0736: long time = path.getCreateTime();
0737:
0738: if (time <= 24 * 3600 * 1000L)
0739: return BooleanValue.FALSE;
0740: else
0741: return new LongValue(time / 1000L);
0742: }
0743:
0744: /**
0745: * Returns the file's group
0746: *
0747: * @param path the path to check
0748: */
0749: public static Value filegroup(Env env, Path path) {
0750: if (!path.canRead()) {
0751: env.warning(L.l("{0} cannot be read", path.getFullPath()));
0752: return BooleanValue.FALSE;
0753: }
0754:
0755: return new LongValue(path.getGroup());
0756: }
0757:
0758: /**
0759: * Returns the file's inocde
0760: *
0761: * @param path the path to check
0762: */
0763: public static Value fileinode(Env env, Path path) {
0764: if (!path.canRead()) {
0765: env.warning(L.l("{0} cannot be read", path.getFullPath()));
0766: return BooleanValue.FALSE;
0767: }
0768:
0769: return new LongValue(path.getInode());
0770: }
0771:
0772: /**
0773: * Returns the file modified time
0774: *
0775: * @param path the path to check
0776: */
0777: public static Value filemtime(Env env, Path path) {
0778: long time = path.getLastModified();
0779:
0780: if (24 * 3600 * 1000L < time)
0781: return new LongValue(time / 1000L);
0782: else {
0783: if (!path.canRead()) {
0784: env.warning(L.l("{0} cannot be read", path
0785: .getFullPath()));
0786: return BooleanValue.FALSE;
0787: }
0788:
0789: return BooleanValue.FALSE;
0790: }
0791: }
0792:
0793: /**
0794: * Returns the file's owner
0795: *
0796: * @param path the path to check
0797: */
0798: public static Value fileowner(Env env, Path path) {
0799: if (!path.canRead()) {
0800: env.warning(L.l("{0} cannot be read", path.getFullPath()));
0801: return BooleanValue.FALSE;
0802: }
0803:
0804: return new LongValue(path.getOwner());
0805: }
0806:
0807: /**
0808: * Returns the file's permissions
0809: *
0810: * @param path the path to check
0811: */
0812: public static Value fileperms(Env env, Path path) {
0813: if (!path.canRead()) {
0814: env.warning(L.l("{0} cannot be read", path.getFullPath()));
0815: return BooleanValue.FALSE;
0816: }
0817:
0818: return new LongValue(path.getMode());
0819: }
0820:
0821: /**
0822: * Returns the file's size
0823: *
0824: * @param path the path to check
0825: */
0826: public static Value filesize(Env env, Path path) {
0827: if (!path.exists() || !path.isFile()) {
0828: env.warning(L.l("{0} cannot be read", path.getFullPath()));
0829: return BooleanValue.FALSE;
0830: }
0831:
0832: long length = path.getLength();
0833:
0834: if (length < 0)
0835: return BooleanValue.FALSE;
0836: else
0837: return new LongValue(length);
0838: }
0839:
0840: /**
0841: * Returns the file's type
0842: *
0843: * @param path the path to check
0844: */
0845: public static Value filetype(Env env, @NotNull
0846: Path path) {
0847: if (path == null)
0848: return BooleanValue.FALSE;
0849: else if (!path.exists()) {
0850: env.warning(L.l("{0} cannot be read", path.getFullPath()));
0851: return BooleanValue.FALSE;
0852: } else if (path.isDirectory())
0853: return env.createString("dir");
0854: else if (path.isFile())
0855: return env.createString("file");
0856: else if (path.isFIFO())
0857: return env.createString("fifo");
0858: else if (path.isLink())
0859: return env.createString("link");
0860: else if (path.isBlockDevice())
0861: return env.createString("block");
0862: else if (path.isCharacterDevice())
0863: return env.createString("char");
0864: else
0865: return env.createString("unknown");
0866: }
0867:
0868: /**
0869: * Returns true if file exists
0870: *
0871: * @param path the path to check
0872: */
0873: public static boolean file_exists(@NotNull
0874: Path path) {
0875: if (path != null)
0876: return path.exists();
0877: else
0878: return false;
0879: }
0880:
0881: /**
0882: * Parses the file, returning it as a string array.
0883: *
0884: * @param filename the file's name
0885: * @param useIncludePath if true, use the include path
0886: * @param context the resource context
0887: */
0888: @ReturnNullAsFalse
0889: public static StringValue file_get_contents(Env env,
0890: StringValue filename, @Optional
0891: boolean useIncludePath, @Optional
0892: Value context, @Optional
0893: long offset, @Optional("4294967296")
0894: long maxLen) {
0895: if (filename.length() == 0) {
0896: env.warning(L.l("file name must not be null"));
0897: return null;
0898: }
0899:
0900: BinaryStream s = fopen(env, filename, "r", useIncludePath,
0901: context);
0902:
0903: if (!(s instanceof BinaryInput))
0904: return null;
0905:
0906: BinaryInput is = (BinaryInput) s;
0907:
0908: StringValue bb = env.createLargeBinaryBuilder();
0909: bb.appendReadAll(is, maxLen);
0910:
0911: s.close();
0912: return bb;
0913: }
0914:
0915: /**
0916: * Writes data to a file.
0917: */
0918: public Value file_put_contents(Env env, StringValue filename,
0919: Value data, @Optional
0920: int flags, @Optional
0921: Value context) {
0922: if (filename.length() == 0) {
0923: env.warning(L.l("file name must not be null"));
0924: return BooleanValue.FALSE;
0925: }
0926:
0927: // php/1634
0928:
0929: BinaryStream s = null;
0930:
0931: try {
0932: boolean useIncludePath = (flags & FILE_USE_INCLUDE_PATH) != 0;
0933: String mode = (flags & FILE_APPEND) != 0 ? "a" : "w";
0934:
0935: s = fopen(env, filename, mode, useIncludePath, context);
0936:
0937: if (!(s instanceof BinaryOutput))
0938: return BooleanValue.FALSE;
0939:
0940: if ((flags & LOCK_EX) != 0) {
0941: if (s instanceof LockableStream) {
0942: if (!flock(env, (LockableStream) s, LOCK_EX, null))
0943: return BooleanValue.FALSE;
0944: } else {
0945: return BooleanValue.FALSE;
0946: }
0947: }
0948:
0949: BinaryOutput os = (BinaryOutput) s;
0950:
0951: try {
0952: long dataWritten = 0;
0953:
0954: if (data instanceof ArrayValue) {
0955: for (Value item : ((ArrayValue) data).values()) {
0956: InputStream is = item.toInputStream();
0957:
0958: dataWritten += os.write(is, Integer.MAX_VALUE);
0959:
0960: is.close();
0961: }
0962: } else {
0963: InputStream is = data.toInputStream();
0964:
0965: dataWritten += os.write(is, Integer.MAX_VALUE);
0966:
0967: is.close();
0968: }
0969:
0970: return new LongValue(dataWritten);
0971: } finally {
0972: os.close();
0973: }
0974: } catch (IOException e) {
0975: throw new QuercusModuleException(e);
0976: } finally {
0977: if (s != null && (s instanceof LockableStream)
0978: && ((flags & LOCK_EX) != 0))
0979: flock(env, (LockableStream) s, LOCK_UN, null);
0980: }
0981: }
0982:
0983: /**
0984: * Advisory locking
0985: *
0986: * @param fileV the file handle
0987: * @param operation the locking operation
0988: * @param wouldBlock the resource context
0989: */
0990: public static boolean flock(Env env, LockableStream fileV,
0991: int operation, @Optional
0992: Value wouldBlock) {
0993: // XXX: also wouldblock is a ref
0994:
0995: if (fileV == null) {
0996: env.warning(L.l("flock: file is null"));
0997: return false;
0998: }
0999:
1000: boolean shared = false;
1001: boolean block = true;
1002:
1003: if (operation > LOCK_NB) {
1004: block = false;
1005: operation -= LOCK_NB;
1006: }
1007:
1008: switch (operation) {
1009: case LOCK_SH:
1010: shared = true;
1011: break;
1012: case LOCK_EX:
1013: shared = false;
1014: break;
1015: case LOCK_UN:
1016: // flock($fd, LOCK_UN) returns true even
1017: // if no lock is held.
1018:
1019: fileV.unlock();
1020: return true;
1021: default:
1022: // This is PHP's behavior...
1023: return true;
1024: }
1025:
1026: return fileV.lock(shared, block);
1027: }
1028:
1029: /**
1030: * Converts a glob pattern to a regular expression.
1031: */
1032: private static String globToRegex(String pattern, int flags,
1033: boolean brace) {
1034: StringBuilder globRegex = new StringBuilder();
1035:
1036: int bracketCount = 0;
1037: boolean inSquareBrackets = false;
1038: boolean inCurlyBrackets = false;
1039: char lastCh = ' ';
1040:
1041: for (int i = 0; i < pattern.length(); i++) {
1042: char ch = pattern.charAt(i);
1043:
1044: switch (ch) {
1045: case '*':
1046: if (inSquareBrackets || inCurlyBrackets) {
1047: globRegex.append("*");
1048:
1049: if (inSquareBrackets)
1050: bracketCount++;
1051: } else {
1052: if ((flags & FNM_PATHNAME) != 0)
1053: globRegex.append("[^/]*");
1054: else
1055: globRegex.append(".*");
1056: }
1057:
1058: break;
1059:
1060: case '?':
1061: if (inSquareBrackets || inCurlyBrackets) {
1062: globRegex.append("*");
1063:
1064: if (inSquareBrackets)
1065: bracketCount++;
1066: } else {
1067: if ((flags & FNM_PATHNAME) != 0)
1068: globRegex.append("[^/]");
1069: else
1070: globRegex.append(".");
1071: }
1072:
1073: break;
1074:
1075: case '^':
1076: if (lastCh == '[')
1077: globRegex.append(ch);
1078: else {
1079: globRegex.append("\\" + ch);
1080:
1081: if (inSquareBrackets)
1082: bracketCount++;
1083: }
1084:
1085: break;
1086:
1087: case '!':
1088: if (lastCh == '[')
1089: globRegex.append('^');
1090: else {
1091: globRegex.append(ch);
1092:
1093: if (inSquareBrackets)
1094: bracketCount++;
1095: }
1096:
1097: break;
1098:
1099: case '/':
1100: if (!((inSquareBrackets || inCurlyBrackets) && ((flags & FNM_PATHNAME) != 0))) {
1101: globRegex.append(ch);
1102:
1103: if (inSquareBrackets)
1104: bracketCount++;
1105: }
1106:
1107: // don't include '/' in the brackets when FNM_PATHNAME is specified
1108: break;
1109:
1110: case '+':
1111: case '(':
1112: case ')':
1113: case '$':
1114: case '.':
1115: case '|':
1116: // escape regex special characters that are not glob
1117: // special characters
1118: globRegex.append('\\');
1119: globRegex.append(ch);
1120:
1121: if (inSquareBrackets)
1122: bracketCount++;
1123:
1124: break;
1125:
1126: case '\\':
1127: if ((flags & FNM_NOESCAPE) != 0)
1128: globRegex.append('\\');
1129:
1130: globRegex.append(ch);
1131:
1132: if (inSquareBrackets)
1133: bracketCount++;
1134:
1135: break;
1136:
1137: case '[':
1138: inSquareBrackets = true;
1139:
1140: globRegex.append(ch);
1141:
1142: break;
1143:
1144: case ']':
1145: inSquareBrackets = false;
1146:
1147: if (bracketCount == 0)
1148: return null;
1149:
1150: globRegex.append(ch);
1151:
1152: break;
1153:
1154: case '{':
1155: if (inSquareBrackets || inCurlyBrackets) {
1156: globRegex.append(ch);
1157:
1158: if (inSquareBrackets)
1159: bracketCount++;
1160: } else if (brace) {
1161: globRegex.append('(');
1162:
1163: inCurlyBrackets = true;
1164: } else {
1165: globRegex.append('\\');
1166: globRegex.append(ch);
1167: }
1168:
1169: break;
1170:
1171: case '}':
1172: if (inSquareBrackets) {
1173: globRegex.append(ch);
1174:
1175: bracketCount++;
1176: } else if (brace && inCurlyBrackets) {
1177: globRegex.append(')');
1178:
1179: inCurlyBrackets = false;
1180: } else {
1181: globRegex.append('\\');
1182: globRegex.append(ch);
1183: }
1184:
1185: break;
1186:
1187: case ',':
1188: if (brace && inCurlyBrackets)
1189: globRegex.append('|');
1190: else
1191: globRegex.append(ch);
1192:
1193: break;
1194:
1195: default:
1196: globRegex.append(ch);
1197:
1198: if (inSquareBrackets)
1199: bracketCount++;
1200:
1201: break;
1202: }
1203:
1204: lastCh = ch;
1205: }
1206:
1207: return globRegex.toString();
1208: }
1209:
1210: /**
1211: * Returns true if the given string matches the given glob pattern.
1212: */
1213: public static boolean fnmatch(Env env, String pattern,
1214: String string, @Optional
1215: int flags) {
1216: if (pattern == null || string == null)
1217: return false;
1218:
1219: if ((flags & FNM_CASEFOLD) != 0) {
1220: string = string.toLowerCase();
1221: pattern = pattern.toLowerCase();
1222: }
1223:
1224: // match "leading" periods exactly (i.e. no wildcards)
1225: if ((flags & FNM_PERIOD) != 0) {
1226: if (string.length() > 0 && string.charAt(0) == '.') {
1227: if (!(pattern.length() > 0 && pattern.charAt(0) == '.'))
1228: return false;
1229:
1230: string = string.substring(1);
1231: pattern = pattern.substring(1);
1232: } else if ((flags & FNM_PATHNAME) != 0) {
1233: // special case: if the string starts with '/.', then the pattern
1234: // must also start with exactly that.
1235: if ((string.length() >= 2) && (string.charAt(0) == '/')
1236: && (string.charAt(1) == '.')) {
1237: if (!((pattern.length() >= 2)
1238: && (pattern.charAt(0) == '/') && (pattern
1239: .charAt(1) == '.')))
1240: return false;
1241:
1242: string = string.substring(2);
1243: pattern = pattern.substring(2);
1244: }
1245: }
1246: }
1247:
1248: String globRegex = globToRegex(pattern, flags, false);
1249:
1250: if (globRegex == null)
1251: return false;
1252:
1253: return string.matches(globRegex.toString());
1254: }
1255:
1256: private static ProtocolWrapper getProtocolWrapper(Env env,
1257: StringValue pathName) {
1258: ArrayValue url = (ArrayValue) UrlModule
1259: .parse_url(env, pathName);
1260:
1261: Value scheme = url.get(env.createString("scheme"));
1262:
1263: if (scheme == UnsetValue.UNSET)
1264: return null;
1265:
1266: return StreamModule.getWrapper(scheme.toString());
1267: }
1268:
1269: /**
1270: * Opens a file.
1271: *
1272: * @param filename the path to the file to open
1273: * @param mode the mode the file should be opened as.
1274: * @param useIncludePath if true, search the current include path
1275: */
1276: @ReturnNullAsFalse
1277: public static BinaryStream fopen(Env env, StringValue filename,
1278: String mode, @Optional
1279: boolean useIncludePath, @Optional
1280: Value context) {
1281: if (filename.length() == 0) {
1282: env.warning(L.l("file name must not be null"));
1283: return null;
1284: }
1285:
1286: if (mode == null || mode.length() == 0) {
1287: env.warning(L.l("fopen mode must not be null"));
1288: return null;
1289: }
1290:
1291: // XXX: context
1292: try {
1293: ProtocolWrapper wrapper = getProtocolWrapper(env, filename);
1294:
1295: if (wrapper != null) {
1296: long options = 0;
1297:
1298: if (useIncludePath)
1299: options = StreamModule.STREAM_USE_PATH;
1300:
1301: return wrapper.fopen(env, filename, env
1302: .createString(mode), LongValue.create(options));
1303: }
1304:
1305: Path path;
1306:
1307: path = env.getPwd().lookup(filename.toString());
1308:
1309: if (mode.startsWith("r")) {
1310: if (useIncludePath)
1311: path = env.lookupInclude(filename.toString());
1312:
1313: if (path == null) {
1314: env.warning(L.l("{0} cannot be read", filename));
1315:
1316: return null;
1317: } else if (!path.exists()) {
1318: env.warning(L.l("{0} cannot be read", path
1319: .getFullPath()));
1320:
1321: return null;
1322: }
1323:
1324: try {
1325: BinaryInput input;
1326:
1327: if (mode.startsWith("r+"))
1328: input = new FileInputOutput(env, path);
1329: else
1330: input = new FileInput(env, path);
1331:
1332: return input;
1333: } catch (IOException e) {
1334:
1335: log.log(Level.FINE, e.toString(), e);
1336: env.warning(L.l("{0} cannot be read", path
1337: .getFullPath()));
1338:
1339: return null;
1340: }
1341: } else if (mode.startsWith("w")) {
1342: try {
1343: if (mode.startsWith("w+"))
1344: return new FileInputOutput(env, path, false,
1345: true);
1346: else
1347: return new FileOutput(env, path);
1348: } catch (IOException e) {
1349:
1350: log.log(Level.FINE, e.toString(), e);
1351: env.warning(L.l("{0} cannot be written", path
1352: .getFullPath()));
1353:
1354: return null;
1355: }
1356: } else if (mode.startsWith("a")) {
1357: try {
1358: if (mode.startsWith("a+"))
1359: return new FileInputOutput(env, path, true,
1360: false);
1361: else
1362: return new FileOutput(env, path, true);
1363: } catch (IOException e) {
1364:
1365: log.log(Level.FINE, e.toString(), e);
1366: env.warning(L.l("{0} cannot be written", path
1367: .getFullPath()));
1368:
1369: return null;
1370: }
1371: } else if (mode.startsWith("x")) {
1372: if (path.exists()) {
1373: env.warning(L.l("{0} already exist", filename));
1374:
1375: return null;
1376: }
1377:
1378: if (mode.startsWith("x+"))
1379: return new FileInputOutput(env, path);
1380: else
1381: return new FileOutput(env, path);
1382: }
1383:
1384: env.warning(L.l("bad mode `{0}'", mode));
1385:
1386: return null;
1387: } catch (IOException e) {
1388: log.log(Level.FINE, e.toString(), e);
1389:
1390: env.warning(L.l("{0} can't be opened.\n{1}", filename, e
1391: .toString()));
1392:
1393: return null;
1394: }
1395: }
1396:
1397: /**
1398: * Output the filepointer data to the output stream.
1399: */
1400: public Value fpassthru(Env env, @NotNull
1401: BinaryInput is) {
1402: // php/1635
1403:
1404: try {
1405: if (is == null)
1406: return BooleanValue.FALSE;
1407:
1408: WriteStream out = env.getOut();
1409:
1410: long writeLength = out.writeStream(is.getInputStream());
1411:
1412: return LongValue.create(writeLength);
1413: } catch (IOException e) {
1414: throw new QuercusModuleException(e);
1415: }
1416: }
1417:
1418: /**
1419: * Parses a comma-separated-value line from a file.
1420: *
1421: * @param file the file to read
1422: * @param delimiter optional comma replacement
1423: * @param enclosure optional quote replacement
1424: */
1425: public Value fputcsv(Env env, @NotNull
1426: BinaryOutput os, @NotNull
1427: ArrayValue value, @Optional
1428: StringValue delimiter, @Optional
1429: StringValue enclosure) {
1430: // php/1636
1431:
1432: try {
1433: if (os == null)
1434: return BooleanValue.FALSE;
1435:
1436: if (value == null)
1437: return BooleanValue.FALSE;
1438:
1439: char comma = ',';
1440: char quote = '\"';
1441:
1442: if (delimiter != null && delimiter.length() > 0)
1443: comma = delimiter.charAt(0);
1444:
1445: if (enclosure != null && enclosure.length() > 0)
1446: quote = enclosure.charAt(0);
1447:
1448: int writeLength = 0;
1449: boolean isFirst = true;
1450:
1451: for (Value data : value.values()) {
1452: if (!isFirst) {
1453: os.print(comma);
1454: writeLength++;
1455: }
1456: isFirst = false;
1457:
1458: StringValue s = data.toStringValue();
1459: int strlen = s.length();
1460:
1461: writeLength++;
1462: os.print(quote);
1463:
1464: for (int i = 0; i < strlen; i++) {
1465: char ch = s.charAt(i);
1466:
1467: if (ch != quote) {
1468: os.print(ch);
1469: writeLength++;
1470: } else {
1471: os.print(quote);
1472: os.print(quote);
1473: writeLength += 2;
1474: }
1475: }
1476:
1477: os.print(quote);
1478: writeLength++;
1479: }
1480:
1481: os.print("\n");
1482: writeLength++;
1483:
1484: return LongValue.create(writeLength);
1485: } catch (IOException e) {
1486: throw new QuercusModuleException(e);
1487: }
1488: }
1489:
1490: /**
1491: * Writes a string to the file.
1492: */
1493: public static Value fputs(Env env, BinaryOutput os,
1494: InputStream value, @Optional("0x7fffffff")
1495: int length) {
1496: return fwrite(env, os, value, length);
1497: }
1498:
1499: /**
1500: * Reads content from a file.
1501: *
1502: * @param is the file
1503: */
1504: public static Value fread(Env env, @NotNull
1505: BinaryInput is, int length) {
1506: if (is == null)
1507: return BooleanValue.FALSE;
1508:
1509: if (length < 0)
1510: length = Integer.MAX_VALUE;
1511:
1512: StringValue sb = env.createBinaryBuilder();
1513:
1514: sb.appendRead(is, length);
1515:
1516: return sb;
1517: }
1518:
1519: /**
1520: * Reads and parses a line.
1521: */
1522: public static Value fscanf(Env env, @NotNull
1523: BinaryInput is, StringValue format, @Optional
1524: Value[] args) {
1525: try {
1526: if (is == null)
1527: return BooleanValue.FALSE;
1528:
1529: StringValue value = is.readLine(Integer.MAX_VALUE);
1530:
1531: if (value == null)
1532: return BooleanValue.FALSE;
1533:
1534: return StringModule.sscanf(env, value, format, args);
1535: } catch (IOException e) {
1536: throw new QuercusModuleException(e);
1537: }
1538: }
1539:
1540: /**
1541: * Sets the current position.
1542: *
1543: * @param is the stream to test
1544: * @return 0 on success, -1 on error.
1545: */
1546: public static Value fseek(Env env, @NotNull
1547: BinaryInput is, long offset, @Optional
1548: int whence) {
1549: if (is == null)
1550: return LongValue.MINUS_ONE;
1551:
1552: long position = is.seek(offset, whence);
1553:
1554: if (position < 0)
1555: return LongValue.MINUS_ONE;
1556: else
1557: return LongValue.ZERO;
1558: }
1559:
1560: /**
1561: * Returns the status of the given file pointer.
1562: */
1563: public static Value fstat(Env env, @NotNull
1564: BinaryStream stream) {
1565: return stream.stat();
1566: }
1567:
1568: /**
1569: * Returns the current position.
1570: *
1571: * @param file the stream to test
1572: * @return position in file or FALSE on error.
1573: */
1574: public static Value ftell(Env env, @NotNull
1575: BinaryInput is) {
1576: if (is == null)
1577: return BooleanValue.FALSE;
1578:
1579: long pos = is.getPosition();
1580:
1581: if (pos < 0)
1582: return BooleanValue.FALSE;
1583:
1584: return LongValue.create(pos);
1585: }
1586:
1587: /**
1588: * Truncates a file.
1589: */
1590: public static boolean ftruncate(Env env, @NotNull
1591: BinaryOutput handle, long size) {
1592: if (handle instanceof FileOutput) {
1593: Path path = ((FileOutput) handle).getPath();
1594:
1595: try {
1596: return path.truncate(size);
1597: } catch (IOException e) {
1598: return false;
1599: }
1600: }
1601:
1602: return false;
1603: }
1604:
1605: /**
1606: * Writes a string to the file.
1607: */
1608: public static Value fwrite(Env env, @NotNull
1609: BinaryOutput os, InputStream value, @Optional("0x7fffffff")
1610: int length) {
1611: try {
1612: if (os == null)
1613: return BooleanValue.FALSE;
1614:
1615: return LongValue.create(os.write(value, length));
1616: } catch (IOException e) {
1617: throw new QuercusModuleException(e);
1618: }
1619: }
1620:
1621: private static ArrayValue globImpl(Env env, String pattern,
1622: int flags, Path path, String prefix, ArrayValue result) {
1623: String cwdPattern;
1624: String subPattern = null;
1625:
1626: int firstSlash = pattern.indexOf('/');
1627:
1628: if (firstSlash < 0)
1629: cwdPattern = pattern;
1630: else {
1631: cwdPattern = pattern.substring(0, firstSlash);
1632:
1633: // strip off any extra slashes
1634: for (; firstSlash < pattern.length(); firstSlash++) {
1635: if (pattern.charAt(firstSlash) != '/')
1636: break;
1637: }
1638:
1639: subPattern = pattern.substring(firstSlash);
1640: }
1641:
1642: int fnmatchFlags = 0;
1643:
1644: if ((flags & GLOB_NOESCAPE) != 0)
1645: fnmatchFlags = FNM_NOESCAPE;
1646:
1647: boolean doBraces = (flags & GLOB_BRACE) != 0;
1648:
1649: String globRegex = globToRegex(cwdPattern, fnmatchFlags,
1650: doBraces);
1651:
1652: if (globRegex == null)
1653: return null;
1654:
1655: Pattern compiledGlobRegex;
1656:
1657: try {
1658: compiledGlobRegex = Pattern.compile(globRegex);
1659: } catch (PatternSyntaxException e) {
1660: log.log(Level.FINE, e.toString(), e);
1661:
1662: return null;
1663: }
1664:
1665: String[] list;
1666:
1667: try {
1668: list = path.list();
1669: } catch (IOException e) {
1670: log.log(Level.FINE, e.toString(), e);
1671:
1672: return null;
1673: }
1674:
1675: for (String entry : list) {
1676: Matcher matcher = compiledGlobRegex.matcher(entry);
1677:
1678: if (matcher.matches()) {
1679: StringValue sb = env.createUnicodeBuilder();
1680:
1681: sb.append(prefix);
1682:
1683: if (prefix.length() > 0)
1684: sb.append("/");
1685:
1686: sb.append(entry);
1687:
1688: Path entryPath = path.lookup(entry);
1689:
1690: if (entryPath != null && entryPath.isDirectory()) {
1691: if (firstSlash >= 0 && subPattern.length() > 0) {
1692: // ArrayValue.add only adds values when the argument is an
1693: // actual array
1694:
1695: boolean isNull = null == globImpl(env,
1696: subPattern, flags, entryPath, sb
1697: .toString(), result);
1698:
1699: if ((flags & GLOB_ERR) != 0 && isNull)
1700: return null;
1701: } else if ((flags & GLOB_MARK) != 0) {
1702: sb.append("/");
1703: }
1704: }
1705:
1706: if ((firstSlash < 0 || subPattern.length() == 0)
1707: && (((flags & GLOB_ONLYDIR) == 0) || (((flags & GLOB_ONLYDIR) != 0) && (entryPath != null && entryPath
1708: .isDirectory()))))
1709: result.put(sb);
1710: }
1711: }
1712:
1713: return result;
1714: }
1715:
1716: /**
1717: * Matches all files with the given pattern.
1718: */
1719: public static Value glob(Env env, StringValue pattern, @Optional
1720: int flags) {
1721: Path path = env.getPwd();
1722:
1723: String trimmedPattern = pattern.toString();
1724:
1725: if (pattern.length() > 0 && pattern.charAt(0) == '/') {
1726: int i;
1727:
1728: // strip off any leading slashes
1729: for (i = 0; i < pattern.length(); i++) {
1730: if (pattern.charAt(i) != '/')
1731: break;
1732: }
1733:
1734: path = path.lookup("/");
1735:
1736: trimmedPattern = pattern.substring(i).toString();
1737: }
1738:
1739: ArrayValue result = new ArrayValueImpl();
1740:
1741: result = globImpl(env, trimmedPattern, flags, path, "", result);
1742:
1743: if (result == null)
1744: return BooleanValue.FALSE;
1745: else if (result.getSize() == 0 && (flags & GLOB_NOCHECK) != 0)
1746: result.put(pattern);
1747:
1748: if ((flags & GLOB_NOSORT) == 0)
1749: result.sort(ArrayValue.ValueComparator.CMP, true, true);
1750:
1751: return result;
1752: }
1753:
1754: /**
1755: * Returns the current working directory.
1756: *
1757: * @return the current directory
1758: */
1759: public static String getcwd(Env env) {
1760: // for xoops on Windows
1761: // paths returned must be consistent across Quercus
1762: return env.getPwd().getPath();
1763:
1764: // return env.getPwd().getNativePath();
1765: }
1766:
1767: /**
1768: * Returns true if the path is a directory.
1769: *
1770: * @param path the path to check
1771: */
1772: public static boolean is_dir(@NotNull
1773: Path path) {
1774: if (path == null)
1775: return false;
1776:
1777: return path.isDirectory();
1778: }
1779:
1780: /**
1781: * Returns true if the path is an executable file
1782: *
1783: * @param path the path to check
1784: */
1785: public static boolean is_executable(@NotNull
1786: Path path) {
1787: if (path == null)
1788: return false;
1789:
1790: return path.isExecutable();
1791: }
1792:
1793: /**
1794: * Returns true if the path is a file.
1795: *
1796: * @param path the path to check
1797: */
1798: public static boolean is_file(@NotNull
1799: Path path) {
1800: if (path == null)
1801: return false;
1802:
1803: return path.isFile();
1804: }
1805:
1806: /**
1807: * Returns true if the path is a symbolic link
1808: *
1809: * @param path the path to check
1810: */
1811: public static boolean is_link(Env env, @NotNull
1812: Path path) {
1813: if (path == null)
1814: return false;
1815:
1816: return path.isLink();
1817: }
1818:
1819: /**
1820: * Returns true if the path is readable
1821: *
1822: * @param path the path to check
1823: */
1824: public static boolean is_readable(Path path) {
1825: return path.canRead();
1826: }
1827:
1828: /**
1829: * Returns true for an uploaded file.
1830: *
1831: * @param path the temp name of the uploaded file
1832: */
1833: public static boolean is_uploaded_file(Env env, @NotNull
1834: Path path) {
1835: // php/1663, php/1664
1836:
1837: if (path == null)
1838: return false;
1839:
1840: String tail = path.getTail();
1841:
1842: return env.getUploadDirectory().lookup(tail).canRead();
1843: }
1844:
1845: /**
1846: * Returns true if the path is writable
1847: *
1848: * @param path the path to check
1849: */
1850: public static boolean is_writable(Path path) {
1851: if (path == null)
1852: return false;
1853:
1854: return path.canWrite();
1855: }
1856:
1857: /**
1858: * Returns true if the path is writable
1859: *
1860: * @param path the path to check
1861: */
1862: public static boolean is_writeable(Path path) {
1863: return is_writable(path);
1864: }
1865:
1866: /**
1867: * Creates a hard link
1868: */
1869: public boolean link(Env env, Path source, Path destination) {
1870: try {
1871: return destination.createLink(source, true);
1872: } catch (Exception e) {
1873: env.warning(e);
1874:
1875: return false;
1876: }
1877: }
1878:
1879: public static long linkinfo(Env env, Path path) {
1880: // XXX: Hack to trigger lstat() in JNI code
1881: if (path.isLink())
1882: return path.getDevice();
1883: else
1884: return 0;
1885: }
1886:
1887: /**
1888: * Returns file statistics
1889: */
1890: public static Value lstat(Env env, StringValue filename) {
1891: ProtocolWrapper wrapper = getProtocolWrapper(env, filename);
1892:
1893: if (wrapper != null)
1894: // XXX flags?
1895: return wrapper.url_stat(env, filename, LongValue
1896: .create(StreamModule.STREAM_URL_STAT_LINK));
1897:
1898: Path path = env.getPwd().lookup(filename.toString());
1899:
1900: // XXX: Hack to trigger lstat() in JNI code
1901: path.isLink();
1902:
1903: return statImpl(env, path);
1904: }
1905:
1906: /**
1907: * Makes the directory
1908: *
1909: * @param path the directory to make
1910: */
1911: public static boolean mkdir(Env env, StringValue dirname, @Optional
1912: int mode, @Optional
1913: boolean recursive, @Optional
1914: Value context) {
1915: ProtocolWrapper wrapper = getProtocolWrapper(env, dirname);
1916:
1917: if (wrapper != null)
1918: // XXX options?
1919: return wrapper.mkdir(env, dirname, LongValue.create(mode),
1920: LongValue.ZERO);
1921:
1922: Path path = env.getPwd().lookup(dirname.toString());
1923:
1924: try {
1925: if (recursive)
1926: return path.mkdirs();
1927: else
1928: return path.mkdir();
1929: } catch (IOException e) {
1930: log.log(Level.FINE, e.toString(), e);
1931:
1932: return false;
1933: }
1934: }
1935:
1936: /**
1937: * Moves the uploaded file.
1938: *
1939: * @param path the temp name of the uploaded file
1940: * @param dst the destination path
1941: */
1942: public static boolean move_uploaded_file(Env env, @NotNull
1943: Path src, @NotNull
1944: Path dst) {
1945: // php/1665, php/1666
1946:
1947: if (src == null)
1948: return false;
1949:
1950: if (dst == null)
1951: return false;
1952:
1953: String tail = src.getTail();
1954:
1955: src = env.getUploadDirectory().lookup(tail);
1956:
1957: try {
1958: if (src.canRead()) {
1959: src.renameTo(dst);
1960: return true;
1961: } else
1962: return false;
1963: } catch (IOException e) {
1964: env.warning(e);
1965:
1966: return false;
1967: }
1968: }
1969:
1970: /**
1971: * Opens a directory
1972: *
1973: * @param pathName the directory to open
1974: */
1975: public static Value opendir(Env env, StringValue pathName,
1976: @Optional
1977: Value context) {
1978: ProtocolWrapper wrapper = getProtocolWrapper(env, pathName);
1979:
1980: if (wrapper != null)
1981: /// XXX options?
1982: return wrapper.opendir(env, pathName, LongValue.ZERO);
1983:
1984: try {
1985: Path path = env.getPwd().lookup(pathName.toString());
1986:
1987: if (path.isDirectory())
1988: return new DirectoryValue(env, path);
1989: else {
1990: env.warning(L.l("{0} is not a directory", path
1991: .getFullPath()));
1992:
1993: return BooleanValue.FALSE;
1994: }
1995: } catch (IOException e) {
1996: throw new QuercusModuleException(e);
1997: }
1998: }
1999:
2000: /**
2001: * Parses the ini file.
2002: */
2003: public static Value parse_ini_file(Env env, Path path, @Optional
2004: boolean processSections) {
2005: ReadStream is = null;
2006:
2007: try {
2008: is = path.openRead();
2009: is.setEncoding(env.getScriptEncoding());
2010:
2011: return parseIni(env, is, processSections);
2012: } catch (IOException e) {
2013: env.warning(e);
2014:
2015: return BooleanValue.FALSE;
2016: } finally {
2017: if (is != null)
2018: is.close();
2019: }
2020: }
2021:
2022: private static ArrayValue parseIni(Env env, ReadStream is,
2023: boolean processSections) throws IOException {
2024: ArrayValue top = new ArrayValueImpl();
2025: ArrayValue section = top;
2026:
2027: int ch;
2028:
2029: while ((ch = is.read()) >= 0) {
2030: if (Character.isWhitespace(ch)) {
2031: } else if (ch == ';') {
2032: for (; ch >= 0 && ch != '\r' && ch != '\n'; ch = is
2033: .read()) {
2034: }
2035: } else if (ch == '[') {
2036: StringBuilder sb = new StringBuilder();
2037:
2038: for (ch = is.read(); ch >= 0 && ch != ']'; ch = is
2039: .read()) {
2040: sb.append((char) ch);
2041: }
2042:
2043: String name = sb.toString().trim();
2044:
2045: if (processSections) {
2046: section = new ArrayValueImpl();
2047: top.put(env.createString(name), section);
2048: }
2049: } else if (isValidIniKeyChar((char) ch)) {
2050: StringBuilder sb = new StringBuilder();
2051:
2052: for (; isValidIniKeyChar((char) ch); ch = is.read()) {
2053: sb.append((char) ch);
2054: }
2055:
2056: String key = sb.toString().trim();
2057:
2058: for (; ch >= 0 && ch != '='; ch = is.read()) {
2059: }
2060:
2061: for (ch = is.read(); ch == ' ' || ch == '\t'; ch = is
2062: .read()) {
2063: }
2064:
2065: Value value = parseIniValue(env, ch, is);
2066:
2067: section.put(env.createString(key), value);
2068: }
2069: }
2070:
2071: return top;
2072: }
2073:
2074: private static Value parseIniValue(Env env, int ch, ReadStream is)
2075: throws IOException {
2076: if (ch == '\r' || ch == '\n')
2077: return NullValue.NULL;
2078:
2079: if (ch == '"') {
2080: StringValue sb = env.createUnicodeBuilder();
2081:
2082: for (ch = is.read(); ch >= 0 && ch != '"'; ch = is.read()) {
2083: sb.append((char) ch);
2084: }
2085:
2086: skipToEndOfLine(ch, is);
2087:
2088: return sb;
2089: } else if (ch == '\'') {
2090: StringValue sb = env.createUnicodeBuilder();
2091:
2092: for (ch = is.read(); ch >= 0 && ch != '\''; ch = is.read()) {
2093: sb.append((char) ch);
2094: }
2095:
2096: skipToEndOfLine(ch, is);
2097:
2098: return sb;
2099: } else {
2100: StringBuilder sb = new StringBuilder();
2101:
2102: for (; ch >= 0 && ch != '\r' && ch != '\n'; ch = is.read()) {
2103: sb.append((char) ch);
2104: }
2105:
2106: String value = sb.toString().trim();
2107:
2108: if (value.equalsIgnoreCase("null"))
2109: return env.createEmptyString();
2110: else if (value.equalsIgnoreCase("true")
2111: || value.equalsIgnoreCase("yes"))
2112: return env.createString("1");
2113: else if (value.equalsIgnoreCase("false")
2114: || value.equalsIgnoreCase("no"))
2115: return env.createEmptyString();
2116:
2117: if (env.isDefined(value))
2118: return env.createString(env.getConstant(value)
2119: .toString());
2120: else
2121: return env.createString(value);
2122: }
2123: }
2124:
2125: private static boolean isValidIniKeyChar(char ch) {
2126: if (ch <= 0 || ch == '=' || ch == ';' || ch == '{' || ch == '}'
2127: || ch == '|' || ch == '&' || ch == '~' || ch == '!'
2128: || ch == '[' || ch == '(' || ch == ')' || ch == '"')
2129: return false;
2130: else
2131: return true;
2132: }
2133:
2134: private static void skipToEndOfLine(int ch, ReadStream is)
2135: throws IOException {
2136: for (; ch > 0 && ch != '\r' && ch != '\n'; ch = is.read()) {
2137: }
2138: }
2139:
2140: /**
2141: * Parses the path, splitting it into parts.
2142: */
2143: public static Value pathinfo(Env env, String path, @Optional
2144: Value optionsV) {
2145: if (optionsV == null)
2146: return env.createEmptyString();
2147:
2148: if (path == null) {
2149: if (!(optionsV instanceof DefaultValue)) {
2150: return env.createEmptyString();
2151: }
2152:
2153: ArrayValueImpl value = new ArrayValueImpl();
2154: value.put(env.createString("basename"), env
2155: .createString(""));
2156: value.put(env.createString("filename"), env
2157: .createString(""));
2158:
2159: return value;
2160: }
2161:
2162: int p = path.lastIndexOf('/');
2163:
2164: String dirname;
2165: if (p >= 0) {
2166: dirname = path.substring(0, p);
2167: path = path.substring(p + 1);
2168: } else {
2169: dirname = ".";
2170: }
2171:
2172: p = path.indexOf('.');
2173:
2174: String filename = path;
2175: String ext = "";
2176:
2177: if (p > 0) {
2178: filename = path.substring(0, p);
2179: ext = path.substring(p + 1);
2180: }
2181:
2182: if (!(optionsV instanceof DefaultValue)) {
2183: int options = optionsV.toInt();
2184:
2185: if ((options & PATHINFO_DIRNAME) == PATHINFO_DIRNAME)
2186: return env.createString(dirname);
2187: else if ((options & PATHINFO_BASENAME) == PATHINFO_BASENAME)
2188: return env.createString(path);
2189: else if ((options & PATHINFO_EXTENSION) == PATHINFO_EXTENSION)
2190: return env.createString(ext);
2191: else if ((options & PATHINFO_FILENAME) == PATHINFO_FILENAME)
2192: return env.createString(filename);
2193: else
2194: return env.createEmptyString();
2195: } else {
2196: ArrayValueImpl value = new ArrayValueImpl();
2197:
2198: value.put(env.createString("dirname"), env
2199: .createString(dirname));
2200: value.put(env.createString("basename"), env
2201: .createString(path));
2202: value.put(env.createString("extension"), env
2203: .createString(ext));
2204: value.put(env.createString("filename"), env
2205: .createString(filename));
2206:
2207: return value;
2208: }
2209: }
2210:
2211: public static int pclose(Env env, @NotNull
2212: BinaryStream stream) {
2213: if (stream instanceof PopenInput)
2214: return ((PopenInput) stream).pclose();
2215: else if (stream instanceof PopenOutput)
2216: return ((PopenOutput) stream).pclose();
2217: else {
2218: env.warning(L.l("{0} was not returned by popen()", stream));
2219:
2220: return -1;
2221: }
2222: }
2223:
2224: @ReturnNullAsFalse
2225: public static BinaryStream popen(Env env, @NotNull
2226: String command, @NotNull
2227: StringValue mode) {
2228: boolean doRead = false;
2229:
2230: if (mode.toString().equalsIgnoreCase("r"))
2231: doRead = true;
2232: else if (mode.toString().equalsIgnoreCase("w"))
2233: doRead = false;
2234: else
2235: return null;
2236:
2237: String[] args = new String[3];
2238:
2239: try {
2240: if (Path.isWindows()) {
2241: args[0] = "cmd";
2242: args[1] = "/c";
2243: } else {
2244: args[0] = "sh";
2245: args[1] = "-c";
2246: }
2247:
2248: args[2] = command;
2249:
2250: Process process = Runtime.getRuntime().exec(args);
2251:
2252: if (doRead)
2253: return new PopenInput(env, process);
2254: else
2255: return new PopenOutput(env, process);
2256: } catch (Exception e) {
2257: env.warning(e.getMessage(), e);
2258:
2259: return null;
2260: }
2261: }
2262:
2263: /**
2264: * Reads the next entry
2265: *
2266: * @param dirV the directory resource
2267: */
2268: public static Value readdir(Env env, @NotNull
2269: DirectoryValue dir) {
2270: if (dir == null)
2271: return BooleanValue.FALSE;
2272:
2273: return dir.readdir();
2274: }
2275:
2276: /**
2277: * Read the contents of a file and write them out.
2278: */
2279: public Value readfile(Env env, StringValue filename, @Optional
2280: boolean useIncludePath, @Optional
2281: Value context) {
2282: if (filename.length() == 0)
2283: return BooleanValue.FALSE;
2284:
2285: BinaryStream s = fopen(env, filename, "r", useIncludePath,
2286: context);
2287:
2288: if (!(s instanceof BinaryInput))
2289: return BooleanValue.FALSE;
2290:
2291: BinaryInput is = (BinaryInput) s;
2292:
2293: try {
2294: return fpassthru(env, is);
2295: } finally {
2296: is.close();
2297: }
2298: }
2299:
2300: /**
2301: * The readlink always fails.
2302: */
2303: public static boolean readlink(Env env, String path) {
2304: env.stub("readlink(" + path + ")");
2305:
2306: return false;
2307: }
2308:
2309: /**
2310: * Returns the actual path name.
2311: */
2312: public static String realpath(Path path) {
2313: String fullPath = path.getFullPath();
2314:
2315: if (fullPath.endsWith("/") && !fullPath.equals("/"))
2316: return fullPath.substring(0, fullPath.length() - 1);
2317: else
2318: return fullPath;
2319: }
2320:
2321: /**
2322: * Renames a file
2323: *
2324: * @param fromPath the path to change to
2325: * @param toPath the path to change to
2326: */
2327: public static boolean rename(Env env, StringValue from,
2328: StringValue to) {
2329: ProtocolWrapper wrapper = getProtocolWrapper(env, from);
2330:
2331: if (wrapper != null)
2332: return wrapper.rename(env, from, to);
2333:
2334: Path fromPath = env.getPwd().lookup(from.toString());
2335: Path toPath = env.getPwd().lookup(to.toString());
2336:
2337: if (!fromPath.canRead()) {
2338: env.warning(L.l("{0} cannot be read", fromPath
2339: .getFullPath()));
2340: return false;
2341: }
2342:
2343: try {
2344: return fromPath.renameTo(toPath);
2345: } catch (IOException e) {
2346: log.log(Level.FINE, e.toString(), e);
2347:
2348: return false;
2349: }
2350: }
2351:
2352: /**
2353: * Rewinds the stream.
2354: *
2355: * @param is the file resource
2356: */
2357: public static Value rewind(Env env, @NotNull
2358: BinaryInput is) {
2359: if (is == null)
2360: return BooleanValue.FALSE;
2361:
2362: fseek(env, is, 0, BinaryInput.SEEK_SET);
2363:
2364: return BooleanValue.TRUE;
2365: }
2366:
2367: /**
2368: * Rewinds the directory listing
2369: *
2370: * @param dirV the directory resource
2371: */
2372: public static void rewinddir(Env env, @NotNull
2373: DirectoryValue dir) {
2374: if (dir == null)
2375: return;
2376:
2377: dir.rewinddir();
2378: }
2379:
2380: /**
2381: * remove a directory
2382: */
2383: public static boolean rmdir(Env env, StringValue filename,
2384: @Optional
2385: Value context) {
2386: ProtocolWrapper wrapper = getProtocolWrapper(env, filename);
2387:
2388: if (wrapper != null)
2389: // XXX options?
2390: return wrapper.rmdir(env, filename, LongValue.ZERO);
2391:
2392: // quercus/160s
2393:
2394: // XXX: safe_mode
2395: try {
2396: Path path = env.getPwd().lookup(filename.toString());
2397:
2398: if (!path.isDirectory()) {
2399: env.warning(L.l("{0} is not a directory", path
2400: .getFullPath()));
2401: return false;
2402: }
2403:
2404: return path.remove();
2405: } catch (IOException e) {
2406: log.log(Level.FINE, e.toString(), e);
2407:
2408: return false;
2409: }
2410: }
2411:
2412: /**
2413: * Closes the directory
2414: *
2415: * @param dirV the directory resource
2416: */
2417: public static void closedir(Env env, @NotNull
2418: DirectoryValue dirV) {
2419: if (dirV == null)
2420: return;
2421:
2422: dirV.close();
2423: }
2424:
2425: /**
2426: * Scan the directory
2427: *
2428: * @param fileName the directory
2429: */
2430: public static Value scandir(Env env, String fileName,
2431: @Optional("1")
2432: int order, @Optional
2433: Value context) {
2434: if (fileName == null) {
2435: env.warning(L.l("file name must not be NULL"));
2436: return BooleanValue.FALSE;
2437: }
2438:
2439: try {
2440: Path path = env.getPwd().lookup(fileName);
2441:
2442: if (!path.isDirectory()) {
2443: env.warning(L.l("{0} is not a directory", path
2444: .getFullPath()));
2445: return BooleanValue.FALSE;
2446: }
2447:
2448: String[] values = path.list();
2449:
2450: Arrays.sort(values);
2451:
2452: ArrayValue result = new ArrayValueImpl();
2453:
2454: if (order == 1) {
2455: for (int i = 0; i < values.length; i++)
2456: result.append(new LongValue(i), env
2457: .createString(values[i]));
2458: } else {
2459: for (int i = values.length - 1; i >= 0; i--) {
2460: result.append(new LongValue(values.length - i - 1),
2461: env.createString(values[i]));
2462: }
2463: }
2464:
2465: return result;
2466: } catch (IOException e) {
2467: throw new QuercusModuleException(e);
2468: }
2469: }
2470:
2471: /**
2472: * Sets the write buffer.
2473: */
2474: public static int set_file_buffer(Env env, BinaryOutput stream,
2475: int bufferSize) {
2476: return StreamModule.stream_set_write_buffer(env, stream,
2477: bufferSize);
2478: }
2479:
2480: /**
2481: * Returns file statistics
2482: */
2483: public static Value stat(Env env, StringValue filename) {
2484: ProtocolWrapper wrapper = getProtocolWrapper(env, filename);
2485:
2486: if (wrapper != null)
2487: // XXX flags?
2488: return wrapper.url_stat(env, filename, LongValue.ZERO);
2489:
2490: Path path = env.getPwd().lookup(filename.toString());
2491:
2492: return statImpl(env, path);
2493: }
2494:
2495: static Value statImpl(Env env, Path path) {
2496: if (!path.exists()) {
2497: env.warning(L.l("stat failed for {0}", path.getFullPath()
2498: .toString()));
2499: return BooleanValue.FALSE;
2500: }
2501:
2502: ArrayValue result = new ArrayValueImpl();
2503:
2504: result.put(path.getDevice());
2505: result.put(path.getInode());
2506: result.put(path.getMode());
2507: result.put(path.getNumberOfLinks());
2508: result.put(path.getUser());
2509: result.put(path.getGroup());
2510: result.put(path.getDeviceId());
2511: result.put(path.getLength());
2512:
2513: result.put(path.getLastAccessTime() / 1000L);
2514: result.put(path.getLastModified() / 1000L);
2515: result.put(path.getLastStatusChangeTime() / 1000L);
2516: result.put(path.getBlockSize());
2517: result.put(path.getBlockCount());
2518:
2519: result.put("dev", path.getDevice());
2520: result.put("ino", path.getInode());
2521:
2522: result.put("mode", path.getMode());
2523: result.put("nlink", path.getNumberOfLinks());
2524: result.put("uid", path.getUser());
2525: result.put("gid", path.getGroup());
2526: result.put("rdev", path.getDeviceId());
2527:
2528: result.put("size", path.getLength());
2529:
2530: result.put("atime", path.getLastAccessTime() / 1000L);
2531: result.put("mtime", path.getLastModified() / 1000L);
2532: result.put("ctime", path.getLastStatusChangeTime() / 1000L);
2533: result.put("blksize", path.getBlockSize());
2534: result.put("blocks", path.getBlockCount());
2535:
2536: return result;
2537: }
2538:
2539: /**
2540: * Creates a symlink
2541: */
2542: public boolean symlink(Env env, Path source, Path destination) {
2543: try {
2544: return destination.createLink(source, false);
2545: } catch (Exception e) {
2546: env.warning(e);
2547:
2548: return false;
2549: }
2550: }
2551:
2552: /**
2553: * Creates a temporary file.
2554: */
2555: public static Value tempnam(Env env, Path dir, String prefix) {
2556: // php/160u
2557:
2558: if (dir == null || !dir.isDirectory())
2559: dir = env.getTempDirectory();
2560:
2561: try {
2562: dir.mkdirs();
2563: } catch (IOException e) {
2564: log.log(Level.FINE, e.toString(), e);
2565:
2566: return BooleanValue.FALSE;
2567: }
2568:
2569: try {
2570: Path path = dir.createTempFile(prefix, ".tmp");
2571:
2572: return env.createString(path.getTail());
2573: } catch (IOException e) {
2574: log.log(Level.FINE, e.toString(), e);
2575:
2576: return BooleanValue.FALSE;
2577: }
2578: }
2579:
2580: /**
2581: * Creates a temporary file.
2582: */
2583: @ReturnNullAsFalse
2584: public static FileInputOutput tmpfile(Env env) {
2585: try {
2586: Path tmp = env.getTempDirectory();
2587:
2588: tmp.mkdirs();
2589:
2590: Path file = tmp.createTempFile("resin", "tmp");
2591:
2592: return new FileInputOutput(env, file, false, false, true);
2593: } catch (IOException e) {
2594: log.log(Level.FINE, e.toString(), e);
2595:
2596: return null;
2597: }
2598: }
2599:
2600: /**
2601: * sets the time to the current time
2602: */
2603: public static boolean touch(Path path, @Optional
2604: int time, @Optional
2605: int atime) {
2606: // XXX: atime not implemented (it might be > time)
2607:
2608: try {
2609: if (path.exists()) {
2610: if (time > 0)
2611: path.setLastModified(1000L * time);
2612: else
2613: path.setLastModified(Alarm.getCurrentTime());
2614: } else {
2615: WriteStream ws = path.openWrite();
2616: ws.close();
2617: }
2618:
2619: return true;
2620: } catch (IOException e) {
2621: log.log(Level.FINE, e.toString(), e);
2622:
2623: return false;
2624: }
2625: }
2626:
2627: /**
2628: * umask call
2629: */
2630: public static int umask(Env env, int mask) {
2631: env.stub("umask(" + mask + ")");
2632:
2633: return mask;
2634: }
2635:
2636: /**
2637: * remove call
2638: */
2639: public static boolean unlink(Env env, StringValue filename,
2640: @Optional
2641: Value context) {
2642: // quercus/160p
2643:
2644: // XXX: safe_mode
2645: try {
2646: ProtocolWrapper wrapper = getProtocolWrapper(env, filename);
2647:
2648: if (wrapper != null)
2649: return wrapper.unlink(env, filename);
2650:
2651: Path path = env.getPwd().lookup(filename.toString());
2652:
2653: return path.remove();
2654: } catch (IOException e) {
2655: log.log(Level.FINE, e.toString(), e);
2656:
2657: return false;
2658: }
2659: }
2660:
2661: static {
2662: ProtocolWrapper zlibProtocolWrapper = new ZlibProtocolWrapper();
2663: StreamModule.stream_wrapper_register(new StringBuilderValue(
2664: "compress.zlib"), zlibProtocolWrapper);
2665: StreamModule.stream_wrapper_register(new StringBuilderValue(
2666: "zlib"), zlibProtocolWrapper);
2667: StreamModule.stream_wrapper_register(new StringBuilderValue(
2668: "php"), new PhpProtocolWrapper());
2669:
2670: _constMap.put("SEEK_SET", LongValue
2671: .create(BinaryInput.SEEK_SET));
2672: _constMap.put("SEEK_CUR", LongValue
2673: .create(BinaryInput.SEEK_CUR));
2674: _constMap.put("SEEK_END", LongValue
2675: .create(BinaryInput.SEEK_END));
2676:
2677: _constMap.put("LOCK_SH", LongValue.create(LOCK_SH));
2678: _constMap.put("LOCK_EX", LongValue.create(LOCK_EX));
2679: _constMap.put("LOCK_UN", LongValue.create(LOCK_UN));
2680: _constMap.put("LOCK_NB", LongValue.create(LOCK_NB));
2681:
2682: _constMap.put("FNM_PATHNAME", LongValue.create(FNM_PATHNAME));
2683: _constMap.put("FNM_NOESCAPE", LongValue.create(FNM_NOESCAPE));
2684: _constMap.put("FNM_PERIOD", LongValue.create(FNM_PERIOD));
2685: _constMap.put("FNM_CASEFOLD", LongValue.create(FNM_CASEFOLD));
2686:
2687: _constMap.put("GLOB_MARK", LongValue.create(GLOB_MARK));
2688: _constMap.put("GLOB_NOSORT", LongValue.create(GLOB_NOSORT));
2689: _constMap.put("GLOB_NOCHECK", LongValue.create(GLOB_NOCHECK));
2690: _constMap.put("GLOB_NOESCAPE", LongValue.create(GLOB_NOESCAPE));
2691: _constMap.put("GLOB_BRACE", LongValue.create(GLOB_BRACE));
2692: _constMap.put("GLOB_ONLYDIR", LongValue.create(GLOB_ONLYDIR));
2693: }
2694:
2695: static final IniDefinition INI_ALLOW_URL_FOPEN = _iniDefinitions
2696: .add("allow_url_fopen", true, PHP_INI_SYSTEM);
2697:
2698: static final IniDefinition INI_USER_AGENT = _iniDefinitions.add(
2699: "user_agent", null, PHP_INI_ALL);
2700:
2701: static final IniDefinition INI_DEFAULT_SOCKET_TIMEOUT = _iniDefinitions
2702: .add("default_socket_timeout", 60, PHP_INI_ALL);
2703:
2704: static final IniDefinition INI_FROM = _iniDefinitions.add("from",
2705: "", PHP_INI_ALL);
2706:
2707: static final IniDefinition INI_AUTO_DETECT_LINE_ENDINGS = _iniDefinitions
2708: .add("auto_detect_line_endings", false, PHP_INI_ALL);
2709:
2710: // file uploads
2711:
2712: static final IniDefinition INI_FILE_UPLOADS = _iniDefinitions.add(
2713: "file_uploads", true, PHP_INI_SYSTEM);
2714:
2715: static final IniDefinition INI_UPLOAD_TMP_DIR = _iniDefinitions
2716: .add("upload_tmp_dir", null, PHP_INI_SYSTEM);
2717:
2718: static final IniDefinition INI_UPLOAD_MAX_FILESIZE = _iniDefinitions
2719: .add("upload_max_filesize", "2M", PHP_INI_SYSTEM);
2720: }
|