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.env;
0031:
0032: import com.caucho.quercus.*;
0033: import com.caucho.quercus.expr.Expr;
0034: import com.caucho.quercus.function.Marshal;
0035: import com.caucho.quercus.function.MarshalFactory;
0036: import com.caucho.quercus.lib.ErrorModule;
0037: import com.caucho.quercus.lib.VariableModule;
0038: import com.caucho.quercus.lib.file.FileModule;
0039: import com.caucho.quercus.lib.string.StringModule;
0040: import com.caucho.quercus.lib.string.StringUtility;
0041: import com.caucho.quercus.module.ModuleContext;
0042: import com.caucho.quercus.module.ModuleStartupListener;
0043: import com.caucho.quercus.module.IniDefinition;
0044: import com.caucho.quercus.page.QuercusPage;
0045: import com.caucho.quercus.program.*;
0046: import com.caucho.quercus.resources.StreamContextResource;
0047: import com.caucho.util.*;
0048: import com.caucho.vfs.ByteToChar;
0049: import com.caucho.vfs.Encoding;
0050: import com.caucho.vfs.NullPath;
0051: import com.caucho.vfs.Path;
0052: import com.caucho.vfs.ReadStream;
0053: import com.caucho.vfs.WriteStream;
0054: import com.caucho.vfs.TempBuffer;
0055: import com.caucho.vfs.i18n.EncodingReader;
0056:
0057: import javax.script.Bindings;
0058: import javax.script.ScriptContext;
0059: import javax.servlet.ServletContext;
0060: import javax.servlet.http.Cookie;
0061: import javax.servlet.http.HttpServletRequest;
0062: import javax.servlet.http.HttpServletResponse;
0063: import javax.servlet.http.HttpSession;
0064: import javax.sql.DataSource;
0065: import java.io.IOException;
0066: import java.lang.ref.SoftReference;
0067: import java.lang.ref.WeakReference;
0068: import java.lang.reflect.Array;
0069: import java.net.URL;
0070: import java.sql.Connection;
0071: import java.util.ArrayList;
0072: import java.util.Collections;
0073: import java.util.HashMap;
0074: import java.util.HashSet;
0075: import java.util.LinkedHashMap;
0076: import java.util.Map;
0077: import java.util.IdentityHashMap;
0078: import java.util.TimeZone;
0079: import java.util.logging.Level;
0080: import java.util.logging.Logger;
0081:
0082: /**
0083: * Represents the Quercus environment.
0084: */
0085: public class Env {
0086: private static final L10N L = new L10N(Env.class);
0087: private static final Logger log = Logger.getLogger(Env.class
0088: .getName());
0089:
0090: public static final int B_ERROR = 0;
0091: public static final int B_WARNING = 1;
0092: public static final int B_PARSE = 2;
0093: public static final int B_NOTICE = 3;
0094: public static final int B_CORE_ERROR = 4;
0095: public static final int B_CORE_WARNING = 5;
0096: public static final int B_COMPILE_ERROR = 6;
0097: public static final int B_COMPILE_WARNING = 7;
0098: public static final int B_USER_ERROR = 8;
0099: public static final int B_USER_WARNING = 9;
0100: public static final int B_USER_NOTICE = 10;
0101: public static final int B_STRICT = 11;
0102:
0103: public static final int E_ERROR = 1 << B_ERROR;
0104: public static final int E_WARNING = 1 << B_WARNING;
0105: public static final int E_PARSE = 1 << B_PARSE;
0106: public static final int E_NOTICE = 1 << B_NOTICE;
0107: public static final int E_CORE_ERROR = 1 << B_CORE_ERROR;
0108: public static final int E_CORE_WARNING = 1 << B_CORE_WARNING;
0109: public static final int E_COMPILE_ERROR = 1 << B_COMPILE_ERROR;
0110: public static final int E_COMPILE_WARNING = 1 << B_COMPILE_WARNING;
0111: public static final int E_USER_ERROR = 1 << B_USER_ERROR;
0112: public static final int E_USER_WARNING = 1 << B_USER_WARNING;
0113: public static final int E_USER_NOTICE = 1 << B_USER_NOTICE;
0114: public static final int E_ALL = 2048 - 1;
0115: public static final int E_STRICT = 1 << B_STRICT;
0116:
0117: public static final int E_DEFAULT = E_ALL & ~E_NOTICE;
0118:
0119: private static final int _SERVER = 1;
0120: private static final int _GET = 2;
0121: private static final int _POST = 3;
0122: private static final int _COOKIE = 4;
0123: private static final int _GLOBAL = 5;
0124: private static final int _REQUEST = 6;
0125: private static final int _SESSION = 7;
0126: private static final int HTTP_GET_VARS = 8;
0127: private static final int HTTP_POST_VARS = 9;
0128: private static final int HTTP_COOKIE_VARS = 10;
0129: private static final int PHP_SELF = 11;
0130: private static final int _FILES = 12;
0131: private static final int HTTP_POST_FILES = 13;
0132: private static final int _ENV = 14;
0133: private static final int HTTP_SERVER_VARS = 15;
0134:
0135: private static final IntMap SPECIAL_VARS = new IntMap();
0136:
0137: private static final StringValue PHP_SELF_STRING = new StringBuilderValue(
0138: "PHP_SELF");
0139:
0140: private static final StringValue UTF8_STRING = new StringBuilderValue(
0141: "utf-8");
0142:
0143: public static final Value[] EMPTY_VALUE = new Value[0];
0144:
0145: private static final LruCache<ClassKey, SoftReference<QuercusClass>> _classCache = new LruCache<ClassKey, SoftReference<QuercusClass>>(
0146: 4096);
0147:
0148: private static final LruCache<IncludeKey, SoftReference<IncludeCache>> _includeCache = new LruCache<IncludeKey, SoftReference<IncludeCache>>(
0149: 4096);
0150:
0151: private static ThreadLocal<Env> _threadEnv = new ThreadLocal<Env>();
0152:
0153: private static final FreeList<AbstractFunction[]> _freeFunList = new FreeList<AbstractFunction[]>(
0154: 256);
0155:
0156: protected final Quercus _quercus;
0157: private final boolean _isUnicodeSemantics;
0158: private QuercusPage _page;
0159:
0160: private Value _this = NullThisValue.NULL;
0161:
0162: private ArrayList<SoftReference<EnvCleanup>> _cleanupList = new ArrayList<SoftReference<EnvCleanup>>();
0163:
0164: private ArrayList<Shutdown> _shutdownList = new ArrayList<Shutdown>();
0165:
0166: private final HashMap<String, Var> _globalMap = new HashMap<String, Var>(
0167: 1024);
0168:
0169: private HashMap<String, Var> _staticMap = new HashMap<String, Var>();
0170:
0171: private HashMap<String, Var> _map = _globalMap;
0172:
0173: private HashMap<String, Value> _constMap = new HashMap<String, Value>(
0174: 1024);
0175:
0176: private HashMap<String, Value> _lowerConstMap = new HashMap<String, Value>(
0177: 1024);
0178:
0179: private HashMap<String, QuercusClass> _classMap = new HashMap<String, QuercusClass>();
0180:
0181: private HashMap<String, QuercusClass> _lowerClassMap = new HashMap<String, QuercusClass>();
0182:
0183: private HashSet<String> _initializedClassSet = new HashSet<String>();
0184:
0185: // Function map
0186: public AbstractFunction[] _fun;
0187: // Class map
0188: public ClassDef[] _classDef;
0189: public QuercusClass[] _qClass;
0190:
0191: private IdentityHashMap<String, Value> _iniMap;
0192:
0193: // specialMap is used for implicit resources like the mysql link
0194: private HashMap<String, Object> _specialMap = new HashMap<String, Object>();
0195:
0196: // include_path ini
0197: private int _iniCount = 1;
0198:
0199: private String _defaultIncludePath;
0200: private String _includePath;
0201: private int _includePathIniCount;
0202: private ArrayList<String> _includePathList;
0203: private HashMap<Path, ArrayList<Path>> _includePathMap;
0204:
0205: private LinkedHashMap<Path, QuercusPage> _includeMap = new LinkedHashMap<Path, QuercusPage>();
0206:
0207: private HashMap<StringValue, Path> _lookupCache = new HashMap<StringValue, Path>();
0208:
0209: private HashMap<ConnectionEntry, ConnectionEntry> _connMap = new HashMap<ConnectionEntry, ConnectionEntry>();
0210:
0211: private AbstractFunction _autoload;
0212: private HashSet<String> _autoloadClasses = new HashSet<String>();
0213:
0214: private LinkedHashMap<String, AbstractFunction> _autoloadFunctionMap;
0215:
0216: private long _startTime;
0217: private long _timeLimit = 600000L;
0218:
0219: private Expr[] _callStack = new Expr[256];
0220: private Value[] _callThisStack = new Value[256];
0221: private int _callStackTop;
0222:
0223: private Value[] _functionArgs;
0224:
0225: private Path _selfPath;
0226: private Path _selfDirectory;
0227: private Path _pwd;
0228: private Path _uploadPath;
0229: private Path _tmpPath;
0230: private ArrayList<Path> _removePaths;
0231:
0232: private final boolean _isStrict;
0233:
0234: private HttpServletRequest _request;
0235: private HttpServletResponse _response;
0236:
0237: private ArrayValue _post;
0238: private ArrayValue _files;
0239: private SessionArrayValue _session;
0240: private HttpSession _javaSession;
0241:
0242: private ScriptContext _scriptContext;
0243:
0244: private WriteStream _originalOut;
0245: private OutputBuffer _outputBuffer;
0246:
0247: private WriteStream _out;
0248:
0249: private LocaleInfo _locale;
0250:
0251: private Callback[] _prevErrorHandlers = new Callback[B_STRICT + 1];
0252: private Callback[] _errorHandlers = new Callback[B_STRICT + 1];
0253:
0254: private Callback _prevExceptionHandler;
0255: private Callback _exceptionHandler;
0256:
0257: private SessionCallback _sessionCallback;
0258:
0259: private StreamContextResource _defaultStreamContext;
0260:
0261: // XXX: need to look this up from the module itself
0262: private int _errorMask = E_DEFAULT;
0263:
0264: private int _objectId = 0;
0265:
0266: private Logger _logger;
0267:
0268: // hold special Quercus php import statements
0269: private ImportMap _importMap;
0270:
0271: private TimeZone _defaultTimeZone;
0272:
0273: private Object _gzStream;
0274:
0275: private Env _oldThreadEnv;
0276:
0277: public Env(Quercus quercus, QuercusPage page, WriteStream out,
0278: HttpServletRequest request, HttpServletResponse response) {
0279: _quercus = quercus;
0280:
0281: _isStrict = quercus.isStrict();
0282: _isUnicodeSemantics = quercus.isUnicodeSemantics();
0283:
0284: _page = page;
0285:
0286: // XXX: grab initial from page
0287: // _defState = new DefinitionState(quercus);
0288:
0289: AbstractFunction[] defFuns = quercus.getFunctionMap();
0290: _fun = _freeFunList.allocate();
0291: if (_fun == null || _fun.length != defFuns.length)
0292: _fun = new AbstractFunction[defFuns.length];
0293: System.arraycopy(defFuns, 0, _fun, 0, defFuns.length);
0294:
0295: ClassDef[] defClasses = quercus.getClassDefMap();
0296:
0297: _classDef = new ClassDef[defClasses.length];
0298: _qClass = new QuercusClass[_classDef.length];
0299:
0300: _originalOut = out;
0301: _out = out;
0302:
0303: _request = request;
0304: _response = response;
0305:
0306: if (page != null) {
0307: _page.init(this );
0308:
0309: _page.importDefinitions(this );
0310: }
0311:
0312: setPwd(_quercus.getPwd());
0313:
0314: if (_page != null) {
0315: setSelfPath(_page.getSelfPath(null));
0316:
0317: // php/0b32
0318: _includeMap.put(_selfPath, _page);
0319: }
0320:
0321: if (_request != null && _request.getMethod().equals("POST")) {
0322: _post = new ArrayValueImpl();
0323: _files = new ArrayValueImpl();
0324: Post.fillPost(this , _post, _files, _request,
0325: getIniBoolean("magic_quotes_gpc"));
0326: }
0327:
0328: /*
0329: Cluster cluster = Cluster.getLocal();
0330:
0331: if (cluster != null) {
0332: ClusterServer selfServer = cluster.getSelfServer();
0333:
0334: if (selfServer != null)
0335: setIni("caucho.server_id", selfServer.getId());
0336: }
0337: */
0338: }
0339:
0340: public Env(Quercus quercus) {
0341: this (quercus, null, null, null, null);
0342: }
0343:
0344: public static Env getInstance() {
0345: return _threadEnv.get();
0346: }
0347:
0348: //
0349: // i18n
0350: //
0351:
0352: /**
0353: * Returns true if unicode.semantics is on.
0354: */
0355: public boolean isUnicodeSemantics() {
0356: return _isUnicodeSemantics;
0357: }
0358:
0359: /**
0360: * Returns the encoding used for scripts.
0361: */
0362: public String getScriptEncoding() {
0363: StringValue encoding = getIni("unicode.script_encoding");
0364:
0365: if (encoding.length() == 0) {
0366: encoding = getIni("unicode.fallback_encoding");
0367:
0368: if (encoding.length() == 0)
0369: return getQuercus().getScriptEncoding();
0370: }
0371:
0372: return encoding.toString();
0373: }
0374:
0375: /**
0376: * Returns the encoding used for runtime conversions, e.g. files
0377: * XXX: ISO-8859-1 when unicode.semantics is OFF
0378: */
0379: public String getRuntimeEncoding() {
0380: if (!_isUnicodeSemantics)
0381: return "iso-8859-1";
0382:
0383: StringValue encoding = getIni("unicode.runtime_encoding");
0384:
0385: if (encoding.length() == 0) {
0386: encoding = getIni("unicode.fallback_encoding");
0387:
0388: if (encoding.length() == 0)
0389: encoding = UTF8_STRING;
0390: }
0391:
0392: return encoding.toString();
0393: }
0394:
0395: /**
0396: * Sets the encoding used for runtime conversions.
0397: */
0398: public Value setRuntimeEncoding(String encoding) {
0399: return setIni("unicode.runtime_encoding", encoding);
0400: }
0401:
0402: /**
0403: * Returns the encoding used for runtime conversions, e.g. files
0404: */
0405: public EncodingReader getRuntimeEncodingFactory()
0406: throws IOException {
0407: return Encoding.getReadFactory(getRuntimeEncoding());
0408: }
0409:
0410: /**
0411: * Returns the encoding used for input, i.e. post,
0412: * null if unicode.semantics is off.
0413: */
0414: public String getHttpInputEncoding() {
0415: if (!_isUnicodeSemantics)
0416: return null;
0417:
0418: StringValue encoding = getIni("unicode.http_input_encoding");
0419:
0420: if (encoding.length() == 0) {
0421: encoding = getIni("unicode.fallback_encoding");
0422:
0423: if (encoding.length() == 0)
0424: encoding = UTF8_STRING;
0425: }
0426:
0427: return encoding.toString();
0428: }
0429:
0430: /**
0431: * Returns the encoding used for output, null if unicode.semantics is off.
0432: */
0433: public String getOutputEncoding() {
0434: if (!_isUnicodeSemantics)
0435: return null;
0436:
0437: String encoding = Quercus.INI_UNICODE_OUTPUT_ENCODING
0438: .getAsString(this );
0439:
0440: if (encoding == null)
0441: encoding = Quercus.INI_UNICODE_FALLBACK_ENCODING
0442: .getAsString(this );
0443:
0444: if (encoding == null)
0445: encoding = "utf-8";
0446:
0447: return encoding;
0448: }
0449:
0450: /**
0451: * Creates a binary builder.
0452: */
0453: public StringValue createBinaryBuilder() {
0454: if (_isUnicodeSemantics)
0455: return new BinaryBuilderValue();
0456: else
0457: return new StringBuilderValue();
0458: }
0459:
0460: /**
0461: * Creates a binary builder for large things like files.
0462: */
0463: public StringValue createLargeBinaryBuilder() {
0464: if (_isUnicodeSemantics)
0465: return new BinaryBuilderValue();
0466: else
0467: return new LargeStringBuilderValue();
0468: }
0469:
0470: /**
0471: * Creates a binary builder.
0472: */
0473: public StringValue createBinaryBuilder(int length) {
0474: if (_isUnicodeSemantics)
0475: return new BinaryBuilderValue(length);
0476: else
0477: return new StringBuilderValue(length);
0478: }
0479:
0480: /**
0481: * Creates a binary builder.
0482: */
0483: public StringValue createBinaryBuilder(byte[] buffer, int offset,
0484: int length) {
0485: if (_isUnicodeSemantics)
0486: return new BinaryBuilderValue(buffer, offset, length);
0487: else
0488: return new StringBuilderValue(buffer, offset, length);
0489: }
0490:
0491: /**
0492: * Creates a binary builder.
0493: */
0494: public StringValue createBinaryBuilder(byte[] buffer) {
0495: if (_isUnicodeSemantics)
0496: return new BinaryBuilderValue(buffer, 0, buffer.length);
0497: else
0498: return new StringBuilderValue(buffer, 0, buffer.length);
0499: }
0500:
0501: /**
0502: * Creates a unicode builder.
0503: */
0504: public StringValue createUnicodeBuilder() {
0505: if (_isUnicodeSemantics)
0506: return new UnicodeBuilderValue();
0507: else
0508: return new StringBuilderValue();
0509: }
0510:
0511: public TimeZone getDefaultTimeZone() {
0512: return _defaultTimeZone;
0513: }
0514:
0515: public void setDefaultTimeZone(String id) {
0516: _defaultTimeZone = TimeZone.getTimeZone(id);
0517: }
0518:
0519: public void setDefaultTimeZone(TimeZone zone) {
0520: _defaultTimeZone = zone;
0521: }
0522:
0523: /*
0524: * Returns the ServletContext.
0525: */
0526: public ServletContext getServletContext() {
0527: return _quercus.getServletContext();
0528: }
0529:
0530: /*
0531: * Sets the ScriptContext.
0532: */
0533: public void setScriptContext(ScriptContext context) {
0534: _scriptContext = context;
0535: }
0536:
0537: /**
0538: * Returns true for strict mode.
0539: */
0540: public final boolean isStrict() {
0541: return _isStrict;
0542: }
0543:
0544: public void start() {
0545: _oldThreadEnv = _threadEnv.get();
0546:
0547: _startTime = Alarm.getCurrentTime();
0548: _timeLimit = getIniLong("max_execution_time") * 1000;
0549:
0550: _threadEnv.set(this );
0551:
0552: // quercus/1b06
0553: String encoding = getOutputEncoding();
0554:
0555: String type = getIniString("default_mimetype");
0556:
0557: if ("".equals(type) || _response == null) {
0558: } else if (encoding != null)
0559: _response.setContentType(type + "; charset=" + encoding);
0560: else
0561: _response.setContentType(type);
0562:
0563: if (_out != null && encoding != null) {
0564: try {
0565: _out.setEncoding(encoding);
0566: } catch (Exception e) {
0567: log.log(Level.WARNING, e.toString(), e);
0568: }
0569: }
0570:
0571: HashSet<ModuleStartupListener> listeners = _quercus
0572: .getModuleStartupListeners();
0573:
0574: for (ModuleStartupListener listener : listeners)
0575: listener.startup(this );
0576: }
0577:
0578: /**
0579: * add resource to the list of refrences that are
0580: * cleaned up when finished with this environment.
0581: */
0582: public void addCleanup(EnvCleanup envCleanup) {
0583: _cleanupList.add(new SoftReference<EnvCleanup>(envCleanup));
0584: }
0585:
0586: /**
0587: * remove resource from the list of refrences that are
0588: * cleaned up when finished with this environment.
0589: *
0590: * @param resource
0591: */
0592: public void removeCleanup(EnvCleanup envCleanup) {
0593: for (int i = _cleanupList.size() - 1; i >= 0; i--) {
0594: SoftReference<EnvCleanup> ref = _cleanupList.get(i);
0595:
0596: EnvCleanup res = ref.get();
0597:
0598: if (envCleanup.equals(res)) {
0599: _cleanupList.remove(i);
0600: break;
0601: }
0602: }
0603: }
0604:
0605: /**
0606: * Returns the owning PHP engine.
0607: */
0608: public Quercus getQuercus() {
0609: return _quercus;
0610: }
0611:
0612: /**
0613: * Returns the owning PHP engine.
0614: */
0615: public ModuleContext getModuleContext() {
0616: return _quercus.getModuleContext();
0617: }
0618:
0619: /**
0620: * Returns the configured database.
0621: */
0622: public DataSource getDatabase() {
0623: return _quercus.getDatabase();
0624: }
0625:
0626: protected final DataSource findDatabase(String driver, String url)
0627: throws Exception {
0628: return _quercus.findDatabase(driver, url);
0629: }
0630:
0631: /**
0632: * Returns the configured database.
0633: */
0634: public Connection getConnection(String driver, String url,
0635: String userName, String password) throws Exception {
0636: DataSource database = _quercus.getDatabase();
0637:
0638: if (database != null) {
0639: ConnectionEntry entry = new ConnectionEntry();
0640: entry.init(database, null, null);
0641:
0642: ConnectionEntry oldEntry = _connMap.get(entry);
0643:
0644: Connection conn;
0645: if (oldEntry != null
0646: && (conn = oldEntry.getConnection()) != null
0647: && !conn.isClosed())
0648: return conn;
0649:
0650: entry.setConnection(database.getConnection());
0651: _connMap.put(entry, entry);
0652:
0653: conn = entry.getConnection();
0654:
0655: return conn;
0656: }
0657:
0658: database = findDatabase(driver, url);
0659:
0660: ConnectionEntry entry = new ConnectionEntry();
0661: entry.init(database, userName, password);
0662:
0663: ConnectionEntry oldEntry = _connMap.get(entry);
0664:
0665: Connection conn;
0666:
0667: if (oldEntry == null
0668: || (conn = oldEntry.getConnection()) == null
0669: || conn.isClosed()) {
0670: if (userName == null || userName.equals(""))
0671: conn = database.getConnection();
0672: else
0673: conn = database.getConnection(userName, password);
0674:
0675: entry.setConnection(conn);
0676:
0677: _connMap.put(entry, entry);
0678: }
0679:
0680: return conn;
0681: }
0682:
0683: /**
0684: * Returns the configured database.
0685: */
0686: public DataSource getDataSource(String driver, String url)
0687: throws Exception {
0688: DataSource database = _quercus.getDatabase();
0689:
0690: if (database != null)
0691: return database;
0692: else
0693: return findDatabase(driver, url);
0694: }
0695:
0696: /**
0697: * Sets the time limit.
0698: */
0699: public void setTimeLimit(long ms) {
0700: if (ms <= 0)
0701: ms = Long.MAX_VALUE / 2;
0702:
0703: _timeLimit = ms;
0704: }
0705:
0706: /**
0707: * Checks for the program timeout.
0708: */
0709: public final void checkTimeout() {
0710: long now = Alarm.getCurrentTime();
0711:
0712: if (_timeLimit > 0 && _startTime + _timeLimit < now)
0713: throw new QuercusRuntimeException(L.l("script timed out"));
0714: }
0715:
0716: public void resetTimeout() {
0717: _startTime = Alarm.getCurrentTime();
0718: }
0719:
0720: /**
0721: * Returns the writer.
0722: */
0723: public WriteStream getOut() {
0724: return _out;
0725: }
0726:
0727: /**
0728: * Returns the writer.
0729: */
0730: public WriteStream getOriginalOut() {
0731: return _originalOut;
0732: }
0733:
0734: /**
0735: * Flushes the output buffer.
0736: */
0737: public final void flush() {
0738: try {
0739: getOut().flush();
0740: } catch (IOException e) {
0741: throw new QuercusModuleException(e);
0742: }
0743: }
0744:
0745: /**
0746: * Prints a string
0747: */
0748: public final void print(String v) {
0749: try {
0750: getOut().print(v);
0751: } catch (IOException e) {
0752: throw new QuercusModuleException(e);
0753: }
0754: }
0755:
0756: /**
0757: * Prints a character buffer.
0758: */
0759: public final void print(char[] buffer, int offset, int length) {
0760: try {
0761: getOut().print(buffer, offset, length);
0762: } catch (IOException e) {
0763: throw new QuercusModuleException(e);
0764: }
0765: }
0766:
0767: /**
0768: * Prints a char
0769: */
0770: public final void print(char v) {
0771: try {
0772: getOut().print(v);
0773: } catch (IOException e) {
0774: throw new QuercusModuleException(e);
0775: }
0776: }
0777:
0778: /**
0779: * Prints a long
0780: */
0781: public final void print(long v) {
0782: try {
0783: getOut().print(v);
0784: } catch (IOException e) {
0785: throw new QuercusModuleException(e);
0786: }
0787: }
0788:
0789: /**
0790: * Prints a double
0791: */
0792: public final void print(double v) {
0793: try {
0794: long longV = (long) v;
0795:
0796: if (v == longV)
0797: getOut().print(longV);
0798: else
0799: getOut().print(v);
0800: } catch (IOException e) {
0801: throw new QuercusModuleException(e);
0802: }
0803: }
0804:
0805: /**
0806: * Prints an object
0807: */
0808: public final void print(Object v) {
0809: try {
0810: getOut().print(v);
0811: } catch (IOException e) {
0812: throw new QuercusModuleException(e);
0813: }
0814: }
0815:
0816: /**
0817: * Prints a value
0818: */
0819: public final void print(Value v) {
0820: v.print(this );
0821: }
0822:
0823: /**
0824: * Prints a string
0825: */
0826: public final void println() {
0827: try {
0828: getOut().println();
0829: } catch (IOException e) {
0830: throw new QuercusModuleException(e);
0831: }
0832: }
0833:
0834: /**
0835: * Prints a string
0836: */
0837: public final void println(String v) {
0838: try {
0839: getOut().println(v);
0840: } catch (IOException e) {
0841: throw new QuercusModuleException(e);
0842: }
0843: }
0844:
0845: /**
0846: * Prints a string
0847: */
0848: public final void println(Value v) {
0849: try {
0850: v.print(this );
0851: getOut().println();
0852: } catch (IOException e) {
0853: throw new QuercusModuleException(e);
0854: }
0855: }
0856:
0857: /**
0858: * Prints and object.
0859: */
0860: public final void println(Object v) {
0861: try {
0862: getOut().println(v);
0863: } catch (IOException e) {
0864: throw new QuercusModuleException(e);
0865: }
0866: }
0867:
0868: /**
0869: * Prints a byte buffer.
0870: */
0871: public final void write(byte[] buffer, int offset, int length) {
0872: try {
0873: getOut().write(buffer, offset, length);
0874: } catch (IOException e) {
0875: throw new QuercusModuleException(e);
0876: }
0877: }
0878:
0879: /**
0880: * Returns the current output buffer.
0881: */
0882: public OutputBuffer getOutputBuffer() {
0883: return _outputBuffer;
0884: }
0885:
0886: /**
0887: * Returns the writer.
0888: */
0889: public void pushOutputBuffer(Callback callback, int chunkSize,
0890: boolean erase) {
0891: if (_outputBuffer == null) {
0892: _outputBuffer = new OutputBuffer(_outputBuffer, this ,
0893: callback, chunkSize, erase);
0894: } else
0895: _outputBuffer = new OutputBuffer(_outputBuffer, this ,
0896: callback, chunkSize, erase);
0897:
0898: _out = _outputBuffer.getOut();
0899: }
0900:
0901: /**
0902: * Pops the output buffer
0903: */
0904: public boolean popOutputBuffer() {
0905: OutputBuffer outputBuffer = _outputBuffer;
0906:
0907: if (outputBuffer == null)
0908: return false;
0909:
0910: outputBuffer.close();
0911:
0912: _outputBuffer = outputBuffer.getNext();
0913:
0914: if (_outputBuffer != null)
0915: _out = _outputBuffer.getOut();
0916: else {
0917: _out = _originalOut;
0918: }
0919:
0920: return true;
0921: }
0922:
0923: /**
0924: * Returns the current directory.
0925: */
0926: public Path getPwd() {
0927: return _pwd;
0928: }
0929:
0930: /**
0931: * Returns the current directory.
0932: */
0933: public Path getWorkDir() {
0934: return _quercus.getWorkDir();
0935: }
0936:
0937: /**
0938: * Sets the current directory.
0939: */
0940: public void setPwd(Path path) {
0941: _pwd = path;
0942: _lookupCache.clear();
0943: }
0944:
0945: /**
0946: * Returns the initial directory.
0947: */
0948: public Path getSelfPath() {
0949: return _selfPath;
0950: }
0951:
0952: /**
0953: * Returns the initial directory.
0954: */
0955: public Path getSelfDirectory() {
0956: return _selfDirectory;
0957: }
0958:
0959: /**
0960: * Sets the initial directory.
0961: */
0962: public void setSelfPath(Path path) {
0963: _selfPath = path;
0964: _selfDirectory = _selfPath.getParent();
0965: }
0966:
0967: /**
0968: * Returns the upload directory.
0969: */
0970: public Path getUploadDirectory() {
0971: if (_uploadPath == null) {
0972: String realPath = getIniString("upload_tmp_dir");
0973:
0974: if (realPath == null)
0975: realPath = getRequest().getRealPath("/WEB-INF/upload");
0976:
0977: _uploadPath = _quercus.getPwd().lookup(realPath);
0978:
0979: try {
0980: if (!_uploadPath.isDirectory())
0981: _uploadPath.mkdirs();
0982: } catch (IOException e) {
0983: log.log(Level.FINE, e.toString(), e);
0984: }
0985:
0986: _uploadPath = _uploadPath.createRoot();
0987: }
0988:
0989: return _uploadPath;
0990: }
0991:
0992: /*
0993: * Returns the temp directory (used by tmpfile()).
0994: */
0995: public Path getTempDirectory() {
0996: String realPath;
0997:
0998: if (_tmpPath == null) {
0999: if (getRequest() != null)
1000: realPath = getRequest().getRealPath("/WEB-INF/tmp");
1001: else
1002: realPath = "file:/tmp";
1003:
1004: _tmpPath = getPwd().lookup(realPath);
1005:
1006: try {
1007: if (!_tmpPath.isDirectory())
1008: _tmpPath.mkdirs();
1009: } catch (IOException e) {
1010: log.log(Level.FINE, e.toString(), e);
1011: }
1012: }
1013:
1014: return _tmpPath;
1015: }
1016:
1017: /**
1018: * Adds an auto-remove path.
1019: */
1020: public void addRemovePath(Path path) {
1021: if (_removePaths == null)
1022: _removePaths = new ArrayList<Path>();
1023:
1024: _removePaths.add(path);
1025: }
1026:
1027: /**
1028: * Returns the request.
1029: */
1030: public HttpServletRequest getRequest() {
1031: return _request;
1032: }
1033:
1034: /**
1035: * Returns the most recently modified time of all of the {@link Path}'s that
1036: * have been used for this Env, or 0 if that cannot be determined.
1037: */
1038: /*
1039: public long getLastModified()
1040: {
1041: long lastModified = 0;
1042:
1043: if (_page != null) {
1044: Path pagePath = _page.getSelfPath(this);
1045:
1046: if (pagePath != null)
1047: lastModified = pagePath.getLastModified();
1048: }
1049:
1050: for (Path includePath : _includeSet) {
1051: long includeLastModified = includePath.getLastModified();
1052:
1053: if (lastModified < includeLastModified)
1054: lastModified = includeLastModified;
1055: }
1056:
1057: return lastModified;
1058: }
1059: */
1060:
1061: /**
1062: * Returns the response.
1063: */
1064: public HttpServletResponse getResponse() {
1065: return _response;
1066: }
1067:
1068: /**
1069: * Sets the session callback.
1070: */
1071: public void setSessionCallback(SessionCallback callback) {
1072: _sessionCallback = callback;
1073: }
1074:
1075: /**
1076: * Gets the session callback.
1077: */
1078: public SessionCallback getSessionCallback() {
1079: return _sessionCallback;
1080: }
1081:
1082: /**
1083: * Returns the session.
1084: */
1085: public SessionArrayValue getSession() {
1086: return _session;
1087: }
1088:
1089: /**
1090: * Returns the Java Http session.
1091: */
1092: public HttpSession getJavaSession() {
1093: return _javaSession;
1094: }
1095:
1096: /**
1097: * Sets the session.
1098: */
1099: public void setSession(SessionArrayValue session) {
1100: _session = session;
1101:
1102: if (session != null) {
1103: Value var = getGlobalVar("_SESSION");
1104:
1105: if (!(var instanceof SessionVar)) {
1106: var = new SessionVar();
1107: setGlobalValue("_SESSION", var);
1108: }
1109:
1110: var.set(session);
1111:
1112: setGlobalValue("HTTP_SESSION_VARS", session);
1113:
1114: session.addUse();
1115: } else {
1116: // php/1k0v
1117: Value v = getGlobalVar("_SESSION");
1118:
1119: if (v != null)
1120: v.set(UnsetValue.UNSET);
1121:
1122: v = getGlobalVar("HTTP_SESSION_VARS");
1123:
1124: if (v != null)
1125: v.set(UnsetValue.UNSET);
1126: }
1127: }
1128:
1129: /**
1130: * Returns a new session id.
1131: */
1132: public String generateSessionId() {
1133: String sessionId = _quercus.getQuercusSessionManager()
1134: .createSessionId(this );
1135:
1136: if (_javaSession != null)
1137: sessionId = _javaSession.getId().substring(0, 3)
1138: + sessionId.substring(3);
1139:
1140: return sessionId;
1141: }
1142:
1143: /**
1144: * Create the session.
1145: */
1146: public SessionArrayValue createSession(String sessionId,
1147: boolean create) {
1148: long now = Alarm.getCurrentTime();
1149:
1150: SessionCallback callback = getSessionCallback();
1151:
1152: _javaSession = _request.getSession(true);
1153:
1154: if (create && _javaSession.getId().length() >= 3
1155: && sessionId.length() >= 3)
1156: sessionId = _javaSession.getId().substring(0, 3)
1157: + sessionId.substring(3);
1158:
1159: SessionArrayValue session = _quercus.loadSession(this ,
1160: sessionId);
1161:
1162: if (callback != null) {
1163: StringValue value = callback.read(this , sessionId);
1164:
1165: if (value != null && value.length() != 0) {
1166: Value unserialize = VariableModule.unserialize(this ,
1167: value);
1168:
1169: if (unserialize instanceof ArrayValue) {
1170: ArrayValue arrayValue = (ArrayValue) unserialize;
1171:
1172: session.reset(now);
1173: session.putAll(arrayValue);
1174: }
1175: }
1176: }
1177:
1178: setSession(session);
1179:
1180: return session;
1181: }
1182:
1183: /**
1184: * Destroy the session.
1185: */
1186: public void destroySession(String sessionId) {
1187: SessionCallback callback = getSessionCallback();
1188:
1189: if (callback != null) {
1190: callback.destroy(this , sessionId);
1191: } else {
1192: _quercus.destroySession(sessionId);
1193: }
1194:
1195: setSession(null);
1196: }
1197:
1198: /**
1199: * Returns the logger used for syslog.
1200: */
1201: public Logger getLogger() {
1202: if (_logger == null)
1203: _logger = Logger.getLogger("quercus.quercus");
1204:
1205: return _logger;
1206: }
1207:
1208: /**
1209: * Returns the configuration value of an init var.
1210: */
1211: public Value getConfigVar(String name) {
1212: return getIniDefinition(name).getValue(_quercus);
1213: }
1214:
1215: /**
1216: * Returns a map of the ini values that have been explicitly set.
1217: */
1218: public IdentityHashMap<String, Value> getIniMap(boolean create) {
1219: if (_iniMap == null && create)
1220: _iniMap = new IdentityHashMap<String, Value>();
1221:
1222: return _iniMap;
1223: }
1224:
1225: /**
1226: * Sets an ini value.
1227: */
1228: public StringValue setIni(String name, Value value) {
1229: _iniCount++;
1230:
1231: StringValue oldValue = getIni(name);
1232:
1233: getIniDefinition(name).set(this , value);
1234:
1235: return oldValue;
1236: }
1237:
1238: /**
1239: * Sets an ini value.
1240: */
1241: public StringValue setIni(String name, String value) {
1242: _iniCount++;
1243:
1244: StringValue oldValue = getIni(name);
1245:
1246: getIniDefinition(name).set(this , value);
1247:
1248: return oldValue;
1249: }
1250:
1251: /**
1252: * Returns an ini value.
1253: */
1254: public StringValue getIni(String name) {
1255: return getIniDefinition(name).getAsStringValue(this );
1256: }
1257:
1258: private IniDefinition getIniDefinition(String name) {
1259: return _quercus.getIniDefinitions().get(name);
1260: }
1261:
1262: /**
1263: * Returns an ini value.
1264: */
1265: public boolean getIniBoolean(String name) {
1266: return getIniDefinition(name).getAsBoolean(this );
1267: }
1268:
1269: /**
1270: * Returns an ini value as a long.
1271: */
1272: public long getIniLong(String name) {
1273: return getIniDefinition(name).getAsLong(this );
1274: }
1275:
1276: /**
1277: * Returns an ini value as a string, null for missing or empty string
1278: */
1279: public String getIniString(String name) {
1280: return getIniDefinition(name).getAsString(this );
1281: }
1282:
1283: /**
1284: * Returns an ini value.
1285: */
1286: public long getIniBytes(String name, long deflt) {
1287: return getIniDefinition(name).getAsLongBytes(this , deflt);
1288: }
1289:
1290: /**
1291: * Returns the ByteToChar converter.
1292: */
1293: public ByteToChar getByteToChar() {
1294: return ByteToChar.create();
1295: }
1296:
1297: /**
1298: * Returns the 'this' value.
1299: */
1300: public Value getThis() {
1301: return _this ;
1302: }
1303:
1304: /**
1305: * Sets the 'this' value, returning the old value.
1306: */
1307: public Value setThis(Value value) {
1308: Value oldThis = _this ;
1309:
1310: _this = value.toValue();
1311:
1312: return oldThis;
1313: }
1314:
1315: /**
1316: * Gets a value.
1317: */
1318: public Value getValue(String name) {
1319: Var var = getRef(name);
1320:
1321: if (var != null)
1322: return var.toValue();
1323: else
1324: return NullValue.NULL;
1325: }
1326:
1327: /**
1328: * Gets a special value, a special value is used to store and retrieve module
1329: * specific values in the env using a unique name.
1330: */
1331: public <T> T getSpecialValue(String name) {
1332: return (T) _specialMap.get(name);
1333: }
1334:
1335: /**
1336: * Gets a global
1337: */
1338: public Value getGlobalValue(String name) {
1339: Var var = getGlobalRef(name);
1340:
1341: if (var != null)
1342: return var.toValue();
1343: else
1344: return NullValue.NULL;
1345: }
1346:
1347: /**
1348: * Gets a variable
1349: *
1350: * @param name the variable name
1351: * @param var the current value of the variable
1352: */
1353: public final Var getVar(String name, Value value) {
1354: if (value != null)
1355: return (Var) value;
1356:
1357: Var var = _map.get(name);
1358:
1359: if (var != null)
1360: return var;
1361:
1362: var = getRef(name);
1363:
1364: if (var == null) {
1365: var = new Var();
1366:
1367: if (_map == _globalMap)
1368: var.setGlobal();
1369:
1370: _map.put(name, var);
1371: }
1372:
1373: return var;
1374: }
1375:
1376: /**
1377: * Gets a variable
1378: *
1379: * @param name the variable name
1380: * @param value the current value of the variable
1381: */
1382: public final Var getGlobalVar(String name, Value value) {
1383: if (value != null)
1384: return (Var) value;
1385:
1386: Var var = _globalMap.get(name);
1387:
1388: if (var != null)
1389: return var;
1390:
1391: var = getSpecialRef(name);
1392:
1393: if (var == null) {
1394: var = new Var();
1395: var.setGlobal();
1396: }
1397:
1398: _globalMap.put(name, var);
1399:
1400: return var;
1401: }
1402:
1403: /**
1404: * Gets a static variable name.
1405: */
1406: public final String createStaticName() {
1407: return _quercus.createStaticName();
1408: }
1409:
1410: /**
1411: * Gets a static variable
1412: *
1413: * @param name the variable name
1414: */
1415: public final Var getStaticVar(String name) {
1416: Var var = _staticMap.get(name);
1417:
1418: if (var == null) {
1419: var = new Var();
1420: var.setGlobal();
1421: _staticMap.put(name, var);
1422: }
1423:
1424: return var;
1425: }
1426:
1427: /**
1428: * Unsets variable
1429: *
1430: * @param name the variable name
1431: */
1432: public final Var unsetVar(String name) {
1433: _map.remove(name);
1434:
1435: return null;
1436: }
1437:
1438: /**
1439: * Gets a variable
1440: *
1441: * @param name the variable name
1442: * @param value the current value of the variable
1443: */
1444: public final Var setVar(String name, Value value) {
1445: Var var;
1446:
1447: if (value instanceof Var) {
1448: var = (Var) value;
1449:
1450: if (_map == _globalMap)
1451: var.setGlobal();
1452: } else
1453: var = new Var(value.toValue());
1454:
1455: _map.put(name, var);
1456:
1457: return var;
1458: }
1459:
1460: /**
1461: * Unsets variable
1462: *
1463: * @param name the variable name
1464: */
1465: public final Var unsetLocalVar(String name) {
1466: _map.remove(name);
1467:
1468: return null;
1469: }
1470:
1471: /**
1472: * Unsets variable
1473: *
1474: * @param name the variable name
1475: */
1476: public final Var unsetGlobalVar(String name) {
1477: _globalMap.remove(name);
1478:
1479: return null;
1480: }
1481:
1482: /**
1483: * Gets a local
1484: *
1485: * @param var the current value of the variable
1486: */
1487: public static final Value getLocalVar(Value var) {
1488: if (var == null)
1489: var = new Var();
1490:
1491: return var;
1492: }
1493:
1494: /**
1495: * Gets a local value
1496: *
1497: * @param var the current value of the variable
1498: */
1499: public static final Value getLocalValue(Value var) {
1500: if (var != null)
1501: return var;
1502: else
1503: return NullValue.NULL;
1504: }
1505:
1506: /**
1507: * Gets a local
1508: *
1509: * @param var the current value of the variable
1510: */
1511: public static final Value setLocalVar(Value var, Value value) {
1512: value = value.toValue();
1513:
1514: if (var instanceof Var)
1515: var.set(value);
1516:
1517: return value;
1518: }
1519:
1520: /**
1521: * Gets a value.
1522: */
1523: public Var getRef(String name) {
1524: Var var = _map.get(name);
1525:
1526: if (var == null) {
1527: var = getSpecialRef(name);
1528:
1529: if (var != null) {
1530: var.setGlobal();
1531: _globalMap.put(name, var);
1532:
1533: var = _map.get(name);
1534: }
1535: }
1536:
1537: return var;
1538: }
1539:
1540: /**
1541: * Returns the raw global lookup.
1542: */
1543: public Var getGlobalRaw(String name) {
1544: return _globalMap.get(name);
1545: }
1546:
1547: /**
1548: * Gets a global value.
1549: */
1550: public Var getGlobalRef(String name) {
1551: Var var = _globalMap.get(name);
1552:
1553: if (var == null) {
1554: var = getSpecialRef(name);
1555: if (var == null)
1556: var = new Var();
1557:
1558: _globalMap.put(name, var);
1559: }
1560:
1561: return var;
1562: }
1563:
1564: /**
1565: * Gets a value.
1566: */
1567: public Var getSpecialRef(String name) {
1568: Var var = null;
1569:
1570: switch (SPECIAL_VARS.get(name)) {
1571: case _ENV: {
1572: var = new Var();
1573:
1574: _globalMap.put(name, var);
1575:
1576: var.set(new ArrayValueImpl());
1577:
1578: return var;
1579: }
1580:
1581: case HTTP_POST_VARS:
1582: if (!Quercus.INI_REGISTER_LONG_ARRAYS.getAsBoolean(this ))
1583: return null;
1584: case _POST: {
1585: var = new Var();
1586:
1587: _globalMap.put(name, var);
1588:
1589: ArrayValue post = new ArrayValueImpl();
1590:
1591: var.set(post);
1592:
1593: if (_request == null)
1594: return null;
1595:
1596: if (!"POST".equals(_request.getMethod()))
1597: return var;
1598:
1599: if (_post != null) {
1600: for (Map.Entry<Value, Value> entry : _post.entrySet()) {
1601: post.put(entry.getKey(), entry.getValue());
1602: }
1603: }
1604: }
1605: break;
1606:
1607: case HTTP_POST_FILES:
1608: if (!Quercus.INI_REGISTER_LONG_ARRAYS.getAsBoolean(this ))
1609: return null;
1610: case _FILES: {
1611: var = new Var();
1612:
1613: _globalMap.put(name, var);
1614:
1615: ArrayValue files = new ArrayValueImpl();
1616:
1617: if (_files != null) {
1618: for (Map.Entry<Value, Value> entry : _files.entrySet()) {
1619: files.put(entry.getKey(), entry.getValue());
1620: }
1621: }
1622:
1623: var.set(files);
1624: }
1625: break;
1626:
1627: case HTTP_GET_VARS:
1628: if (!Quercus.INI_REGISTER_LONG_ARRAYS.getAsBoolean(this ))
1629: return null;
1630:
1631: case _GET: {
1632: var = new Var();
1633:
1634: ArrayValue array = new ArrayValueImpl();
1635:
1636: var.set(array);
1637: _globalMap.put(name, var);
1638:
1639: String queryString = _request.getQueryString();
1640: if (queryString == null)
1641: return var;
1642:
1643: StringUtility.parseStr(this , queryString, array, true,
1644: getHttpInputEncoding());
1645:
1646: return var;
1647: }
1648:
1649: case _REQUEST: {
1650: var = new Var();
1651:
1652: ArrayValue array = new ArrayValueImpl();
1653:
1654: var.set(array);
1655:
1656: _globalMap.put(name, var);
1657:
1658: if (_request == null)
1659: return var;
1660:
1661: try {
1662: String encoding = getHttpInputEncoding();
1663:
1664: if (encoding == null)
1665: encoding = "iso-8859-1";
1666:
1667: _request.setCharacterEncoding(encoding);
1668: } catch (Exception e) {
1669: log.log(Level.FINE, e.toString(), e);
1670: }
1671:
1672: ArrayList<String> keys = new ArrayList<String>();
1673: keys.addAll(_request.getParameterMap().keySet());
1674:
1675: Collections.sort(keys);
1676:
1677: boolean isMagicQuotes = getIniBoolean("magic_quotes_gpc");
1678:
1679: for (String key : keys) {
1680: String[] value = _request.getParameterValues(key);
1681:
1682: Post.addFormValue(this , array, key, value,
1683: isMagicQuotes);
1684: }
1685:
1686: if (name.equals("_REQUEST") && _post != null) {
1687: for (Map.Entry<Value, Value> entry : _post.entrySet()) {
1688: array.put(entry.getKey(), entry.getValue().copy());
1689: }
1690: }
1691:
1692: Cookie[] cookies = _request.getCookies();
1693: for (int i = 0; cookies != null && i < cookies.length; i++) {
1694: Post.addFormValue(this , array, cookies[i].getName(),
1695: new String[] { cookies[i].getValue() },
1696: isMagicQuotes);
1697: }
1698:
1699: return var;
1700: }
1701:
1702: case HTTP_SERVER_VARS:
1703: if (!Quercus.INI_REGISTER_LONG_ARRAYS.getAsBoolean(this ))
1704: return null;
1705: case _SERVER: {
1706: var = new Var();
1707:
1708: _globalMap.put(name, var);
1709:
1710: var.set(new ServerArrayValue(this ));
1711:
1712: return var;
1713: }
1714:
1715: case _GLOBAL: {
1716: var = new Var();
1717:
1718: _globalMap.put(name, var);
1719:
1720: var.set(new GlobalArrayValue(this ));
1721:
1722: return var;
1723: }
1724:
1725: case HTTP_COOKIE_VARS:
1726: if (!Quercus.INI_REGISTER_LONG_ARRAYS.getAsBoolean(this ))
1727: return null;
1728: case _COOKIE: {
1729: var = new Var();
1730: _globalMap.put(name, var);
1731:
1732: if (_request == null)
1733: return var;
1734:
1735: ArrayValue array = new ArrayValueImpl();
1736:
1737: Cookie[] cookies = _request.getCookies();
1738: if (cookies != null) {
1739: for (int i = 0; i < cookies.length; i++) {
1740: Cookie cookie = cookies[i];
1741:
1742: String value = decodeValue(cookie.getValue());
1743:
1744: StringValue valueAsValue = createString(value);
1745:
1746: if (getIniBoolean("magic_quotes_gpc")) // php/0876
1747: valueAsValue = StringModule
1748: .addslashes(valueAsValue);
1749:
1750: array.append(createString(cookie.getName()),
1751: valueAsValue);
1752: }
1753: }
1754:
1755: var.set(array);
1756:
1757: return var;
1758: }
1759:
1760: case PHP_SELF: {
1761: var = new Var();
1762: _globalMap.put(name, var);
1763:
1764: var.set(getGlobalVar("_SERVER").get(PHP_SELF_STRING));
1765:
1766: return var;
1767: }
1768:
1769: default: {
1770: if (_scriptContext != null) {
1771: Object value = _scriptContext.getAttribute(name);
1772:
1773: if (value == null) {
1774: Bindings bindings = _scriptContext
1775: .getBindings(ScriptContext.ENGINE_SCOPE);
1776:
1777: if (bindings != null)
1778: value = bindings.get(name);
1779: }
1780:
1781: if (value == null) {
1782: Bindings bindings = _scriptContext
1783: .getBindings(ScriptContext.GLOBAL_SCOPE);
1784:
1785: if (bindings != null)
1786: value = bindings.get(name);
1787: }
1788:
1789: if (value != null) {
1790: var = new Var();
1791: _globalMap.put(name, var);
1792:
1793: var.set(wrapJava(value));
1794:
1795: return var;
1796: }
1797: }
1798: }
1799: } // end switch
1800:
1801: return var;
1802: }
1803:
1804: private static String decodeValue(String s) {
1805: int len = s.length();
1806: StringBuilder sb = new StringBuilder();
1807:
1808: for (int i = 0; i < len; i++) {
1809: char ch = s.charAt(i);
1810:
1811: if (ch == '%' && i + 2 < len) {
1812: int d1 = s.charAt(i + 1);
1813: int d2 = s.charAt(i + 2);
1814:
1815: int v = 0;
1816:
1817: if ('0' <= d1 && d1 <= '9')
1818: v = 16 * (d1 - '0');
1819: else if ('a' <= d1 && d1 <= 'f')
1820: v = 16 * (d1 - 'a' + 10);
1821: else if ('A' <= d1 && d1 <= 'F')
1822: v = 16 * (d1 - 'A' + 10);
1823: else {
1824: sb.append('%');
1825: continue;
1826: }
1827:
1828: if ('0' <= d2 && d2 <= '9')
1829: v += (d2 - '0');
1830: else if ('a' <= d2 && d2 <= 'f')
1831: v += (d2 - 'a' + 10);
1832: else if ('A' <= d2 && d2 <= 'F')
1833: v += (d2 - 'A' + 10);
1834: else {
1835: sb.append('%');
1836: continue;
1837: }
1838:
1839: i += 2;
1840: sb.append((char) v);
1841: } else if (ch == '+')
1842: sb.append(' ');
1843: else
1844: sb.append(ch);
1845: }
1846:
1847: return sb.toString();
1848: }
1849:
1850: /**
1851: * Gets a value.
1852: */
1853: public Var getVar(String name) {
1854: Var var = _map.get(name);
1855:
1856: if (var != null)
1857: return var;
1858:
1859: var = getRef(name);
1860:
1861: if (var == null) {
1862: var = new Var();
1863:
1864: if (_map == _globalMap) {
1865: // php/379c
1866: var.setGlobal();
1867: }
1868:
1869: _map.put(name, var);
1870: }
1871:
1872: return var;
1873: }
1874:
1875: /**
1876: * Gets a value.
1877: */
1878: public Var getGlobalVar(String name) {
1879: Var var = getGlobalRef(name);
1880:
1881: if (var == null) {
1882: var = new Var();
1883: var.setGlobal();
1884: _globalMap.put(name, var);
1885: }
1886:
1887: return var;
1888: }
1889:
1890: public boolean isGlobalEnv() {
1891: return _map == _globalMap;
1892: }
1893:
1894: /**
1895: * Sets a value.
1896: */
1897: public Value setValue(String name, Value value) {
1898: if (value instanceof Var)
1899: _map.put(name, (Var) value);
1900: else {
1901: Var var = getVar(name);
1902: var.set(value);
1903: }
1904:
1905: return value;
1906: }
1907:
1908: /**
1909: * Sets a special value, a special value is used to store and retrieve module
1910: * specific values in the env using a unique name.
1911: */
1912: public Object setSpecialValue(String name, Object value) {
1913: _specialMap.put(name, value);
1914:
1915: return value;
1916: }
1917:
1918: /**
1919: * Sets a value.
1920: */
1921: public Value setGlobalValue(String name, Value value) {
1922: if (value instanceof Var)
1923: _globalMap.put(name, (Var) value);
1924: else {
1925: Var var = getGlobalVar(name);
1926: var.set(value);
1927: }
1928:
1929: return value;
1930: }
1931:
1932: /**
1933: * Gets a static class field.
1934: *
1935: * @param className of the owning class
1936: * @param name of the variable
1937: */
1938: public Value getStaticClassFieldValue(String className, String name) {
1939: Var var = getStaticClassFieldVar(className, name);
1940:
1941: if (var != null) {
1942: Value val = var.toValue();
1943:
1944: return val;
1945: } else
1946: return NullValue.NULL;
1947: }
1948:
1949: /**
1950: * Gets a static field from a class.
1951: *
1952: * @param className of the owning class
1953: * @param name of the variable
1954: */
1955: public final Var getStaticClassFieldVar(String className,
1956: String name) {
1957: QuercusClass cl = findAbstractClass(className);
1958:
1959: Var var = cl.getStaticField(this , name);
1960:
1961: if (var == null) {
1962: error(L.l("{0}::${1} is an undeclared static property",
1963: className, name));
1964: }
1965:
1966: return var;
1967: }
1968:
1969: /**
1970: * Sets the calling function expression.
1971: */
1972: public void pushCall(Expr call, Value obj) {
1973: if (_callStack.length <= _callStackTop) {
1974: Expr[] newStack = new Expr[2 * _callStack.length];
1975: System.arraycopy(_callStack, 0, newStack, 0,
1976: _callStack.length);
1977: _callStack = newStack;
1978:
1979: Value[] newThisStack = new Value[2 * _callThisStack.length];
1980: System.arraycopy(_callThisStack, 0, newThisStack, 0,
1981: _callThisStack.length);
1982: _callThisStack = newThisStack;
1983: }
1984:
1985: _callStack[_callStackTop] = call;
1986: _callThisStack[_callStackTop] = obj;
1987:
1988: _callStackTop++;
1989: }
1990:
1991: /**
1992: * Pops the top call.
1993: */
1994: public Expr popCall() {
1995: return _callStack[--_callStackTop];
1996: }
1997:
1998: /**
1999: * Returns the stack depth.
2000: */
2001: public int getCallDepth() {
2002: return _callStackTop;
2003: }
2004:
2005: /**
2006: * Peeks at the the top call.
2007: */
2008: public Expr peekCall(int depth) {
2009: if (_callStackTop - depth > 0)
2010: return _callStack[_callStackTop - depth - 1];
2011: else
2012: return null;
2013: }
2014:
2015: /**
2016: * Peeks at the the "this" top call.
2017: */
2018: public Value peekCallThis(int depth) {
2019: if (_callStackTop - depth > 0)
2020: return _callThisStack[_callStackTop - depth - 1];
2021: else
2022: return null;
2023: }
2024:
2025: public ArrayList<String> getStackTrace() {
2026: ArrayList<String> trace = new ArrayList<String>();
2027:
2028: for (int i = _callStackTop - 1; i >= 0; i--) {
2029: String entry;
2030: Location location = _callStack[i].getLocation();
2031: String loc;
2032:
2033: if (location != null && location.getFileName() != null) {
2034: loc = (" (at " + location.getFileName() + ":"
2035: + location.getLineNumber() + ")");
2036: } else
2037: loc = "";
2038:
2039: if (_callThisStack[i] != null
2040: && !"".equals(_callThisStack[i].toString())) {
2041: entry = _callThisStack[i] + "."
2042: + _callStack[i].toString() + loc;
2043: } else
2044: entry = _callStack[i].toString() + loc;
2045:
2046: trace.add(entry);
2047: }
2048:
2049: return trace;
2050: }
2051:
2052: /**
2053: * Pushes a new environment.
2054: */
2055: public HashMap<String, Var> pushEnv(HashMap<String, Var> map) {
2056: HashMap<String, Var> oldEnv = _map;
2057:
2058: _map = map;
2059:
2060: return oldEnv;
2061: }
2062:
2063: /**
2064: * Restores the old environment.
2065: */
2066: public void popEnv(HashMap<String, Var> oldEnv) {
2067: _map = oldEnv;
2068: }
2069:
2070: /**
2071: * Returns the current environment.
2072: */
2073: public HashMap<String, Var> getEnv() {
2074: return _map;
2075: }
2076:
2077: /**
2078: * Returns the current environment.
2079: */
2080: public HashMap<String, Var> getGlobalEnv() {
2081: return _globalMap;
2082: }
2083:
2084: /**
2085: * Pushes a new environment.
2086: */
2087: public final Value[] setFunctionArgs(Value[] args) {
2088: Value[] oldArgs = _functionArgs;
2089:
2090: Value[] newArgs = new Value[args.length];
2091:
2092: for (int i = 0; args != null && i < args.length; i++) {
2093: // php/3715, 3768
2094: newArgs[i] = args[i].toValue().toArgValue();
2095: }
2096:
2097: _functionArgs = newArgs;
2098:
2099: return oldArgs;
2100: }
2101:
2102: /**
2103: * Pushes a new environment.
2104: */
2105: public final Value[] setFunctionArgsNoCopy(Value[] args) {
2106: Value[] oldArgs = _functionArgs;
2107:
2108: for (int i = 0; args != null && i < args.length; i++)
2109: args[i] = args[i].toValue();
2110:
2111: _functionArgs = args;
2112:
2113: return oldArgs;
2114: }
2115:
2116: /**
2117: * Pushes a new environment.
2118: */
2119: public final void restoreFunctionArgs(Value[] args) {
2120: _functionArgs = args;
2121: }
2122:
2123: /**
2124: * Returns the function args.
2125: */
2126: public final Value[] getFunctionArgs() {
2127: return _functionArgs;
2128: }
2129:
2130: /**
2131: * Removes a specialValue
2132: */
2133: public Object removeSpecialValue(String name) {
2134: return _specialMap.remove(name);
2135: }
2136:
2137: /**
2138: * Returns a constant.
2139: */
2140: public Value getConstant(String name) {
2141: Value value = getConstantImpl(name);
2142:
2143: if (value != null)
2144: return value;
2145:
2146: /* XXX:
2147: notice(L.l("Converting undefined constant '{0}' to string.",
2148: name));
2149: */
2150:
2151: value = createString(name);
2152:
2153: return value;
2154: }
2155:
2156: /**
2157: * Returns true if the constant is defined.
2158: */
2159: public boolean isDefined(String name) {
2160: return getConstantImpl(name) != null;
2161: }
2162:
2163: /**
2164: * Returns a constant.
2165: */
2166: private Value getConstantImpl(String name) {
2167: Value value = _constMap.get(name);
2168:
2169: if (value != null)
2170: return value;
2171:
2172: value = _quercus.getConstant(name);
2173: if (value != null)
2174: return value;
2175:
2176: if (_lowerConstMap != null) {
2177: value = _lowerConstMap.get(name.toLowerCase());
2178:
2179: if (value != null)
2180: return value;
2181: }
2182:
2183: return null;
2184: }
2185:
2186: /**
2187: * Removes a constant.
2188: */
2189: public Value removeConstant(String name) {
2190: return _constMap.remove(name);
2191: }
2192:
2193: /**
2194: * Sets a constant.
2195: */
2196: public Value addConstant(String name, Value value,
2197: boolean isCaseInsensitive) {
2198: Value oldValue = _constMap.get(name);
2199:
2200: if (oldValue != null)
2201: return oldValue;
2202:
2203: _constMap.put(name, value);
2204:
2205: if (_lowerConstMap != null && isCaseInsensitive)
2206: _lowerConstMap.put(name.toLowerCase(), value);
2207:
2208: return value;
2209: }
2210:
2211: /**
2212: * Returns an array of the defined functions.
2213: */
2214: public ArrayValue getDefinedConstants() {
2215: ArrayValue result = new ArrayValueImpl();
2216:
2217: for (Map.Entry<String, Value> entry : _quercus.getConstMap()
2218: .entrySet()) {
2219: result.put(createString(entry.getKey()), entry.getValue());
2220: }
2221:
2222: for (Map.Entry<String, Value> entry : _constMap.entrySet()) {
2223: result.put(createString(entry.getKey()), entry.getValue());
2224: }
2225:
2226: return result;
2227: }
2228:
2229: /**
2230: * Returns true if an extension is loaded.
2231: */
2232: public boolean isExtensionLoaded(String name) {
2233: return getQuercus().isExtensionLoaded(name);
2234: }
2235:
2236: /**
2237: * Returns true if an extension is loaded.
2238: */
2239: public HashSet<String> getLoadedExtensions() {
2240: return getQuercus().getLoadedExtensions();
2241: }
2242:
2243: /**
2244: * Returns true if an extension is loaded.
2245: */
2246: public Value getExtensionFuncs(String name) {
2247: return getQuercus().getExtensionFuncs(name);
2248: }
2249:
2250: /**
2251: * Returns the default stream resource.
2252: */
2253: public StreamContextResource getDefaultStreamContext() {
2254: if (_defaultStreamContext == null)
2255: _defaultStreamContext = new StreamContextResource();
2256:
2257: return _defaultStreamContext;
2258: }
2259:
2260: public ArrayValue getDefinedFunctions() {
2261: // return _defState.getDefinedFunctions();
2262: return new ArrayValueImpl();
2263: }
2264:
2265: /**
2266: * Returns the function with a given name.
2267: *
2268: * Compiled mode normally uses the _fun array directly, so this call
2269: * is rare.
2270: */
2271: public AbstractFunction findFunction(String name) {
2272: int id = _quercus.findFunctionId(name);
2273:
2274: if (id >= 0) {
2275: if (id < _fun.length
2276: && !(_fun[id] instanceof UndefinedFunction))
2277: return _fun[id];
2278: else
2279: return null;
2280: }
2281:
2282: AbstractFunction fun = _quercus.findFunctionImpl(name);
2283:
2284: if (fun != null)
2285: return fun;
2286:
2287: if (isStrict())
2288: return null;
2289:
2290: name = name.toLowerCase();
2291:
2292: id = _quercus.findFunctionId(name);
2293:
2294: if (id >= 0) {
2295: if (id < _fun.length
2296: && !(_fun[id] instanceof UndefinedFunction))
2297: return _fun[id];
2298: else
2299: return null;
2300: }
2301:
2302: return _quercus.findLowerFunctionImpl(name);
2303: }
2304:
2305: public AbstractFunction getFunction(String name) {
2306: AbstractFunction fun = findFunction(name);
2307:
2308: if (fun != null)
2309: return fun;
2310: else
2311: throw createErrorException(L.l(
2312: "'{0}' is an unknown function.", name));
2313: }
2314:
2315: /**
2316: * Finds the java reflection method for the function with the given name.
2317: *
2318: * @param name the method name
2319: * @return the found method or null if no method found.
2320: */
2321: public AbstractFunction getFunction(Value name) {
2322: name = name.toValue();
2323:
2324: if (name instanceof CallbackFunction)
2325: return ((CallbackFunction) name).getFunction();
2326:
2327: return getFunction(name.toString());
2328: }
2329:
2330: /*
2331: public DefinitionState getDefinitionState()
2332: {
2333: return _defState;
2334: }
2335: */
2336:
2337: public Value addFunction(String name, AbstractFunction fun) {
2338: AbstractFunction staticFun = _quercus
2339: .findLowerFunctionImpl(name.toLowerCase());
2340:
2341: if (staticFun != null)
2342: throw new QuercusException(L.l(
2343: "can't redefine function {0}", name));
2344:
2345: int id = _quercus.getFunctionId(name);
2346:
2347: // XXX: anonymous/generated functions(?), e.g. like foo2431
2348:
2349: if (_fun.length <= id) {
2350: AbstractFunction[] funMap = new AbstractFunction[id + 256];
2351: System.arraycopy(_fun, 0, funMap, 0, _fun.length);
2352: _fun = funMap;
2353: }
2354:
2355: if (_fun[id] != null
2356: && !(_fun[id] instanceof UndefinedFunction))
2357: throw new QuercusException(L.l(
2358: "can't redefine function {0}", name));
2359:
2360: _fun[id] = fun;
2361:
2362: return BooleanValue.TRUE;
2363: }
2364:
2365: /**
2366: * Adds a function from a compiled include
2367: *
2368: * @param name the function name, must be an intern() string
2369: * @param lowerName the function name, must be an intern() string
2370: */
2371: public Value addFunctionFromPage(String name, String lowerName,
2372: AbstractFunction fun) {
2373: // XXX: skip the old function check since the include for compiled
2374: // pages is already verified. Might have a switch here?
2375: /*
2376: AbstractFunction oldFun = _lowerFunMap.get(lowerName);
2377:
2378: if (oldFun == null)
2379: oldFun = _quercus.findLowerFunctionImpl(lowerName);
2380:
2381: if (oldFun != null) {
2382: throw new QuercusException(L.l("can't redefine function {0}", name));
2383: }
2384:
2385: _funMap.put(name, fun);
2386:
2387: if (! isStrict())
2388: _lowerFunMap.put(lowerName, fun);
2389: */
2390:
2391: return BooleanValue.TRUE;
2392: }
2393:
2394: /**
2395: * Finds the java reflection method for the function with the given name.
2396: *
2397: * @param className the class name
2398: * @param methodName the method name
2399: * @return the found method or null if no method found.
2400: */
2401: public AbstractFunction findMethod(String className,
2402: String methodName) {
2403: QuercusClass cl = findClass(className);
2404:
2405: if (cl == null) {
2406: error(L.l("'{0}' is an unknown class.", className));
2407: return null;
2408: }
2409:
2410: AbstractFunction fun = cl.findFunction(methodName);
2411:
2412: if (fun == null && !isStrict())
2413: fun = cl.findFunctionLowerCase(methodName.toLowerCase());
2414:
2415: if (fun == null) {
2416: error(L.l("'{0}::{1}' is an unknown method.", className,
2417: methodName));
2418: return null;
2419: }
2420:
2421: return fun;
2422: }
2423:
2424: /**
2425: * Compiles and calluates the given code
2426: *
2427: * @param code the code to calluate
2428: * @return the result
2429: */
2430: public Value evalCode(String code) throws IOException {
2431: if (log.isLoggable(Level.FINER))
2432: log.finer(code);
2433:
2434: Quercus quercus = getQuercus();
2435:
2436: QuercusProgram program = quercus.parseEvalExpr(code);
2437:
2438: Value value = program.execute(this );
2439:
2440: return value;
2441: }
2442:
2443: /**
2444: * Evaluates the named function.
2445: *
2446: * @param name the function name
2447: * @return the function value
2448: */
2449: public Value call(String name) {
2450: AbstractFunction fun = findFunction(name);
2451:
2452: if (fun == null)
2453: return error(L.l("'{0}' is an unknown function.", name));
2454:
2455: return fun.call(this );
2456: }
2457:
2458: /**
2459: * Evaluates the named function.
2460: *
2461: * @param name the function name
2462: * @param a0 the first argument
2463: * @return the function value
2464: */
2465: public Value call(String name, Value a0) {
2466: AbstractFunction fun = findFunction(name);
2467:
2468: if (fun == null)
2469: return error(L.l("'{0}' is an unknown function.", name));
2470:
2471: return fun.call(this , a0);
2472: }
2473:
2474: /**
2475: * Evaluates the named function.
2476: *
2477: * @param name the function name
2478: * @param a0 the first argument
2479: * @param a1 the second argument
2480: * @return the function value
2481: */
2482: public Value call(String name, Value a0, Value a1) {
2483: return getFunction(name).call(this , a0, a1);
2484: }
2485:
2486: /**
2487: * Evaluates the named function.
2488: *
2489: * @param name the function name
2490: * @param a0 the first argument
2491: * @param a1 the second argument
2492: * @param a2 the third argument
2493: * @return the function value
2494: */
2495: public Value call(String name, Value a0, Value a1, Value a2) {
2496: return getFunction(name).call(this , a0, a1, a2);
2497: }
2498:
2499: /**
2500: * Evaluates the named function.
2501: *
2502: * @param name the function name
2503: * @param a0 the first argument
2504: * @param a1 the second argument
2505: * @param a2 the third argument
2506: * @param a3 the fourth argument
2507: * @return the function value
2508: */
2509: public Value call(String name, Value a0, Value a1, Value a2,
2510: Value a3) {
2511: return getFunction(name).call(this , a0, a1, a2, a3);
2512: }
2513:
2514: /**
2515: * Evaluates the named function.
2516: *
2517: * @param name the function name
2518: * @param a0 the first argument
2519: * @param a1 the second argument
2520: * @param a2 the third argument
2521: * @param a3 the fourth argument
2522: * @param a4 the fifth argument
2523: * @return the function value
2524: */
2525: public Value call(String name, Value a0, Value a1, Value a2,
2526: Value a3, Value a4) {
2527: return getFunction(name).call(this , a0, a1, a2, a3, a4);
2528: }
2529:
2530: /**
2531: * Evaluates the named function.
2532: *
2533: * @param name the function name
2534: * @param args the arguments
2535: * @return the function value
2536: */
2537: public Value call(String name, Value[] args) {
2538: return getFunction(name).call(this , args);
2539: }
2540:
2541: /**
2542: * Evaluates the named function.
2543: *
2544: * @param name the function name
2545: * @return the function value
2546: */
2547: public Value callRef(String name) {
2548: AbstractFunction fun = findFunction(name);
2549:
2550: if (fun == null)
2551: return error(L.l("'{0}' is an unknown function.", name));
2552:
2553: return fun.callRef(this );
2554: }
2555:
2556: /**
2557: * EvalRefuates the named function.
2558: *
2559: * @param name the function name
2560: * @param a0 the first argument
2561: * @return the function value
2562: */
2563: public Value callRef(String name, Value a0) {
2564: AbstractFunction fun = findFunction(name);
2565:
2566: if (fun == null)
2567: return error(L.l("'{0}' is an unknown function.", name));
2568:
2569: return fun.callRef(this , a0);
2570: }
2571:
2572: /**
2573: * EvalRefuates the named function.
2574: *
2575: * @param name the function name
2576: * @param a0 the first argument
2577: * @param a1 the second argument
2578: * @return the function value
2579: */
2580: public Value callRef(String name, Value a0, Value a1) {
2581: AbstractFunction fun = findFunction(name);
2582:
2583: if (fun == null)
2584: return error(L.l("'{0}' is an unknown function.", name));
2585:
2586: return fun.callRef(this , a0, a1);
2587: }
2588:
2589: /**
2590: * EvalRefuates the named function.
2591: *
2592: * @param name the function name
2593: * @param a0 the first argument
2594: * @param a1 the second argument
2595: * @param a2 the third argument
2596: * @return the function value
2597: */
2598: public Value callRef(String name, Value a0, Value a1, Value a2) {
2599: AbstractFunction fun = findFunction(name);
2600:
2601: if (fun == null)
2602: return error(L.l("'{0}' is an unknown function.", name));
2603:
2604: return fun.callRef(this , a0, a1, a2);
2605: }
2606:
2607: /**
2608: * Evaluates the named function.
2609: *
2610: * @param name the function name
2611: * @param a0 the first argument
2612: * @param a1 the second argument
2613: * @param a2 the third argument
2614: * @param a3 the fourth argument
2615: * @return the function value
2616: */
2617: public Value callRef(String name, Value a0, Value a1, Value a2,
2618: Value a3) {
2619: AbstractFunction fun = findFunction(name);
2620:
2621: if (fun == null)
2622: return error(L.l("'{0}' is an unknown function.", name));
2623:
2624: return fun.callRef(this , a0, a1, a2, a3);
2625: }
2626:
2627: /**
2628: * Evaluates the named function.
2629: *
2630: * @param name the function name
2631: * @param a0 the first argument
2632: * @param a1 the second argument
2633: * @param a2 the third argument
2634: * @param a3 the fourth argument
2635: * @param a4 the fifth argument
2636: * @return the function value
2637: */
2638: public Value callRef(String name, Value a0, Value a1, Value a2,
2639: Value a3, Value a4) {
2640: AbstractFunction fun = findFunction(name);
2641:
2642: if (fun == null)
2643: return error(L.l("'{0}' is an unknown function.", name));
2644:
2645: return fun.callRef(this , a0, a1, a2, a3, a4);
2646: }
2647:
2648: /**
2649: * Evaluates the named function.
2650: *
2651: * @param name the function name
2652: * @param args the arguments
2653: * @return the function value
2654: */
2655: public Value callRef(String name, Value[] args) {
2656: AbstractFunction fun = findFunction(name);
2657:
2658: if (fun == null)
2659: return error(L.l("'{0}' is an unknown function.", name));
2660:
2661: return fun.callRef(this , args);
2662: }
2663:
2664: /**
2665: * Adds a class, e.g. from an include.
2666: */
2667: public void addClassDef(String name, ClassDef cl) {
2668: int id = _quercus.getClassId(name);
2669:
2670: if (_classDef.length <= id) {
2671: ClassDef[] def = new ClassDef[id + 256];
2672: System.arraycopy(_classDef, 0, def, 0, _classDef.length);
2673: _classDef = def;
2674: }
2675:
2676: _classDef[id] = cl;
2677: }
2678:
2679: public ClassDef findClassDef(String name) {
2680: int id = _quercus.getClassId(name);
2681:
2682: if (id < _classDef.length)
2683: return _classDef[id];
2684: else
2685: return null;
2686: }
2687:
2688: /**
2689: * Creates a stdClass object.
2690: */
2691: public ObjectValue createObject() {
2692: try {
2693: return (ObjectValue) _quercus.getStdClass().callNew(this ,
2694: EMPTY_VALUE);
2695: } catch (Exception e) {
2696: throw new QuercusModuleException(e);
2697: }
2698: }
2699:
2700: /*
2701: * Creates an empty string.
2702: */
2703: public StringValue createEmptyString() {
2704: if (_isUnicodeSemantics)
2705: return UnicodeBuilderValue.EMPTY;
2706: else
2707: return StringBuilderValue.EMPTY;
2708: }
2709:
2710: /**
2711: * Creates a PHP string from a byte buffer.
2712: */
2713: public StringValue createString(byte[] buffer, int offset,
2714: int length) {
2715: if (_isUnicodeSemantics)
2716: return new UnicodeValueImpl(new String(buffer, offset,
2717: length));
2718: else
2719: return new StringBuilderValue(buffer, offset, length);
2720: }
2721:
2722: /**
2723: * Creates a PHP string from a byte buffer.
2724: */
2725: public StringValue createString(char[] buffer, int length) {
2726: if (_isUnicodeSemantics)
2727: return new UnicodeBuilderValue(buffer, length);
2728: else
2729: return new StringBuilderValue(buffer, 0, length);
2730: }
2731:
2732: /**
2733: * Creates a PHP string from a char buffer.
2734: */
2735: public StringValue createString(char[] buffer, int offset,
2736: int length) {
2737: if (_isUnicodeSemantics)
2738: return new UnicodeBuilderValue(buffer, offset, length);
2739: else
2740: return new StringBuilderValue(buffer, offset, length);
2741: }
2742:
2743: /**
2744: * Creates a PHP string from a java String.
2745: */
2746: public StringValue createString(String s) {
2747: if (s == null) {
2748: return (_isUnicodeSemantics ? UnicodeBuilderValue.EMPTY
2749: : StringBuilderValue.EMPTY);
2750: } else if (_isUnicodeSemantics)
2751: return new UnicodeBuilderValue(s);
2752: else
2753: return new StringBuilderValue(s);
2754: }
2755:
2756: /**
2757: * Creates a string from a byte.
2758: */
2759: public StringValue createString(char ch) {
2760: // XXX: create static cache for this
2761:
2762: if (_isUnicodeSemantics)
2763: return new UnicodeValueImpl(String.valueOf(ch));
2764: else
2765: return new StringBuilderValue(String.valueOf(ch));
2766: }
2767:
2768: /**
2769: * Creates a PHP string from a buffer.
2770: */
2771: public StringValue createBinaryString(TempBuffer head) {
2772: StringValue string;
2773:
2774: if (_isUnicodeSemantics)
2775: string = new BinaryBuilderValue();
2776: else
2777: string = new StringBuilderValue();
2778:
2779: for (; head != null; head = head.getNext()) {
2780: string.append(head.getBuffer(), 0, head.getLength());
2781: }
2782:
2783: return string;
2784: }
2785:
2786: /**
2787: * Creates a PHP Exception.
2788: */
2789: public Value createException(Exception e) {
2790: QuercusClass cls = findClass("Exception");
2791:
2792: StringValue message = createString(e.getMessage());
2793: Value[] args = { message };
2794:
2795: Value value = cls.callNew(this , args);
2796:
2797: StackTraceElement elt = e.getStackTrace()[0];
2798:
2799: value.putField(this , "file", createString(elt.getFileName()));
2800: value.putField(this , "line", LongValue.create(elt
2801: .getLineNumber()));
2802: value
2803: .putField(this , "trace", ErrorModule
2804: .debug_backtrace(this ));
2805:
2806: return value;
2807: }
2808:
2809: /**
2810: * Generate an object id.
2811: */
2812: public int generateId() {
2813: return ++_objectId;
2814: }
2815:
2816: /**
2817: * Returns an introspected Java class defintion.
2818: */
2819: public JavaClassDef getJavaClassDefinition(String className) {
2820: JavaClassDef def = getJavaClassDefinition(className, true);
2821:
2822: if (def != null)
2823: return def;
2824: else
2825: throw createErrorException(L.l(
2826: "'{0}' class definition not found", className));
2827: }
2828:
2829: /*
2830: * Returns an introspected Java class definition.
2831: */
2832: public JavaClassDef getJavaClassDefinition(Class type) {
2833: JavaClassDef def = _quercus.getJavaClassDefinition(type, type
2834: .getName());
2835:
2836: def.init();
2837:
2838: return def;
2839: }
2840:
2841: private JavaClassDef getJavaClassDefinition(String className,
2842: boolean useImport) {
2843: JavaClassDef def = null;
2844:
2845: try {
2846: def = _quercus.getJavaClassDefinition(className);
2847: } catch (Throwable e) {
2848: if (useImport) {
2849: def = importJavaClass(className);
2850: } else
2851: log.log(Level.FINER, e.toString(), e);
2852:
2853: }
2854:
2855: if (def != null)
2856: def.init();
2857:
2858: return def;
2859: }
2860:
2861: /**
2862: * Imports a Java class.
2863: *
2864: * @param className name of class to import
2865: * @return class definition of imported class, null if class not found
2866: */
2867: public JavaClassDef importJavaClass(String className) {
2868: if (_importMap == null)
2869: return null;
2870:
2871: String fullName = _importMap.getQualified(className);
2872:
2873: if (fullName != null) {
2874: return getJavaClassDefinition(fullName, false);
2875: } else {
2876: ArrayList<String> wildcardList = _importMap
2877: .getWildcardList();
2878:
2879: for (String entry : wildcardList) {
2880: fullName = entry + '.' + className;
2881:
2882: JavaClassDef def = getJavaClassDefinition(fullName,
2883: false);
2884:
2885: if (def != null) {
2886: _importMap.putQualified(className, fullName);
2887: return def;
2888: }
2889: }
2890: }
2891:
2892: return null;
2893: }
2894:
2895: /**
2896: * Adds a Quercus class import.
2897: *
2898: * @param javaName fully qualified class import string
2899: */
2900: public void putQualifiedImport(String javaName) {
2901: if (_importMap == null)
2902: _importMap = new ImportMap();
2903:
2904: String phpName = _importMap.putQualified(javaName);
2905: }
2906:
2907: /**
2908: * Adds a Quercus class import.
2909: *
2910: * @param name wildcard class import string minus '*' at the end (i.e. java.util.)
2911: */
2912: public void addWildcardImport(String name) {
2913: if (_importMap == null)
2914: _importMap = new ImportMap();
2915:
2916: _importMap.addWildcardImport(name);
2917: }
2918:
2919: /**
2920: * Returns a PHP value for a Java object
2921: */
2922: public Value wrapJava(Object obj) {
2923: return wrapJava(obj, null, false);
2924: }
2925:
2926: /**
2927: * Returns a PHP value for a Java object
2928: *
2929: * @param isNullAsFalse what to return if <i>obj</i> is null, if true return
2930: * {@link BooleanValue.FALSE} otherwise return {@link NullValue.NULL)
2931: */
2932: public Value wrapJava(Object obj, boolean isNullAsFalse) {
2933: return wrapJava(obj, null, isNullAsFalse);
2934: }
2935:
2936: /**
2937: * Returns a PHP value for a Java object
2938: *
2939: * @param isNullAsFalse what to return if <i>obj</i> is null, if true return
2940: * {@link BooleanValue.FALSE} otherwise return {@link NullValue.NULL)
2941: */
2942: public Value wrapJava(Object obj, JavaClassDef def,
2943: boolean isNullAsFalse) {
2944: if (obj == null) {
2945: if (isNullAsFalse)
2946: return BooleanValue.FALSE;
2947: else
2948: return NullValue.NULL;
2949: }
2950:
2951: if (obj instanceof Value)
2952: return (Value) obj;
2953:
2954: if (def == null)
2955: def = getJavaClassDefinition(obj.getClass());
2956: else if (def.getType() != obj.getClass()) {
2957: // XXX: what if types are incompatible, does it matter?
2958: // if it doesn't matter, simplify this to one if with no else
2959: def = getJavaClassDefinition(obj.getClass());
2960: }
2961:
2962: if (def.isArray()) {
2963: ArrayValueImpl arrayValueImpl = new ArrayValueImpl();
2964:
2965: Class componentClass = def.getType().getComponentType();
2966:
2967: MarshalFactory factory = _quercus.getModuleContext()
2968: .getMarshalFactory();
2969: Marshal componentClassMarshal = factory
2970: .create(componentClass);
2971:
2972: int length = Array.getLength(obj);
2973:
2974: for (int i = 0; i < length; i++) {
2975: arrayValueImpl.put(componentClassMarshal.unmarshal(
2976: this , Array.get(obj, i)));
2977: }
2978:
2979: return arrayValueImpl;
2980: } else {
2981: return def.wrap(this , obj);
2982: }
2983: }
2984:
2985: /**
2986: * Finds the class with the given name.
2987: *
2988: * @param name the class name
2989: * @return the found class or null if no class found.
2990: */
2991: public QuercusClass findClass(String name) {
2992: return findClass(name, true);
2993: }
2994:
2995: /**
2996: * Finds the class with the given name.
2997: *
2998: * @param name the class name
2999: * @param useAutoload use autoload to locate the class if necessary
3000: * @return the found class or null if no class found.
3001: */
3002: public QuercusClass findClass(String name, boolean useAutoload) {
3003: QuercusClass cl = _classMap.get(name);
3004:
3005: if (cl != null)
3006: return cl;
3007:
3008: cl = _lowerClassMap.get(name.toLowerCase());
3009:
3010: if (cl != null)
3011: return cl;
3012:
3013: cl = createClassImpl(name, useAutoload, true);
3014:
3015: if (cl != null) {
3016: _classMap.put(cl.getName(), cl);
3017: _lowerClassMap.put(cl.getName().toLowerCase(), cl);
3018:
3019: // php/09b7
3020: cl.init(this );
3021:
3022: return cl;
3023: } else
3024: return null;
3025: }
3026:
3027: /**
3028: * Finds the class with the given name.
3029: *
3030: * @param name the class name
3031: * @param useAutoload use autoload to locate the class if necessary
3032: * @param useImport import the class if necessary
3033: *
3034: * @return the found class or null if no class found.
3035: */
3036: private QuercusClass createClassImpl(String name,
3037: boolean useAutoload, boolean useImport) {
3038: int id = _quercus.getClassId(name);
3039:
3040: ClassDef classDef = _classDef[id];
3041:
3042: if (classDef != null) {
3043: String parentName = classDef.getParentName();
3044:
3045: QuercusClass parent = null;
3046:
3047: if (parentName != null)
3048: parent = findClass(parentName);
3049:
3050: if (parentName == null || parent instanceof QuercusClass)
3051: return createQuercusClass(classDef,
3052: (QuercusClass) parent);
3053: else
3054: return null; // php/
3055: }
3056:
3057: ClassDef staticClass = _quercus.findClass(name);
3058:
3059: if (staticClass != null)
3060: return createQuercusClass(staticClass, null); // XXX: cache
3061:
3062: if (useAutoload) {
3063: if (!_autoloadClasses.contains(name)) {
3064: try {
3065: _autoloadClasses.add(name);
3066:
3067: if (_autoloadFunctionMap != null) {
3068: for (Map.Entry<String, AbstractFunction> entry : _autoloadFunctionMap
3069: .entrySet()) {
3070: entry.getValue().call(this ,
3071: new StringBuilderValue(name));
3072:
3073: QuercusClass cls = createClassImpl(name,
3074: false, useImport);
3075:
3076: if (cls != null)
3077: break;
3078: }
3079: } else {
3080: if (_autoload == null)
3081: _autoload = findFunction("__autoload");
3082:
3083: if (_autoload != null) {
3084: _autoload.call(this ,
3085: new StringBuilderValue(name));
3086:
3087: return createClassImpl(name, false,
3088: useImport);
3089: }
3090: }
3091: } finally {
3092: _autoloadClasses.remove(name);
3093: }
3094: }
3095: }
3096:
3097: if (useImport) {
3098: if (importPhpClass(name)) {
3099: return createClassImpl(name, false, false);
3100: } else {
3101: try {
3102: JavaClassDef javaClassDef = getJavaClassDefinition(
3103: name, true);
3104:
3105: if (javaClassDef != null)
3106: return createQuercusClass(javaClassDef, null);
3107: } catch (Exception e) {
3108: log.log(Level.FINER, e.toString(), e);
3109: }
3110: }
3111: }
3112:
3113: return null;
3114: }
3115:
3116: /*
3117: * Registers an SPL autoload function.
3118: */
3119: public void addAutoloadFunction(String name) {
3120: if (_autoloadFunctionMap == null)
3121: _autoloadFunctionMap = new LinkedHashMap<String, AbstractFunction>();
3122:
3123: _autoloadFunctionMap.put(name, getFunction(name));
3124: }
3125:
3126: /*
3127: * Unregisters an SPL autoload function.
3128: */
3129: public void removeAutoloadFunction(String fun) {
3130: if (_autoloadFunctionMap != null) {
3131: _autoloadFunctionMap.remove(fun);
3132:
3133: //restore original __autoload functionality
3134: if (_autoloadFunctionMap.size() == 0)
3135: _autoloadFunctionMap = null;
3136: }
3137: }
3138:
3139: /*
3140: * Returns the registered SPL autoload functions.
3141: */
3142: public LinkedHashMap<String, AbstractFunction> getAutoloadFunctions() {
3143: return _autoloadFunctionMap;
3144: }
3145:
3146: /**
3147: * Imports a PHP class.
3148: *
3149: * @param name of the PHP class
3150: *
3151: * @return true if matching php file was found and included.
3152: */
3153: public boolean importPhpClass(String name) {
3154: if (_importMap == null)
3155: return false;
3156:
3157: String fullName = _importMap.getQualifiedPhp(name);
3158:
3159: URL url = null;
3160: ClassLoader loader = Thread.currentThread()
3161: .getContextClassLoader();
3162:
3163: if (fullName != null) {
3164: url = loader.getResource(fullName);
3165: } else {
3166: for (String entry : _importMap.getWildcardPhpList()) {
3167:
3168: url = loader.getResource(entry + '/' + name + ".php");
3169:
3170: if (url != null)
3171: break;
3172: }
3173: }
3174:
3175: if (url != null) {
3176: includeOnce(url.toString());
3177: return true;
3178: } else {
3179: return false;
3180: }
3181: }
3182:
3183: /**
3184: * Returns the declared classes.
3185: *
3186: * @return an array of the declared classes()
3187: */
3188: public Value getDeclaredClasses() {
3189: // return _defState.getDeclaredClasses(this);
3190: return NullValue.NULL;
3191: }
3192:
3193: /**
3194: * Finds the class with the given name.
3195: *
3196: * @param name the class name
3197: * @return the found class or null if no class found.
3198: */
3199: public QuercusClass findAbstractClass(String name) {
3200: QuercusClass cl = findClass(name, true);
3201:
3202: if (cl != null)
3203: return cl;
3204:
3205: throw createErrorException(L.l(
3206: "'{0}' is an unknown class name.", name));
3207: /*
3208: // return _quercus.findJavaClassWrapper(name);
3209:
3210: return null;
3211: */
3212: }
3213:
3214: /**
3215: * Finds the class with the given name.
3216: *
3217: * @param name the class name
3218: * @return the found class
3219: * @throws QuercusRuntimeException if the class is not found
3220: */
3221: public QuercusClass getClass(String name) {
3222: QuercusClass cl = findClass(name);
3223:
3224: if (cl != null)
3225: return cl;
3226: else
3227: throw createErrorException(L.l(
3228: "'{0}' is an unknown class.", name));
3229: }
3230:
3231: QuercusClass createQuercusClass(ClassDef def, QuercusClass parent) {
3232: ClassKey key = new ClassKey(def, parent);
3233:
3234: SoftReference<QuercusClass> qClassRef = _classCache.get(key);
3235: QuercusClass qClass;
3236:
3237: if (qClassRef != null) {
3238: qClass = qClassRef.get();
3239:
3240: if (qClass != null) {
3241: return qClass;
3242: }
3243: }
3244:
3245: qClass = new QuercusClass(getModuleContext(), def, parent);
3246: qClass.validate(this );
3247:
3248: _classCache.put(key, new SoftReference<QuercusClass>(qClass));
3249:
3250: return qClass;
3251: }
3252:
3253: /**
3254: * Returns true if class has already been initialized.
3255: */
3256: public boolean isInitializedClass(String name) {
3257: return _initializedClassSet.contains(name);
3258: }
3259:
3260: /**
3261: * Mark this class as being initialized.
3262: */
3263: public void addInitializedClass(String name) {
3264: _initializedClassSet.add(name);
3265: }
3266:
3267: /**
3268: * Finds the class and method.
3269: *
3270: * @param className the class name
3271: * @param methodName the method name
3272: * @return the found method or null if no method found.
3273: */
3274: public AbstractFunction findFunction(String className,
3275: String methodName) {
3276: QuercusClass cl = findClass(className);
3277:
3278: if (cl == null)
3279: throw new QuercusRuntimeException(L.l(
3280: "'{0}' is an unknown class", className));
3281:
3282: return cl.findFunction(methodName);
3283: }
3284:
3285: /**
3286: * Returns the appropriate callback.
3287: */
3288: public Callback createCallback(Value value) {
3289: if (value == null || value.isNull())
3290: return null;
3291:
3292: value = value.toValue();
3293:
3294: if (value instanceof Callback)
3295: return (Callback) value;
3296:
3297: else if (value instanceof StringValue)
3298: return new CallbackFunction(this , value.toString());
3299:
3300: else if (value instanceof ArrayValue) {
3301: Value obj = value.get(LongValue.ZERO);
3302: Value name = value.get(LongValue.ONE);
3303:
3304: if (!(name instanceof StringValue))
3305: throw new IllegalStateException(L.l(
3306: "unknown callback name {0}", name));
3307:
3308: if (obj instanceof StringValue) {
3309: QuercusClass cl = findClass(obj.toString());
3310:
3311: if (cl == null)
3312: throw new IllegalStateException(L.l(
3313: "can't find class {0}", obj.toString()));
3314:
3315: return new CallbackFunction(cl.getFunction(name
3316: .toString()));
3317: } else {
3318: return new CallbackObjectMethod(this , obj, name
3319: .toString());
3320: }
3321: } else
3322: return null;
3323: }
3324:
3325: /**
3326: * Evaluates an included file.
3327: */
3328: public Value requireOnce(String include) {
3329: return include(getSelfDirectory(), include, true, true);
3330: }
3331:
3332: /**
3333: * Evaluates an included file.
3334: */
3335: public Value require(String include) {
3336: return include(getSelfDirectory(), include, true, false);
3337: }
3338:
3339: /**
3340: * Evaluates an included file.
3341: */
3342: public Value include(String include) {
3343: return include(getSelfDirectory(), include, false, false);
3344: }
3345:
3346: /**
3347: * Evaluates an included file.
3348: */
3349: public Value includeOnce(String include) {
3350: return include(getSelfDirectory(), include, false, true);
3351: }
3352:
3353: /**
3354: * Evaluates an included file.
3355: */
3356: public Value includeOnce(Path scriptPwd, String include,
3357: boolean isRequire) {
3358: return include(scriptPwd, include, isRequire, true);
3359: }
3360:
3361: /**
3362: * Evaluates an included file.
3363: */
3364: public Value include(Path scriptPwd, String include,
3365: boolean isRequire, boolean isOnce) {
3366: try {
3367: Path pwd = getPwd();
3368:
3369: Path path = lookupInclude(include, pwd, scriptPwd);
3370:
3371: if (path != null) {
3372: } else if (isRequire) {
3373: error(L.l("'{0}' is not a valid path", include));
3374: return NullValue.NULL;
3375: } else {
3376: warning(L.l("'{0}' is not a valid path", include));
3377: return NullValue.NULL;
3378: }
3379:
3380: // php/0b2d
3381: if (!"".equals(path.getScheme())
3382: && !"file".equals(path.getScheme())
3383: && !"memory".equals(path.getScheme())) {
3384: String msg = (L.l("attempt to include {0}", path
3385: .getURL()));
3386:
3387: log.warning(dbgId() + msg);
3388: error(msg);
3389:
3390: return NullValue.NULL;
3391: }
3392:
3393: QuercusPage page = _includeMap.get(path);
3394:
3395: if (page == null || page.isModified(this )) {
3396: page = _quercus.parse(path);
3397:
3398: page.importDefinitions(this );
3399:
3400: _includeMap.put(path, page);
3401: } else if (isOnce)
3402: return NullValue.NULL;
3403:
3404: return page.execute(this );
3405: } catch (IOException e) {
3406: throw new QuercusModuleException(e);
3407: }
3408: }
3409:
3410: /**
3411: * Looks up based on the pwd.
3412: */
3413: public Path lookupPwd(Value relPathV) {
3414: if (!relPathV.isset())
3415: return null;
3416:
3417: StringValue relPath = relPathV.toStringValue();
3418:
3419: if (relPath.length() == 0)
3420: return null;
3421:
3422: Path path = _lookupCache.get(relPath);
3423:
3424: if (path == null) {
3425: path = getPwd().lookup(relPath.toString());
3426: _lookupCache.put(relPath, path);
3427: }
3428:
3429: return path;
3430: }
3431:
3432: /**
3433: * Looks up the path.
3434: */
3435: public Path lookup(String relPath) {
3436: return lookupInclude(getSelfDirectory(), relPath);
3437: }
3438:
3439: /**
3440: * Looks up the path.
3441: */
3442: public Path lookupInclude(String relPath) {
3443: return lookupInclude(relPath, getPwd(), getSelfDirectory());
3444: }
3445:
3446: private Path lookupInclude(String include, Path pwd, Path scriptPwd) {
3447: String includePath = getDefaultIncludePath();
3448:
3449: Path path = _quercus.getIncludeCache(include, includePath, pwd,
3450: scriptPwd);
3451:
3452: if (path == null) {
3453: path = lookupIncludeImpl(include, pwd, scriptPwd);
3454:
3455: if (path != null)
3456: _quercus.putIncludeCache(include, includePath, pwd,
3457: scriptPwd, path);
3458: }
3459:
3460: _includePath = includePath;
3461: _includePathIniCount = _iniCount;
3462:
3463: return path;
3464: }
3465:
3466: private String getDefaultIncludePath() {
3467: String includePath = _includePath;
3468:
3469: if (_includePathIniCount != _iniCount) {
3470: includePath = Quercus.INI_INCLUDE_PATH.getAsString(this );
3471: _includePath = null;
3472: _includePathList = null;
3473: }
3474:
3475: if (includePath == null)
3476: includePath = ".";
3477:
3478: return includePath;
3479: }
3480:
3481: private Path lookupIncludeImpl(String include, Path pwd,
3482: Path scriptPwd) {
3483: // php/0b0g
3484:
3485: Path path = lookupInclude(pwd, include);
3486:
3487: if (path == null) {
3488: // php/0b0l
3489: path = lookupInclude(scriptPwd, include);
3490: }
3491:
3492: if (path == null) {
3493: // php/0b21
3494: path = scriptPwd.lookup(include);
3495:
3496: if (!path.canRead() || path.isDirectory())
3497: path = null;
3498: }
3499:
3500: return path;
3501: }
3502:
3503: /**
3504: * Looks up the path.
3505: */
3506: private Path lookupInclude(Path pwd, String relPath) {
3507: ArrayList<Path> pathList = getIncludePath(pwd);
3508:
3509: for (int i = 0; i < pathList.size(); i++) {
3510: Path path = pathList.get(i).lookup(relPath);
3511:
3512: if (path.canRead() && !path.isDirectory()) {
3513: return path;
3514: }
3515: }
3516:
3517: return null;
3518: }
3519:
3520: /**
3521: * Returns the include path.
3522: */
3523: private ArrayList<Path> getIncludePath(Path pwd) {
3524: String includePath = getDefaultIncludePath();
3525:
3526: if (_includePathList == null) {
3527: _includePathList = new ArrayList<String>();
3528: _includePathMap = new HashMap<Path, ArrayList<Path>>();
3529:
3530: int head = 0;
3531: int tail;
3532:
3533: String pathSeparator = FileModule.PATH_SEPARATOR;
3534: int length = pathSeparator.length();
3535:
3536: while ((tail = includePath.indexOf(pathSeparator, head)) >= 0) {
3537: String subpath = includePath.substring(head, tail);
3538:
3539: _includePathList.add(subpath);
3540:
3541: head = tail + length;
3542: }
3543:
3544: String subpath = includePath.substring(head);
3545:
3546: _includePathList.add(subpath);
3547:
3548: _includePath = includePath;
3549: _includePathIniCount = _iniCount;
3550: }
3551:
3552: ArrayList<Path> pathList = _includePathMap.get(pwd);
3553:
3554: if (pathList == null) {
3555: pathList = new ArrayList<Path>();
3556:
3557: for (int i = 0; i < _includePathList.size(); i++) {
3558: pathList.add(pwd.lookup(_includePathList.get(i)));
3559: }
3560:
3561: _includePathMap.put(pwd, pathList);
3562: }
3563:
3564: return pathList;
3565: }
3566:
3567: /**
3568: * Sets the include path.
3569: */
3570: public String setIncludePath(String path) {
3571: String prevIncludePath = Quercus.INI_INCLUDE_PATH
3572: .getAsString(this );
3573:
3574: if (_defaultIncludePath == null)
3575: _defaultIncludePath = prevIncludePath;
3576:
3577: Quercus.INI_INCLUDE_PATH.set(this , path);
3578:
3579: // reset include path cache count
3580: _includePathIniCount = -1;
3581:
3582: return prevIncludePath;
3583: }
3584:
3585: /**
3586: * Restores the default include path.
3587: */
3588: public void restoreIncludePath() {
3589: Quercus.INI_INCLUDE_PATH.set(this , _defaultIncludePath);
3590: }
3591:
3592: /**
3593: * Returns all the included files.
3594: */
3595: public ArrayValue getIncludedFiles() {
3596: ArrayValue array = new ArrayValueImpl();
3597:
3598: for (Path path : _includeMap.keySet()) {
3599: array.put(createString(path.toString()));
3600: }
3601:
3602: return array;
3603: }
3604:
3605: /**
3606: * Handles error suppression.
3607: */
3608: public Value suppress(int errorMask, Value value) {
3609: setErrorMask(errorMask);
3610:
3611: return value;
3612: }
3613:
3614: /**
3615: * Handles exit/die
3616: */
3617: public Value exit(Value msg) {
3618: if (msg.isNull() || msg instanceof LongValue)
3619: return exit();
3620:
3621: try {
3622: getOut().print(msg.toString());
3623: } catch (IOException e) {
3624: log.log(Level.WARNING, e.toString(), e);
3625: }
3626:
3627: throw new QuercusExitException(msg.toString());
3628: }
3629:
3630: /**
3631: * Handles exit/die
3632: */
3633: public Value exit() {
3634: throw new QuercusExitException();
3635: }
3636:
3637: /**
3638: * Handles exit/die
3639: */
3640: public Value die(String msg) {
3641: try {
3642: getOut().print(msg);
3643: } catch (IOException e) {
3644: log.log(Level.WARNING, e.toString(), e);
3645: }
3646:
3647: throw new QuercusDieException(msg);
3648: }
3649:
3650: /**
3651: * Handles exit/die
3652: */
3653: public Value die() {
3654: throw new QuercusDieException();
3655: }
3656:
3657: /**
3658: * Handles exit/die
3659: */
3660: public Value cast(Class cl, Value value) {
3661: value = value.toValue();
3662:
3663: if (value.isNull())
3664: return null;
3665: else if (cl.isAssignableFrom(value.getClass()))
3666: return value;
3667: else {
3668: error(L.l("{0} ({1}) is not assignable to {2}", value,
3669: value.getClass().getName(), cl.getName()));
3670:
3671: return value;
3672: }
3673: }
3674:
3675: /**
3676: * Returns the first value
3677: */
3678: public static Value first(Value value) {
3679: return value;
3680: }
3681:
3682: /**
3683: * Returns the first value
3684: */
3685: public static Value first(Value value, Value a1) {
3686: return value;
3687: }
3688:
3689: /**
3690: * Returns the first value
3691: */
3692: public static Value first(Value value, Value a1, Value a2) {
3693: return value;
3694: }
3695:
3696: /**
3697: * Returns the first value
3698: */
3699: public static Value first(Value value, Value a1, Value a2, Value a3) {
3700: return value;
3701: }
3702:
3703: /**
3704: * Returns the first value
3705: */
3706: public static Value first(Value value, Value a1, Value a2,
3707: Value a3, Value a4) {
3708: return value;
3709: }
3710:
3711: /**
3712: * Returns the first value
3713: */
3714: public static Value first(Value value, Value a1, Value a2,
3715: Value a3, Value a4, Value a5) {
3716: return value;
3717: }
3718:
3719: /**
3720: * A fatal runtime error.
3721: */
3722: public Value error(String msg) {
3723: return error(B_ERROR, "", msg + getFunctionLocation());
3724: }
3725:
3726: /**
3727: * A fatal runtime error.
3728: */
3729: public Value error(Location location, String msg) {
3730: return error(B_ERROR, location, msg + getFunctionLocation());
3731: }
3732:
3733: /**
3734: * A fatal runtime error.
3735: */
3736: public Value error(String loc, String msg) {
3737: return error(B_ERROR, loc, msg + getFunctionLocation());
3738: }
3739:
3740: /**
3741: * A warning with an exception.
3742: */
3743: public Value error(String msg, Throwable e) {
3744: log.log(Level.WARNING, e.toString(), e);
3745:
3746: return error(msg);
3747: }
3748:
3749: /**
3750: * A warning with an exception.
3751: */
3752: public Value error(Throwable e) {
3753: log.log(Level.WARNING, e.toString(), e);
3754:
3755: return error(e.toString());
3756: }
3757:
3758: /**
3759: * A fatal runtime error.
3760: */
3761: public QuercusRuntimeException createErrorException(String msg)
3762: throws QuercusRuntimeException {
3763: return createErrorException(null, msg);
3764: }
3765:
3766: /**
3767: * A fatal runtime error.
3768: */
3769: public QuercusRuntimeException createErrorException(
3770: Location location, String msg)
3771: throws QuercusRuntimeException {
3772: if (location == null)
3773: location = getLocation();
3774:
3775: String prefix = location.getMessagePrefix();
3776:
3777: String fullMsg = msg + getFunctionLocation();
3778:
3779: error(B_ERROR, location, fullMsg);
3780:
3781: String exMsg = prefix + fullMsg;
3782:
3783: return new QuercusRuntimeException(fullMsg);
3784: }
3785:
3786: /**
3787: * A runtime warning.
3788: */
3789: public Value warning(String msg) {
3790: if (log.isLoggable(Level.FINER)) {
3791: QuercusException e = new QuercusException(msg);
3792:
3793: log.log(Level.FINER, e.toString(), e);
3794: }
3795:
3796: return error(B_WARNING, "", msg + getFunctionLocation());
3797: }
3798:
3799: /**
3800: * A runtime warning.
3801: */
3802: public Value warning(Location location, String msg) {
3803: if (log.isLoggable(Level.FINER)) {
3804: QuercusException e = new QuercusException(msg);
3805:
3806: log.log(Level.FINER, e.toString(), e);
3807: }
3808:
3809: return error(B_WARNING, location, "", msg
3810: + getFunctionLocation());
3811: }
3812:
3813: /**
3814: * A warning with an exception.
3815: */
3816: public Value warning(String msg, Throwable e) {
3817: log.log(Level.FINE, e.toString(), e);
3818:
3819: return warning(msg);
3820: }
3821:
3822: /**
3823: * A warning with an exception.
3824: */
3825: public Value warning(Location location, String msg, Throwable e) {
3826: log.log(Level.FINE, e.toString(), e);
3827:
3828: return warning(location, msg);
3829: }
3830:
3831: /**
3832: * A warning with an exception.
3833: */
3834: public Value warning(Throwable e) {
3835: return warning(e.toString(), e);
3836: }
3837:
3838: /**
3839: * A warning with an exception.
3840: */
3841: public Value warning(Location location, Throwable e) {
3842: return warning(location, e.toString(), e);
3843: }
3844:
3845: /**
3846: * A runtime strict warning.
3847: */
3848: public Value strict(String msg) {
3849: if (log.isLoggable(Level.FINER)) {
3850: QuercusException e = new QuercusException(msg);
3851:
3852: log.log(Level.FINER, e.toString(), e);
3853: }
3854:
3855: return error(B_STRICT, "", msg + getFunctionLocation());
3856: }
3857:
3858: /**
3859: * A warning about an invalid argument passed to a function.
3860: */
3861: public Value invalidArgument(String name, Object value) {
3862: return warning(L
3863: .l("invalid value `{0}' for `{1}'", value, name));
3864: }
3865:
3866: /**
3867: * A warning about an deprecated argument passed to a function.
3868: */
3869: public Value deprecatedArgument(String name) {
3870: return strict(L.l("argument `{1}' is deprecated", name));
3871: }
3872:
3873: /**
3874: * A notice.
3875: */
3876: public Value notice(String msg) {
3877: return error(B_NOTICE, "", msg + getFunctionLocation());
3878: }
3879:
3880: /**
3881: * A notice with an exception.
3882: */
3883: public Value notice(String msg, Throwable e) {
3884: log.log(Level.FINE, e.toString(), e);
3885:
3886: return notice(msg);
3887: }
3888:
3889: /**
3890: * A stub notice.
3891: */
3892: public Value stub(String msg) {
3893: if (log.isLoggable(Level.FINE))
3894: log.fine(getLocation().getMessagePrefix() + msg);
3895:
3896: return NullValue.NULL;
3897: }
3898:
3899: public static Value nullAsFalse(Value value) {
3900: return value == null || value.isNull() ? BooleanValue.FALSE
3901: : value;
3902: }
3903:
3904: /**
3905: * A parse error
3906: */
3907: public Value parse(String msg) throws Exception {
3908: return error(B_PARSE, "", msg);
3909: }
3910:
3911: /**
3912: * A parse error
3913: */
3914: public Value compileError(String msg) {
3915: return error(B_COMPILE_ERROR, "", msg);
3916: }
3917:
3918: /**
3919: * A parse warning
3920: */
3921: public Value compileWarning(String msg) {
3922: return error(B_COMPILE_WARNING, "", msg);
3923: }
3924:
3925: /**
3926: * Returns the error mask.
3927: */
3928: public int getErrorMask() {
3929: return _errorMask;
3930: }
3931:
3932: /**
3933: * Sets the error mask.
3934: */
3935: public int setErrorMask(int mask) {
3936: int oldMask = _errorMask;
3937:
3938: _errorMask = mask;
3939:
3940: return oldMask;
3941: }
3942:
3943: /**
3944: * Sets an error handler
3945: */
3946: public void setErrorHandler(int mask, Callback fun) {
3947: for (int i = 0; i < _errorHandlers.length; i++)
3948: _prevErrorHandlers[i] = _errorHandlers[i];
3949:
3950: if ((mask & E_ERROR) != 0)
3951: _errorHandlers[B_ERROR] = fun;
3952:
3953: if ((mask & E_WARNING) != 0)
3954: _errorHandlers[B_WARNING] = fun;
3955:
3956: if ((mask & E_PARSE) != 0)
3957: _errorHandlers[B_PARSE] = fun;
3958:
3959: if ((mask & E_NOTICE) != 0)
3960: _errorHandlers[B_NOTICE] = fun;
3961:
3962: if ((mask & E_USER_ERROR) != 0)
3963: _errorHandlers[B_USER_ERROR] = fun;
3964:
3965: if ((mask & E_USER_WARNING) != 0)
3966: _errorHandlers[B_USER_WARNING] = fun;
3967:
3968: if ((mask & E_USER_NOTICE) != 0)
3969: _errorHandlers[B_USER_NOTICE] = fun;
3970:
3971: if ((mask & E_STRICT) != 0)
3972: _errorHandlers[B_STRICT] = fun;
3973: }
3974:
3975: /**
3976: * Sets an error handler
3977: */
3978: public void restoreErrorHandler() {
3979: for (int i = 0; i < _errorHandlers.length; i++)
3980: _errorHandlers[i] = _prevErrorHandlers[i];
3981: }
3982:
3983: /**
3984: * Gets the exception handler
3985: */
3986: public Callback getExceptionHandler() {
3987: return _exceptionHandler;
3988: }
3989:
3990: /**
3991: * Sets an exception handler
3992: */
3993: public Value setExceptionHandler(Callback fun) {
3994: _prevExceptionHandler = _exceptionHandler;
3995:
3996: _exceptionHandler = fun;
3997:
3998: if (_prevExceptionHandler != null)
3999: return _prevExceptionHandler.toStringValue();
4000: else
4001: return NullValue.NULL;
4002: }
4003:
4004: /**
4005: * Restore an exception handler
4006: */
4007: public void restoreExceptionHandler() {
4008: _exceptionHandler = _prevExceptionHandler;
4009: }
4010:
4011: /*
4012: * Writes an error.
4013: */
4014: public Value error(int code, String locString, String msg) {
4015: return error(code, null, locString, msg);
4016: }
4017:
4018: /*
4019: * Writes an error.
4020: */
4021: public Value error(int code, Location location, String msg) {
4022: return error(code, location, "", msg);
4023: }
4024:
4025: /**
4026: * Writes an error.
4027: */
4028: public Value error(int code, Location location, String loc,
4029: String msg) {
4030: int mask = 1 << code;
4031:
4032: if (location == null)
4033: location = getLocation();
4034:
4035: String locationMessagePrefix = loc;
4036:
4037: if (loc.equals(""))
4038: locationMessagePrefix = location.getMessagePrefix();
4039:
4040: if (code >= 0 && code < _errorHandlers.length
4041: && _errorHandlers[code] != null) {
4042: Callback handler = _errorHandlers[code];
4043:
4044: try {
4045: _errorHandlers[code] = null;
4046:
4047: Value fileNameV = NullValue.NULL;
4048:
4049: String fileName = location.getFileName();
4050:
4051: if (fileName != null)
4052: fileNameV = createString(fileName);
4053:
4054: Value lineV = NullValue.NULL;
4055: int line = location.getLineNumber();
4056: if (line > 0)
4057: lineV = new LongValue(line);
4058:
4059: Value context = NullValue.NULL;
4060:
4061: handler.call(this , new LongValue(mask),
4062: createString(msg), fileNameV, lineV, context);
4063:
4064: return NullValue.NULL;
4065: } catch (RuntimeException e) {
4066: throw e;
4067: } catch (Throwable e) {
4068: throw new RuntimeException(e);
4069: } finally {
4070: _errorHandlers[code] = handler;
4071: }
4072: }
4073:
4074: if ((_errorMask & mask) != 0) {
4075: try {
4076: String fullMsg = locationMessagePrefix
4077: + getCodeName(mask) + msg;
4078:
4079: if (getIniBoolean("track_errors"))
4080: setGlobalValue("php_errormsg",
4081: createString(fullMsg));
4082:
4083: if (getIniBoolean("display_errors"))
4084: getOut().println(fullMsg);
4085:
4086: if (getIniBoolean("log_errors"))
4087: log.info(fullMsg);
4088: } catch (IOException e) {
4089: log.log(Level.FINE, e.toString(), e);
4090: }
4091: }
4092:
4093: if ((mask & (E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR)) != 0) {
4094: if (!"".equals(locationMessagePrefix)) {
4095: /*
4096: throw new QuercusLineExitException(getLocation() +
4097: getCodeName(mask) +
4098: msg);
4099: */
4100: throw new QuercusErrorException(locationMessagePrefix
4101: + getCodeName(mask) + msg);
4102: } else
4103: throw new QuercusErrorException(msg);
4104: }
4105:
4106: return NullValue.NULL;
4107: }
4108:
4109: /**
4110: * Returns the error code name.
4111: */
4112: private String getCodeName(int code) {
4113: switch (code) {
4114: case E_ERROR:
4115: return "Fatal Error: ";
4116: case E_WARNING:
4117: return "Warning: ";
4118: case E_PARSE:
4119: return "Parse Error: ";
4120: case E_NOTICE:
4121: return "Notice: ";
4122: case E_CORE_ERROR:
4123: return "Fatal Error: ";
4124: case E_CORE_WARNING:
4125: return "Warning: ";
4126: case E_COMPILE_ERROR:
4127: return "Fatal Error: ";
4128: case E_COMPILE_WARNING:
4129: return "Warning : ";
4130: case E_USER_ERROR:
4131: return "Fatal Error: ";
4132: case E_USER_WARNING:
4133: return "Warning: ";
4134: case E_USER_NOTICE:
4135: return "Notice: ";
4136: case E_STRICT:
4137: return "Notice: ";
4138:
4139: default:
4140: return String.valueOf("ErrorCode(" + code + ")");
4141: }
4142: }
4143:
4144: /**
4145: * Returns the source of an error line.
4146: */
4147: public static String[] getSourceLine(Path path, int sourceLine,
4148: int length) {
4149: if (path == null)
4150: return null;
4151: else if (path instanceof NullPath) {
4152: // for QuercusScriptEngine.eval() where only a Reader is passed in
4153: // XXX: not too pretty
4154: return null;
4155: }
4156:
4157: ReadStream is = null;
4158:
4159: try {
4160: is = path.openRead();
4161: int ch;
4162: boolean hasCr = false;
4163: int line = 1;
4164:
4165: while (line < sourceLine) {
4166: ch = is.read();
4167:
4168: if (ch < 0)
4169: return null;
4170: else if (ch == '\r') {
4171: hasCr = true;
4172: line++;
4173: } else if (ch == '\n') {
4174: if (!hasCr)
4175: line++;
4176: hasCr = false;
4177: } else
4178: hasCr = false;
4179: }
4180:
4181: String[] result = new String[length];
4182:
4183: int i = 0;
4184: StringBuilder sb = new StringBuilder();
4185: while (i < length && (ch = is.read()) > 0) {
4186: if (ch == '\n' && hasCr) {
4187: hasCr = false;
4188: continue;
4189: } else if (ch == '\r') {
4190: hasCr = true;
4191: result[i++] = sb.toString();
4192: sb.setLength(0);
4193: } else if (ch == '\n') {
4194: hasCr = false;
4195: result[i++] = sb.toString();
4196: sb.setLength(0);
4197: } else {
4198: hasCr = false;
4199: sb.append((char) ch);
4200: }
4201: }
4202:
4203: if (i < length)
4204: result[i] = sb.toString();
4205:
4206: return result;
4207: } catch (IOException e) {
4208: log.log(Level.FINE, e.toString(), e);
4209: } finally {
4210: if (is != null)
4211: is.close();
4212: }
4213:
4214: return null;
4215: }
4216:
4217: /**
4218: * Returns the current execution location.
4219: *
4220: * Use with care, for compiled code this can be a relatively expensive
4221: * operation.
4222: */
4223: public Location getLocation() {
4224: Expr call = peekCall(0);
4225:
4226: if (call != null)
4227: return call.getLocation();
4228:
4229: return Location.UNKNOWN;
4230: }
4231:
4232: public int getSourceLine(String className, int javaLine) {
4233: return javaLine;
4234: }
4235:
4236: /**
4237: * Returns the current function.
4238: */
4239: public String getFunctionLocation() {
4240: // XXX: need to work with compiled code, too
4241: Expr call = peekCall(0);
4242:
4243: if (call != null)
4244: return call.getFunctionLocation();
4245: else
4246: return "";
4247: }
4248:
4249: /**
4250: * Converts a boolean to the boolean value
4251: */
4252: public static Value toValue(boolean value) {
4253: return value ? BooleanValue.TRUE : BooleanValue.FALSE;
4254: }
4255:
4256: /**
4257: * Converts a boolean to the boolean value
4258: */
4259: public static Value toValue(long value) {
4260: return new LongValue(value);
4261: }
4262:
4263: /**
4264: * Converts to a variable
4265: */
4266: public static Var toVar(Value value) {
4267: if (value instanceof Var)
4268: return (Var) value;
4269: else if (value == null)
4270: return new Var();
4271: else
4272: return new Var(value);
4273: }
4274:
4275: /**
4276: * Sets a vield variable
4277: */
4278: public static Value setFieldVar(Value oldValue, Value value) {
4279: if (value instanceof Var)
4280: return value;
4281: else if (oldValue instanceof Var)
4282: return new Var(value);
4283: else
4284: return value;
4285: }
4286:
4287: /**
4288: * Sets a reference
4289: */
4290: public static Value setRef(Value oldValue, Value value) {
4291: // php/3243
4292: if (value instanceof Var)
4293: return value;
4294: /*
4295: else if (oldValue instanceof Var) {
4296: oldValue.set(value);
4297:
4298: return oldValue;
4299: }
4300: */
4301: else
4302: return new Var(value);
4303: }
4304:
4305: /**
4306: * Returns the last value.
4307: */
4308: public static Value comma(Value a0, Value a1) {
4309: return a1;
4310: }
4311:
4312: /**
4313: * Returns the last value.
4314: */
4315: public static Value comma(Value a0, Value a1, Value a2) {
4316: return a2;
4317: }
4318:
4319: /**
4320: * Returns the last value.
4321: */
4322: public static Value comma(Value a0, Value a1, Value a2, Value a3) {
4323: return a3;
4324: }
4325:
4326: /**
4327: * Returns the last value.
4328: */
4329: public static Value comma(Value a0, Value a1, Value a2, Value a3,
4330: Value a4) {
4331: return a4;
4332: }
4333:
4334: public String toString() {
4335: return "Env[]";
4336: }
4337:
4338: /**
4339: * Returns ifNull if condition.isNull(), otherwise returns ifNotNull.
4340: */
4341: public Value ifNull(Value condition, Value ifNull, Value ifNotNull) {
4342: return condition.isNull() ? ifNull : ifNotNull;
4343: }
4344:
4345: /**
4346: * Returns the locale info.
4347: */
4348: public LocaleInfo getLocaleInfo() {
4349: if (_locale == null)
4350: _locale = new LocaleInfo();
4351:
4352: return _locale;
4353: }
4354:
4355: /**
4356: * Registers a shutdown function.
4357: */
4358: public void addShutdown(Callback callback, Value[] args) {
4359: _shutdownList.add(new Shutdown(callback, args));
4360: }
4361:
4362: // XXX: hack until can clean up
4363: public void setGzStream(Object obj) {
4364: _gzStream = obj;
4365: }
4366:
4367: // XXX: hack until can clean up
4368: public Object getGzStream() {
4369: return _gzStream;
4370: }
4371:
4372: /**
4373: * Called when the Env is no longer needed.
4374: */
4375: public void close() {
4376: try {
4377: // php/1l0t
4378: // output buffers callbacks may throw an exception
4379: while (_outputBuffer != null) {
4380: popOutputBuffer();
4381: }
4382:
4383: _freeFunList.free(_fun);
4384: }
4385: //catch (Exception e) {
4386: //throw new RuntimeException(e);
4387: //}
4388: finally {
4389: try {
4390: for (int i = 0; i < _shutdownList.size(); i++)
4391: _shutdownList.get(i).call(this );
4392: } catch (Throwable e) {
4393: log.log(Level.FINE, e.toString(), e);
4394: }
4395:
4396: try {
4397: sessionWriteClose();
4398: } catch (Throwable e) {
4399: log.log(Level.FINE, e.toString(), e);
4400: }
4401:
4402: ArrayList<SoftReference<EnvCleanup>> cleanupList = _cleanupList;
4403: _cleanupList = new ArrayList<SoftReference<EnvCleanup>>(
4404: _cleanupList);
4405:
4406: for (SoftReference<EnvCleanup> ref : cleanupList) {
4407: try {
4408: EnvCleanup envCleanup = ref.get();
4409:
4410: if (envCleanup != null)
4411: envCleanup.cleanup();
4412: } catch (Throwable e) {
4413: log.log(Level.FINER, e.toString(), e);
4414: }
4415: }
4416:
4417: _threadEnv.set(_oldThreadEnv);
4418:
4419: for (int i = 0; _removePaths != null
4420: && i < _removePaths.size(); i++) {
4421: Path path = _removePaths.get(i);
4422:
4423: try {
4424: path.remove();
4425: } catch (IOException e) {
4426: log.log(Level.FINER, e.toString(), e);
4427: }
4428: }
4429: }
4430: }
4431:
4432: public void sessionWriteClose() {
4433: SessionArrayValue session = _session;
4434:
4435: _session = null;
4436:
4437: if (session != null) {
4438: SessionCallback callback = getSessionCallback();
4439:
4440: if (callback != null) {
4441: String value;
4442:
4443: // php/1k6e
4444: if (session.getSize() > 0)
4445: value = VariableModule
4446: .serialize(session.getArray());
4447: else
4448: value = "";
4449:
4450: callback.write(this , session.getId(), value);
4451:
4452: callback.close(this );
4453: } else {
4454: _quercus.saveSession(this , session);
4455:
4456: setGlobalValue("_SESSION", session.copy(this ));
4457: setGlobalValue("HTTP_SESSION_VARS", session.copy(this ));
4458: }
4459: }
4460: }
4461:
4462: public String dbgId() {
4463: return "Quercus[" + _selfPath + "] ";
4464: }
4465:
4466: static class ClassKey {
4467: private final WeakReference<ClassDef> _defRef;
4468: private final WeakReference<QuercusClass> _parentRef;
4469:
4470: private final int _hash;
4471:
4472: ClassKey(ClassDef def, QuercusClass parent) {
4473: _defRef = new WeakReference<ClassDef>(def);
4474:
4475: if (parent != null)
4476: _parentRef = new WeakReference<QuercusClass>(parent);
4477: else
4478: _parentRef = null;
4479:
4480: // hash needs to be precalculated so losing a weak references won't
4481: // change the result
4482:
4483: int hash = 37;
4484:
4485: if (def != null)
4486: hash = 65521 * hash + def.hashCode();
4487:
4488: if (parent != null)
4489: hash = 65521 * hash + parent.hashCode();
4490:
4491: _hash = hash;
4492: }
4493:
4494: public int hashCode() {
4495: return _hash;
4496: }
4497:
4498: public boolean equals(Object o) {
4499: ClassKey key = (ClassKey) o;
4500:
4501: ClassDef aDef = _defRef.get();
4502: ClassDef bDef = key._defRef.get();
4503:
4504: if (aDef != bDef)
4505: return false;
4506:
4507: if (_parentRef == key._parentRef)
4508: return true;
4509:
4510: else if (_parentRef != null && key._parentRef != null)
4511: return _parentRef.get() == key._parentRef.get();
4512:
4513: else
4514: return false;
4515: }
4516: }
4517:
4518: static class ConnectionEntry {
4519: private DataSource _ds;
4520: private String _user;
4521: private String _password;
4522: private Connection _conn;
4523:
4524: public void init(DataSource ds, String user, String password) {
4525: _ds = ds;
4526: _user = user;
4527: _password = password;
4528: }
4529:
4530: public void setConnection(Connection conn) {
4531: _conn = conn;
4532: }
4533:
4534: public Connection getConnection() {
4535: return _conn;
4536: }
4537:
4538: public int hashCode() {
4539: int hash = _ds.hashCode();
4540:
4541: if (_user == null)
4542: return hash;
4543: else
4544: return 65521 * hash + _user.hashCode();
4545: }
4546:
4547: public boolean equals(Object o) {
4548: if (!(o instanceof ConnectionEntry))
4549: return false;
4550:
4551: ConnectionEntry entry = (ConnectionEntry) o;
4552:
4553: if (_ds != entry._ds)
4554: return false;
4555: else if (_user == null)
4556: return entry._user == null;
4557: else
4558: return _user.equals(entry._user);
4559: }
4560:
4561: public String toString() {
4562: return getClass().getSimpleName() + "[ds=" + _ds
4563: + ", user=" + _user + "]";
4564: }
4565: }
4566:
4567: static {
4568: SPECIAL_VARS.put("GLOBALS", _GLOBAL);
4569: SPECIAL_VARS.put("_SERVER", _SERVER);
4570: SPECIAL_VARS.put("_GET", _GET);
4571: SPECIAL_VARS.put("_POST", _POST);
4572: SPECIAL_VARS.put("_FILES", _FILES);
4573: SPECIAL_VARS.put("_REQUEST", _REQUEST);
4574: SPECIAL_VARS.put("_COOKIE", _COOKIE);
4575: SPECIAL_VARS.put("_SESSION", _SESSION);
4576: SPECIAL_VARS.put("_ENV", _ENV);
4577: SPECIAL_VARS.put("HTTP_GET_VARS", HTTP_GET_VARS);
4578: SPECIAL_VARS.put("HTTP_POST_VARS", HTTP_POST_VARS);
4579: SPECIAL_VARS.put("HTTP_POST_FILES", HTTP_POST_FILES);
4580: SPECIAL_VARS.put("HTTP_COOKIE_VARS", HTTP_COOKIE_VARS);
4581: SPECIAL_VARS.put("HTTP_SERVER_VARS", HTTP_SERVER_VARS);
4582: SPECIAL_VARS.put("PHP_SELF", PHP_SELF);
4583: }
4584: }
|