Source Code Cross Referenced for FileModule.java in  » EJB-Server-resin-3.1.5 » quercus » com » caucho » quercus » lib » file » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » EJB Server resin 3.1.5 » quercus » com.caucho.quercus.lib.file 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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