Tag Cloud

CRM 2011 (161) CRM 4.0 (144) C# (116) JScript (109) Plugin (92) Registry (90) Techpedia (77) PyS60 (68) WScript (43) Plugin Message (31) Exploit (27) ShellCode (26) FAQ (22) JavaScript (21) Killer Codes (21) Hax (18) VB 6.0 (17) Commands (16) VBScript (16) Quotes (15) Turbo C++ (13) WMI (13) Security (11) 1337 (10) Tutorials (10) Asp.Net (9) Safe Boot (9) Python (8) Interview Questions (6) video (6) Ajax (5) VC++ (5) WebService (5) Workflow (5) Bat (4) Dorks (4) Sql Server (4) Aptitude (3) Picklist (3) Tweak (3) WCF (3) regex (3) Config (2) LINQ (2) PHP (2) Shell (2) Silverlight (2) TSql (2) flowchart (2) serialize (2) ASHX (1) CRM 4.0 Videos (1) Debug (1) FetchXml (1) GAC (1) General (1) Generics (1) HttpWebRequest (1) InputParameters (1) Lookup (1) Offline Plug-ins (1) OutputParameters (1) Plug-in Constructor (1) Protocol (1) RIA (1) Sharepoint (1) Walkthrough (1) Web.config (1) design patterns (1) generic (1) iframe (1) secure config (1) unsecure config (1) url (1)

Pages

Wednesday, August 10, 2011

File Explorer







function file_explorer($boss = false, $webmaster="webmaster@site.com")

{



$page = "





File Explorer

";//Variable that will store all of the HTML

$user_dir = isset($_GET['d'])? $_GET['d'] : "";

//Uses this files location to get the directory and then looks for 'files' folder

//make sure the folder is here, or change this variable

$dir = substr(__FILE__, 0, strrpos(__FILE__, '/'))."files$user_dir";



//Checks to see if they are trying to get out of your folder and roam your filesystem

if(strpos($user_dir, "..") !== false)

{

$page .= "Please do not try and hack the website. You have been reported to Bosses";

/**

* You must have php configured to send mail before including this bit

*/

$headers = 'MIME-Version: 1.0' . "\r\n";

$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";

$headers .= 'From: File Explorer Notifier ' . "\r\n";//customize me

<--more-->

//mail($webmaster, "Someone tried to hack admin/documents",

// "
SERVER:\n\n".var_export($_SERVER, true)."\n\n---\n\nSession:\n\n".var_export($_SESSION, true)."
",
// $headers);
return $page;
}

/*BREADCRUMBS*/
$cur_path = explode("\\", $user_dir);
$temp_path = "";//stores the url for the increasing breadcrumb

$page .= "
";
//loops through the current directory and puts links in breadcrumb form
// Top --> dir1 --> dir1_1 --> dir1_1_2
for($cc=0;$cc {
if($cc == 0)
$page .= "Top";
else if(!empty($cur_path[$cc]))
{
$temp_path .= "\\".$cur_path[$cc];
$page .= " --> {$cur_path[$cc]}";
}
}
$page .= "
";

//Tries to open the directory
$m = opendir($dir);
if($m !== false)//vaild directory
{
//if there is a file to be uploaded and the user has permission
if(isset($_FILES['uploadMe']) && $boss)
{
$name = "$dir\\[".time()."] - ".filename_safe($_FILES["uploadMe"]["name"]);//makes the filename safe
if(move_uploaded_file($_FILES["uploadMe"]["tmp_name"], $name))
$page .= "
Uploaded file to $name
";
else
$page .= "
An error occured
".var_export($_FILES, true)."
";
}
//if there is a directory to be created and the user has permission
if(isset($_POST['newdir']) && $boss)
{
$name = "$dir\\".filename_safe($_POST['newdir']);//makes the directory name safe
if(mkdir($name))//create directory
$page .= "
Created Folder: $name
";
else
$page .= "
Unable to create directory
";
}

$page .= "
"; /** * Icons taken from: http://www.erichynds...ples/famfamfam/ */ $folder_icon = ""; //check source for picture source $file_icon = ""; //check source for picture source //Loops through the opened directory, displays all files and directories $numfiles = 0;//stores the number of files it finds $numfolders = 0;//stores the number of folders it finds while (false !== ($file = readdir($m))) { if($file == "." || $file == "..") continue; $f = "$dir\\$file"; $page .= "
"; if(is_dir($f))//checks if directory { $numfolders++; $page .= ""; } else//its a file { $numfiles++; $page .= ""; } $page .= "
"; } $page .= "
Name Size Last Modified Last Accessed Last Created
$folder_icon$file N/A$file_icon$file".
round(filesize($f)/1024, 2)." KB
".date ("F d Y H:i:s.", filemtime($f)).
"
".date ("F d Y H:i:s.", fileatime($f)).
"
".date ("F d Y H:i:s.", filectime($f)).
"
";

if($numfiles == 0 && $numfolders == 0)//no files or folders
$page .= "
No File or Folders
";
else
$page .= "
Files: $numfiles, Folders: $numfolders
";

//has premission to upload and create directories
if($boss)
{
$page .= "


Will upload your file to: $dir
Send this file:

Will create your directory in: $dir
Create directory:

";
}

}
else
{
$page .= "Not a directory";
}

return $page;
}
?>

File Explorer







function file_explorer($boss = false, $webmaster="webmaster@site.com")

{



$page = "





File Explorer

";//Variable that will store all of the HTML

$user_dir = isset($_GET['d'])? $_GET['d'] : "";

//Uses this files location to get the directory and then looks for 'files' folder

//make sure the folder is here, or change this variable

$dir = substr(__FILE__, 0, strrpos(__FILE__, '/'))."files$user_dir";



//Checks to see if they are trying to get out of your folder and roam your filesystem

if(strpos($user_dir, "..") !== false)

{

$page .= "Please do not try and hack the website. You have been reported to Bosses";

/**

* You must have php configured to send mail before including this bit

*/

$headers = 'MIME-Version: 1.0' . "\r\n";

$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";

$headers .= 'From: File Explorer Notifier ' . "\r\n";//customize me

<--more-->

//mail($webmaster, "Someone tried to hack admin/documents",

// "
SERVER:\n\n".var_export($_SERVER, true)."\n\n---\n\nSession:\n\n".var_export($_SESSION, true)."
",
// $headers);
return $page;
}

/*BREADCRUMBS*/
$cur_path = explode("\\", $user_dir);
$temp_path = "";//stores the url for the increasing breadcrumb

$page .= "
";
//loops through the current directory and puts links in breadcrumb form
// Top --> dir1 --> dir1_1 --> dir1_1_2
for($cc=0;$cc {
if($cc == 0)
$page .= "Top";
else if(!empty($cur_path[$cc]))
{
$temp_path .= "\\".$cur_path[$cc];
$page .= " --> {$cur_path[$cc]}";
}
}
$page .= "
";

//Tries to open the directory
$m = opendir($dir);
if($m !== false)//vaild directory
{
//if there is a file to be uploaded and the user has permission
if(isset($_FILES['uploadMe']) && $boss)
{
$name = "$dir\\[".time()."] - ".filename_safe($_FILES["uploadMe"]["name"]);//makes the filename safe
if(move_uploaded_file($_FILES["uploadMe"]["tmp_name"], $name))
$page .= "
Uploaded file to $name
";
else
$page .= "
An error occured
".var_export($_FILES, true)."
";
}
//if there is a directory to be created and the user has permission
if(isset($_POST['newdir']) && $boss)
{
$name = "$dir\\".filename_safe($_POST['newdir']);//makes the directory name safe
if(mkdir($name))//create directory
$page .= "
Created Folder: $name
";
else
$page .= "
Unable to create directory
";
}

$page .= "
"; /** * Icons taken from: http://www.erichynds...ples/famfamfam/ */ $folder_icon = ""; //check source for picture source $file_icon = ""; //check source for picture source //Loops through the opened directory, displays all files and directories $numfiles = 0;//stores the number of files it finds $numfolders = 0;//stores the number of folders it finds while (false !== ($file = readdir($m))) { if($file == "." || $file == "..") continue; $f = "$dir\\$file"; $page .= "
"; if(is_dir($f))//checks if directory { $numfolders++; $page .= ""; } else//its a file { $numfiles++; $page .= ""; } $page .= "
"; } $page .= "
Name Size Last Modified Last Accessed Last Created
$folder_icon$file N/A$file_icon$file".
round(filesize($f)/1024, 2)." KB
".date ("F d Y H:i:s.", filemtime($f)).
"
".date ("F d Y H:i:s.", fileatime($f)).
"
".date ("F d Y H:i:s.", filectime($f)).
"
";

if($numfiles == 0 && $numfolders == 0)//no files or folders
$page .= "
No File or Folders
";
else
$page .= "
Files: $numfiles, Folders: $numfolders
";

//has premission to upload and create directories
if($boss)
{
$page .= "


Will upload your file to: $dir
Send this file:

Will create your directory in: $dir
Create directory:

";
}

}
else
{
$page .= "Not a directory";
}

return $page;
}
?>

JPG Information





/* 

DESCRIPTION: Extracts any information after the actual end of a JPEG file.

*/



#include

#include

#include

using namespace std;



unsigned long int szFile;

char * buffer;



int main(int argc, char* argv[])

{

char *buffer;

int dataBegin;

char SOI[] = { 0xFF, 0xD8 }; //Start of Image

char COMM[] = { 0xFF, 0xFE }; //Comments Follow

char EOI[] = { 0xFF, 0xD9 }; //End of Image

ifstream fin;

ofstream fout;

if(argc != 3 ) {

cout << "Usage: " << argv[0] << " file.jpg outputfile.ext" << endl;

exit(EXIT_SUCCESS);

}



fin.open(argv[1], ios::binary | ios::in | ios::ate);

if(!fin.is_open()) {

cerr << "Error while opening input file!" << endl;

exit(EXIT_FAILURE);

}

szFile = (unsigned long int) fin.tellg();

if(szFile < 4) {

cerr << "Not a valid jpg image file!" << endl;

exit(EXIT_SUCCESS);

}



buffer = new char[szFile];

fin.seekg (0, ios::beg);

fin.read (buffer, szFile);

fin.close();



if(buffer[0] != (char) 0xFF || buffer[1] != (char) 0xD8) {

cerr << "Not a valid jpeg image file!" << endl;

exit(EXIT_SUCCESS);

}



bool comments = false;

for(unsigned long int i = 2; i < szFile-1; i++) {

if(buffer[i] == COMM[0] && buffer[i+1] == COMM[1]) {

cout << "Jpeg Comments: "; comments = true;

}



if(buffer[i] == EOI[0] && buffer[i+1] == EOI[1]) {

if(comments){

//end comments section;

comments=false;

cout << endl;

}

cout << "Jpeg Image Size: " << i+1 << " bytes" << endl;

dataBegin = i + 2;

break;

}

if(comments) cout << (char)buffer[i];

}



fout.open(argv[2], ios::out | ios::binary);

if(!fout.is_open()) {

cerr << "Error while opening output file!" << endl;

exit(EXIT_FAILURE);

}

for(unsigned long int i = dataBegin; i < szFile; i++) {

fout.put(buffer[i]);

}

fout.close();

cout << "Done Writing " << szFile - dataBegin << " bytes to " << argv[2] << endl;



delete[] buffer;

exit(EXIT_SUCCESS);

}

OvrIndexer.cs






using System;

///

/// Implements overloaded indexers.

///




namespace IndiLogiX.Tutorial

{

class OvrIndexer

{

private string[] myData;

private int arrSize;

public OvrIndexer(int size)

{

arrSize = size;

myData = new string[size];

for (int i=0; i < size; i++)

{

myData[i] = "empty";

}

}

public string this[int pos]

{

get

{

return myData[pos];

}

set

{

myData[pos] = value;

}

}<--more-->

public string this[string data]

{

get

{

int count = 0;

for (int i=0; i < arrSize; i++)

{

if (myData[i] == data)

{

count++;

}

}

return count.ToString();

}

set

{

for (int i=0; i < arrSize; i++)

{

if (myData[i] == data)

{

myData[i] = value;

}

}

}

}

static void Main(string[] args)

{

int size = 10;

OvrIndexer myInd = new OvrIndexer(size);

myInd[9] = "Some Value";

myInd[3] = "Another Value";

myInd[5] = "Any Value";

myInd["empty"] = "no value";

Console.WriteLine("\nIndexer Output\n");

for (int i=0; i < size; i++)

{

Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]);

}

Console.WriteLine("\nNumber of \"no value\" entries: {0}",

myInd["no value"]);

}

}

}


OvrIndexer.cs






using System;

///

/// Implements overloaded indexers.

///




namespace IndiLogiX.Tutorial

{

class OvrIndexer

{

private string[] myData;

private int arrSize;

public OvrIndexer(int size)

{

arrSize = size;

myData = new string[size];

for (int i=0; i < size; i++)

{

myData[i] = "empty";

}

}

public string this[int pos]

{

get

{

return myData[pos];

}

set

{

myData[pos] = value;

}

}<--more-->

public string this[string data]

{

get

{

int count = 0;

for (int i=0; i < arrSize; i++)

{

if (myData[i] == data)

{

count++;

}

}

return count.ToString();

}

set

{

for (int i=0; i < arrSize; i++)

{

if (myData[i] == data)

{

myData[i] = value;

}

}

}

}

static void Main(string[] args)

{

int size = 10;

OvrIndexer myInd = new OvrIndexer(size);

myInd[9] = "Some Value";

myInd[3] = "Another Value";

myInd[5] = "Any Value";

myInd["empty"] = "no value";

Console.WriteLine("\nIndexer Output\n");

for (int i=0; i < size; i++)

{

Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]);

}

Console.WriteLine("\nNumber of \"no value\" entries: {0}",

myInd["no value"]);

}

}

}


IntIndexer.cs






using System;

///

/// A simple indexer example.

///


namespace IndiLogiX.Tutorial



{

class IntIndexer

{

private string[] myData;

public IntIndexer(int size)

{

myData = new string[size];

for (int i=0; i < size; i++)

{

myData[i] = "empty";

}

}

public string this[int pos]

{

get

{

return myData[pos];

}

set

{

myData[pos] = value;

}

}



static void Main(string[] args)

{

int size = 10;

IntIndexer myInd = new IntIndexer(size);

myInd[9] = "Some Value";

myInd[3] = "Another Value";

myInd[5] = "Any Value";

Console.WriteLine("\nIndexer Output\n");

for (int i=0; i < size; i++)

{

Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]);

}

}

}

}

IntIndexer.cs






using System;

///

/// A simple indexer example.

///


namespace IndiLogiX.Tutorial



{

class IntIndexer

{

private string[] myData;

public IntIndexer(int size)

{

myData = new string[size];

for (int i=0; i < size; i++)

{

myData[i] = "empty";

}

}

public string this[int pos]

{

get

{

return myData[pos];

}

set

{

myData[pos] = value;

}

}



static void Main(string[] args)

{

int size = 10;

IntIndexer myInd = new IntIndexer(size);

myInd[9] = "Some Value";

myInd[3] = "Another Value";

myInd[5] = "Any Value";

Console.WriteLine("\nIndexer Output\n");

for (int i=0; i < size; i++)

{

Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]);

}

}

}

}

indexer.cs




// indexer.cs

// arguments: indexer.txt

using System;

using System.IO;



// Class to provide access to a large file

// as if it were a byte array.

public class FileByteArray

{

Stream stream; // Holds the underlying stream

// used to access the file.

// Create a new FileByteArray encapsulating a particular file.

public FileByteArray(string fileName)

{

stream = new FileStream(fileName, FileMode.Open);

}



// Close the stream. This should be the last thing done

// when you are finished.

public void Close()

{

stream.Close();

stream = null;

}



// Indexer to provide read/write access to the file.

public byte this[long index] // long is a 64-bit integer

{

// Read one byte at offset index and return it.

get

{

byte[] buffer = new byte[1];

stream.Seek(index, SeekOrigin.Begin);

stream.Read(buffer, 0, 1);

return buffer[0];

}

// Write one byte at offset index and return it.

set

{

byte[] buffer = new byte[1] {value};

stream.Seek(index, SeekOrigin.Begin);

stream.Write(buffer, 0, 1);

}

}



// Get the total length of the file.

public long Length

{

get

{

return stream.Seek(0, SeekOrigin.End);

}

}

}



// Demonstrate the FileByteArray class.

// Reverses the bytes in a file.

public class Reverse

{

public static void Main(String[] args)

{

// Check for arguments.

if (args.Length != 1)

{

Console.WriteLine("Usage : Indexer ");

return;

}



// Check for file existence

if (!System.IO.File.Exists(args[0]))

{

Console.WriteLine("File " + args[0] + " not found.");

return;

}



FileByteArray file = new FileByteArray(args[0]);

long len = file.Length;



// Swap bytes in the file to reverse it.

for (long i = 0; i < len / 2; ++i)

{

byte t;



// Note that indexing the "file" variable invokes the

// indexer on the FileByteStream class, which reads

// and writes the bytes in the file.

t = file[i];

file[i] = file[len - i - 1];

file[len - i - 1] = t;

}



file.Close();

}

}

indexer.cs




// indexer.cs

// arguments: indexer.txt

using System;

using System.IO;



// Class to provide access to a large file

// as if it were a byte array.

public class FileByteArray

{

Stream stream; // Holds the underlying stream

// used to access the file.

// Create a new FileByteArray encapsulating a particular file.

public FileByteArray(string fileName)

{

stream = new FileStream(fileName, FileMode.Open);

}



// Close the stream. This should be the last thing done

// when you are finished.

public void Close()

{

stream.Close();

stream = null;

}



// Indexer to provide read/write access to the file.

public byte this[long index] // long is a 64-bit integer

{

// Read one byte at offset index and return it.

get

{

byte[] buffer = new byte[1];

stream.Seek(index, SeekOrigin.Begin);

stream.Read(buffer, 0, 1);

return buffer[0];

}

// Write one byte at offset index and return it.

set

{

byte[] buffer = new byte[1] {value};

stream.Seek(index, SeekOrigin.Begin);

stream.Write(buffer, 0, 1);

}

}



// Get the total length of the file.

public long Length

{

get

{

return stream.Seek(0, SeekOrigin.End);

}

}

}



// Demonstrate the FileByteArray class.

// Reverses the bytes in a file.

public class Reverse

{

public static void Main(String[] args)

{

// Check for arguments.

if (args.Length != 1)

{

Console.WriteLine("Usage : Indexer ");

return;

}



// Check for file existence

if (!System.IO.File.Exists(args[0]))

{

Console.WriteLine("File " + args[0] + " not found.");

return;

}



FileByteArray file = new FileByteArray(args[0]);

long len = file.Length;



// Swap bytes in the file to reverse it.

for (long i = 0; i < len / 2; ++i)

{

byte t;



// Note that indexing the "file" variable invokes the

// indexer on the FileByteStream class, which reads

// and writes the bytes in the file.

t = file[i];

file[i] = file[len - i - 1];

file[len - i - 1] = t;

}



file.Close();

}

}

indexedproperty.cs


This sample shows how C# classes can declare indexed properties to represent an array-like collection of different kinds of things.
This sample contains the source code for the Indexed Properties Tutorial.


Building and Running the Sample Within Visual Studio
To build and run the Indexed Properties sample 
1. Open the solution (IndexedProperties.sln). 
2. From the Debug menu, click Start Without Debugging. 


Building and Running the Sample from the Command Line
To build and run the Indexed Properties sample 
* Type the following at the command prompt: 
    csc indexedproperty.cs
    indexedproperty



// indexedproperty.cs
using System;


public class Document
{
    // Type allowing the document to be viewed like an array of words:
    public class WordCollection
    {
        readonly Document document;  // The containing document


        internal WordCollection(Document d)
        {
           document = d;
        }


        // Helper function -- search character array "text", starting at
        // character "begin", for word number "wordCount." Returns false
        // if there are less than wordCount words. Sets "start" and
        // length" to the position and length of the word within text:
        private bool GetWord(char[] text, int begin, int wordCount, 
                                       out int start, out int length) 
        { 
            int end = text.Length;
            int count = 0;
            int inWord = -1;
            start = length = 0; 


            for (int i = begin; i <= end; ++i) 
            {
                bool isLetter = i < end && Char.IsLetterOrDigit(text[i]);


                if (inWord >= 0) 
                {
                    if (!isLetter) 
                    {
                        if (count++ == wordCount) 
                        {
                            start = inWord;
                            length = i - inWord;
                            return true;
                        }
                        inWord = -1;
                    }
                }
                else 
                {
                    if (isLetter)
                        inWord = i;
                }
            }
            return false;
        }


        // Indexer to get and set words of the containing document:
        public string this[int index] 
        {
            get 
            { 
                int start, length;
                if (GetWord(document.TextArray, 0, index, out start, 
                                                          out length))
                    return new string(document.TextArray, start, length);
                else
                    throw new IndexOutOfRangeException();
            }
            set 
            {
                int start, length;
                if (GetWord(document.TextArray, 0, index, out start, 
                                                         out length)) 
                {
                    // Replace the word at start/length with the 
                    // string "value":
                    if (length == value.Length) 
                    {
                        Array.Copy(value.ToCharArray(), 0, 
                                 document.TextArray, start, length);
                    }
                    else 
                    {
                        char[] newText = 
                            new char[document.TextArray.Length + 
                                           value.Length - length];
                        Array.Copy(document.TextArray, 0, newText, 
                                                        0, start);
                        Array.Copy(value.ToCharArray(), 0, newText, 
                                             start, value.Length);
                        Array.Copy(document.TextArray, start + length,
                                   newText, start + value.Length,
                                  document.TextArray.Length - start
                                                            - length);
                        document.TextArray = newText;
                    }
                }                    
                else
                    throw new IndexOutOfRangeException();
            }
        }


        // Get the count of words in the containing document:
        public int Count 
        {
            get 
            { 
                int count = 0, start = 0, length = 0;
                while (GetWord(document.TextArray, start + length, 0, 
                                              out start, out length))
                    ++count;
                return count; 
            }
        }
    }


    // Type allowing the document to be viewed like an "array" 
    // of characters:
    public class CharacterCollection
    {
        readonly Document document;  // The containing document


        internal CharacterCollection(Document d)
        {
          document = d; 
        }


        // Indexer to get and set characters in the containing document:
        public char this[int index] 
        {
            get 
            { 
                return document.TextArray[index]; 
            }
            set 
            { 
                document.TextArray[index] = value; 
            }
        }


        // Get the count of characters in the containing document:
        public int Count 
        {
            get 
            { 
                return document.TextArray.Length; 
            }
        }
    }


    // Because the types of the fields have indexers, 
    // these fields appear as "indexed properties":
    public WordCollection Words;
    public CharacterCollection Characters;


    private char[] TextArray;  // The text of the document. 


    public Document(string initialText)
    {
        TextArray = initialText.ToCharArray();
        Words = new WordCollection(this);
        Characters = new CharacterCollection(this);
    }


    public string Text 
    {
        get 
        { 
           return new string(TextArray); 
        }
    }
}


class Test
{
    static void Main()
    {
        Document d = new Document(
           "peter piper picked a peck of pickled peppers. How many pickled peppers did peter piper pick?"
        );


        // Change word "peter" to "penelope":
        for (int i = 0; i < d.Words.Count; ++i) 
        {
            if (d.Words[i] == "peter") 
                d.Words[i] = "penelope";
        }


        // Change character "p" to "P"
        for (int i = 0; i < d.Characters.Count; ++i) 
        {
            if (d.Characters[i] == 'p')
                d.Characters[i] = 'P';
        }
        
        Console.WriteLine(d.Text);
    }
}

indexedproperty.cs


This sample shows how C# classes can declare indexed properties to represent an array-like collection of different kinds of things.
This sample contains the source code for the Indexed Properties Tutorial.


Building and Running the Sample Within Visual Studio
To build and run the Indexed Properties sample 
1. Open the solution (IndexedProperties.sln). 
2. From the Debug menu, click Start Without Debugging. 


Building and Running the Sample from the Command Line
To build and run the Indexed Properties sample 
* Type the following at the command prompt: 
    csc indexedproperty.cs
    indexedproperty



// indexedproperty.cs
using System;


public class Document
{
    // Type allowing the document to be viewed like an array of words:
    public class WordCollection
    {
        readonly Document document;  // The containing document


        internal WordCollection(Document d)
        {
           document = d;
        }


        // Helper function -- search character array "text", starting at
        // character "begin", for word number "wordCount." Returns false
        // if there are less than wordCount words. Sets "start" and
        // length" to the position and length of the word within text:
        private bool GetWord(char[] text, int begin, int wordCount, 
                                       out int start, out int length) 
        { 
            int end = text.Length;
            int count = 0;
            int inWord = -1;
            start = length = 0; 


            for (int i = begin; i <= end; ++i) 
            {
                bool isLetter = i < end && Char.IsLetterOrDigit(text[i]);


                if (inWord >= 0) 
                {
                    if (!isLetter) 
                    {
                        if (count++ == wordCount) 
                        {
                            start = inWord;
                            length = i - inWord;
                            return true;
                        }
                        inWord = -1;
                    }
                }
                else 
                {
                    if (isLetter)
                        inWord = i;
                }
            }
            return false;
        }


        // Indexer to get and set words of the containing document:
        public string this[int index] 
        {
            get 
            { 
                int start, length;
                if (GetWord(document.TextArray, 0, index, out start, 
                                                          out length))
                    return new string(document.TextArray, start, length);
                else
                    throw new IndexOutOfRangeException();
            }
            set 
            {
                int start, length;
                if (GetWord(document.TextArray, 0, index, out start, 
                                                         out length)) 
                {
                    // Replace the word at start/length with the 
                    // string "value":
                    if (length == value.Length) 
                    {
                        Array.Copy(value.ToCharArray(), 0, 
                                 document.TextArray, start, length);
                    }
                    else 
                    {
                        char[] newText = 
                            new char[document.TextArray.Length + 
                                           value.Length - length];
                        Array.Copy(document.TextArray, 0, newText, 
                                                        0, start);
                        Array.Copy(value.ToCharArray(), 0, newText, 
                                             start, value.Length);
                        Array.Copy(document.TextArray, start + length,
                                   newText, start + value.Length,
                                  document.TextArray.Length - start
                                                            - length);
                        document.TextArray = newText;
                    }
                }                    
                else
                    throw new IndexOutOfRangeException();
            }
        }


        // Get the count of words in the containing document:
        public int Count 
        {
            get 
            { 
                int count = 0, start = 0, length = 0;
                while (GetWord(document.TextArray, start + length, 0, 
                                              out start, out length))
                    ++count;
                return count; 
            }
        }
    }


    // Type allowing the document to be viewed like an "array" 
    // of characters:
    public class CharacterCollection
    {
        readonly Document document;  // The containing document


        internal CharacterCollection(Document d)
        {
          document = d; 
        }


        // Indexer to get and set characters in the containing document:
        public char this[int index] 
        {
            get 
            { 
                return document.TextArray[index]; 
            }
            set 
            { 
                document.TextArray[index] = value; 
            }
        }


        // Get the count of characters in the containing document:
        public int Count 
        {
            get 
            { 
                return document.TextArray.Length; 
            }
        }
    }


    // Because the types of the fields have indexers, 
    // these fields appear as "indexed properties":
    public WordCollection Words;
    public CharacterCollection Characters;


    private char[] TextArray;  // The text of the document. 


    public Document(string initialText)
    {
        TextArray = initialText.ToCharArray();
        Words = new WordCollection(this);
        Characters = new CharacterCollection(this);
    }


    public string Text 
    {
        get 
        { 
           return new string(TextArray); 
        }
    }
}


class Test
{
    static void Main()
    {
        Document d = new Document(
           "peter piper picked a peck of pickled peppers. How many pickled peppers did peter piper pick?"
        );


        // Change word "peter" to "penelope":
        for (int i = 0; i < d.Words.Count; ++i) 
        {
            if (d.Words[i] == "peter") 
                d.Words[i] = "penelope";
        }


        // Change character "p" to "P"
        for (int i = 0; i < d.Characters.Count; ++i) 
        {
            if (d.Characters[i] == 'p')
                d.Characters[i] = 'P';
        }
        
        Console.WriteLine(d.Text);
    }
}