<commit_before>/* 
    JSPWiki - a JSP-based WikiWiki clone.

    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.  
 */
package com.ecyrd.jspwiki.providers;

import java.io.*;
import java.util.Properties;
import java.util.Collection;
import java.util.Date;
import java.util.TreeSet;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;

import com.ecyrd.jspwiki.*;

/**
 *  Provides a simple directory based repository for Wiki pages.
 *  <P>
 *  All files have ".txt" appended to make life easier for those
 *  who insist on using Windows or other software which makes assumptions
 *  on the files contents based on its name.
 *  <p>
 *  This class functions as a superclass to all file based providers.
 *
 *  @since 2.1.21.
 *
 */
public abstract class AbstractFileProvider
    implements WikiPageProvider
{
    private static final Logger   log = Logger.getLogger(AbstractFileProvider.class);
    private String m_pageDirectory = "/tmp/";
    
    protected String m_encoding;
    
    protected WikiEngine m_engine;

    /**
     *  Name of the property that defines where page directories are.
     */
    public static final String      PROP_PAGEDIR = "jspwiki.fileSystemProvider.pageDir";

    /**
     *  All files should have this extension to be recognized as JSPWiki files.
     *  We default to .txt, because that is probably easiest for Windows users,
     *  and guarantees correct handling.
     */
    public static final String FILE_EXT = ".txt";

    public static final String DEFAULT_ENCODING = "ISO-8859-1";

    private boolean m_windowsHackNeeded = false;
    
    /**
     *  @throws FileNotFoundException If the specified page directory does not exist.
     *  @throws IOException In case the specified page directory is a file, not a directory.
     */
    public void initialize( WikiEngine engine, Properties properties )
        throws NoRequiredPropertyException,
               IOException
    {
        log.debug("Initing FileSystemProvider");
        m_pageDirectory = WikiEngine.getRequiredProperty( properties, PROP_PAGEDIR );

        File f = new File(m_pageDirectory);

        if( !f.exists() )
        {
            if (!f.mkdirs()) 
            {
              throw new IOException("Failed to create page directory "+f.getAbsolutePath()+" , please check property "+PROP_PAGEDIR);  
            }
        }
        else {
            if( !f.isDirectory() )
            {
            throw new IOException("Page directory is not a directory: "+f.getAbsolutePath());
            }
            if (!f.canWrite()) 
            {
                throw new IOException("Page directory is not writable: "+f.getAbsolutePath());    
            }
            }
        
        m_engine = engine;

        m_encoding = properties.getProperty( WikiEngine.PROP_ENCODING, 
                                             DEFAULT_ENCODING );

        String os = System.getProperty( "os.name" ).toLowerCase();
        
        if( os.startsWith("windows") || os.equals("nt") )
        {
            m_windowsHackNeeded = true;
        }
        
        log.info( "Wikipages are read from '" + m_pageDirectory + "'" );
    }


    String getPageDirectory()
    {
        return m_pageDirectory;
    }

    private static final String[] WINDOWS_DEVICE_NAMES =
    {
        "con", "prn", "nul", "aux", "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9",
        "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9"
    };
    
    /**
     *  This makes sure that the queried page name
     *  is still readable by the file system.
     */
    protected String mangleName( String pagename )
    {
        pagename = TextUtil.urlEncode( pagename, m_encoding );
        
        pagename = TextUtil.replaceString( pagename, "/", "%2F" );

        if( m_windowsHackNeeded )
        {
            String pn = pagename.toLowerCase();
            for( int i = 0; i < WINDOWS_DEVICE_NAMES.length; i++ )
            {
                if( WINDOWS_DEVICE_NAMES[i].equals(pn) )
                {
                    pagename = "$$$" + pagename;
                }
            }
        }
        
        return pagename;
    }

    /**
     *  This makes the reverse of mangleName.
     */
    protected String unmangleName( String filename )
    {
        // The exception should never happen.
        try
        {
            if( m_windowsHackNeeded && filename.startsWith( "$$$") && filename.length() > 3 )
            {
                filename = filename.substring(3);
            }<commit_msg>JSPWIKI-5.  Pages starting with a dot are now properly encoded.<commit_after>/* 
    JSPWiki - a JSP-based WikiWiki clone.

    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.  
 */
package com.ecyrd.jspwiki.providers;

import java.io.*;
import java.util.Properties;
import java.util.Collection;
import java.util.Date;
import java.util.TreeSet;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;

import com.ecyrd.jspwiki.*;

/**
 *  Provides a simple directory based repository for Wiki pages.
 *  <P>
 *  All files have ".txt" appended to make life easier for those
 *  who insist on using Windows or other software which makes assumptions
 *  on the files contents based on its name.
 *  <p>
 *  This class functions as a superclass to all file based providers.
 *
 *  @since 2.1.21.
 *
 */
public abstract class AbstractFileProvider
    implements WikiPageProvider
{
    private static final Logger   log = Logger.getLogger(AbstractFileProvider.class);
    private String m_pageDirectory = "/tmp/";
    
    protected String m_encoding;
    
    protected WikiEngine m_engine;

    /**
     *  Name of the property that defines where page directories are.
     */
    public static final String      PROP_PAGEDIR = "jspwiki.fileSystemProvider.pageDir";

    /**
     *  All files should have this extension to be recognized as JSPWiki files.
     *  We default to .txt, because that is probably easiest for Windows users,
     *  and guarantees correct handling.
     */
    public static final String FILE_EXT = ".txt";

    public static final String DEFAULT_ENCODING = "ISO-8859-1";

    private boolean m_windowsHackNeeded = false;
    
    /**
     *  @throws FileNotFoundException If the specified page directory does not exist.
     *  @throws IOException In case the specified page directory is a file, not a directory.
     */
    public void initialize( WikiEngine engine, Properties properties )
        throws NoRequiredPropertyException,
               IOException
    {
        log.debug("Initing FileSystemProvider");
        m_pageDirectory = WikiEngine.getRequiredProperty( properties, PROP_PAGEDIR );

        File f = new File(m_pageDirectory);

        if( !f.exists() )
        {
            if (!f.mkdirs()) 
            {
              throw new IOException("Failed to create page directory "+f.getAbsolutePath()+" , please check property "+PROP_PAGEDIR);  
            }
        }
        else {
            if( !f.isDirectory() )
            {
            throw new IOException("Page directory is not a directory: "+f.getAbsolutePath());
            }
            if (!f.canWrite()) 
            {
                throw new IOException("Page directory is not writable: "+f.getAbsolutePath());    
            }
            }
        
        m_engine = engine;

        m_encoding = properties.getProperty( WikiEngine.PROP_ENCODING, 
                                             DEFAULT_ENCODING );

        String os = System.getProperty( "os.name" ).toLowerCase();
        
        if( os.startsWith("windows") || os.equals("nt") )
        {
            m_windowsHackNeeded = true;
        }
        
        log.info( "Wikipages are read from '" + m_pageDirectory + "'" );
    }


    String getPageDirectory()
    {
        return m_pageDirectory;
    }

    private static final String[] WINDOWS_DEVICE_NAMES =
    {
        "con", "prn", "nul", "aux", "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9",
        "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9"
    };
    
    /**
     *  This makes sure that the queried page name
     *  is still readable by the file system.
     */
    protected String mangleName( String pagename )
    {
        pagename = TextUtil.urlEncode( pagename, m_encoding );
        
        pagename = TextUtil.replaceString( pagename, "/", "%2F" );

        //
        //  Names which start with a dot must be escaped to prevent problems.
        //  Since we use URL encoding, this is invisible in our unescaping.
        //
        if( pagename.startsWith( "." ) )
        {
            pagename = "%2E" + pagename.substring( 1 );
        }
        
        if( m_windowsHackNeeded )
        {
            String pn = pagename.toLowerCase();
            for( int i = 0; i < WINDOWS_DEVICE_NAMES.length; i++ )
            {
                if( WINDOWS_DEVICE_NAMES[i].equals(pn) )
                {
                    pagename = "$$$" + pagename;
                }
            }
        }
        
        return pagename;
    }

    /**
     *  This makes the reverse of mangleName.
     */
    protected String unmangleName( String filename )
    {
        // The exception should never happen.
        try
        {
            if( m_windowsHackNeeded && filename.startsWith( "$$$") && filename.length() > 3 )
            {
                filename = filename.substring(3);
            }
{'fraction_non_alphanumeric': 0.09215295396882929, 'fraction_numerical': 0.006795940558173251, 'mean_word_length': 2.1169161253883084, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2400836', 'n_tokens_mistral': 3080, 'n_tokens_neox': 2993, 'n_words': 996}