-3

我正在编写一些解析 Apache 配置文件的代码。

正在解析的文件:

NameVirtualHost *:80

#
# VirtualHost example:
# Almost any Apache directive may go into a VirtualHost container.
# The first VirtualHost section is used for all requests that do not
# match a ServerName or ServerAlias in any <VirtualHost> block.
#
<VirtualHost *:80>
    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot "c:/Apache2/docs/dummy-host.example.com"
    ServerName dummy-host.example.com
    ServerAlias www.dummy-host.example.com
    ErrorLog "logs/dummy-host.example.com-error.log"
    CustomLog "logs/dummy-host.example.com-access.log" common
</VirtualHost>

<VirtualHost *:80>
    ServerAdmin webmaster@dummy-host2.example.com
    DocumentRoot "c:/Apache2/docs/dummy-host2.example.com"
    ServerName dummy-host2.example.com
    ErrorLog "logs/dummy-host2.example.com-error.log"
    CustomLog "logs/dummy-host2.example.com-access.log" common
</VirtualHost>

这是解析器方法 filePath 是上面文件的路径。

public void readFile(string filePath)
    {
        /* read the file path provided */
        StreamReader reader = new StreamReader(filePath);
        string content = reader.ReadToEnd();

        /* remove the comments from the file */
        string[] lines = content.Split('\n');
        string newContent = "";
        foreach(string line in lines){
            char[] chars = line.ToCharArray();
            if(chars[0] != '#'){
                newContent += line+"\n";
            }
        }

        /* search for Virtual hosts and save them */
        string regEx = "<VirtualHost [^>]*>[^<]*</VirtualHost>";
        MatchCollection coll = Regex.Matches(newContent, regEx, RegexOptions.IgnoreCase);
        string[] vhosts = new string[coll.Count];
        int counter = 0;

        /* go though them and save them into a string array */
        foreach (Match match in coll)
        {
            vhosts[counter] = (match.Value);
            counter++;
        }

        /* set the number of vhosts */
        hosts = new vhost[vhosts.Count()];

        /* go though the string array */
        for (int c = 0; c < vhosts.Count(); c++ )
        {

            MessageBox.Show("hi");

            /* set the host string to current vhost string */
            string host = vhosts[c];
            /* get the lines from the vhost */
            string[] lines2 = host.Split('\n');
            /* create the new save object in the array of vhosts */
            hosts[c] = new vhost();
            /* tell the console what were proccessing */
            Console.WriteLine((c+1).ToString() + " of " + vhosts.Count().ToString());
            /* for each line add the rule to the correct vHost via the counter for looping though the vhosts */
            for (int i = 0; i < lines2.Count(); i++)
            {
                /* set the string line to the line were currently on */
                string line = lines2[i];
                /* get rid of whitespace and split on the space (' ')*/
                string[] param = line.Trim().Split(' ');
                /* provde the current vHost number and the key and value in the config file */
                hosts[c].addRule(param[0], param[1]);
            }
        }
    }

hosts是一个vHost[]虚拟主机如下

class vhost
{
    public vhostRules[] rules = new vhostRules[1];

    public string getRuleValue(string key)
    {
        vhostRules[] currentRules = rules;
        rules = new vhostRules[currentRules.Count()];
        for (int i = 0; i < currentRules.Count(); i++)
        {
            vhostRules Rule = currentRules[i];
            if (key == Rule.key)
                return Rule.value;
        }
        return "";
    }

    public vhostRules getRule(string key)
    {
        vhostRules[] currentRules = rules;
        rules = new vhostRules[currentRules.Count()];
        for (int i = 0; i < currentRules.Count(); i++)
        {
            vhostRules Rule = currentRules[i];
            if (key == Rule.key)
                return Rule;
        }
        return new vhostRules();
    }

    public vhostRules[] getRules()
    {
        return rules;
    }

    public void addRule(string key, string rule)
    {
        vhostRules[] currentRules = rules;
        rules = new vhostRules[currentRules.Count()];
        int counter = 0;
        for (int i = 0; i < currentRules.Count(); i++)
        {
            vhostRules Rule = currentRules[i];
            rules[i] = Rule;
            counter++;
        }
        rules[counter] = new vhostRules();
        rules[counter].key = key;
        rules[counter].value = rule;
    }

    public void removeRule(string key)
    {
        vhostRules[] currentRules = rules;
        rules = new vhostRules[currentRules.Count()];
        for (int i = 0; i < currentRules.Count(); i++)
        {
            vhostRules Rule = currentRules[i];
            if (key != Rule.key)
                rules[i] = Rule;
        }
    }

    public void changeRule(string key, string value)
    {
        vhostRules[] currentRules = rules;
        rules = new vhostRules[currentRules.Count()];
        for (int i = 0; i < currentRules.Count(); i++)
        {
            vhostRules Rule = currentRules[i];
            if (key != Rule.key)
            {
                rules[i] = Rule;
                rules[i].value = value;
            }
        }
    }
}

vhostRules 对象

class vhostRules { public string key; public string value; }

并且vhostRules基本上是一个保存key和value的类

现在问题hosts[c].addRule(param[0], param[1]);出在上面的读取文件上,你可以看到它addRule在类中再次调用,vhost即使我为空 addRule 所以里面没有代码仍然不起作用。

这是我可以显示问题的唯一方法,没有更小的方法可以复制,因为错误似乎与编译的最终结果有关

我发现的唯一方法是注释或hosts[c].addRule(param[0], param[1]);从我的代码中删除然后它可以工作,但是当我清空它时,它不起作用,理论上是不正确的

单步执行代码不会发生错误,它只运行一次循环,

没有错误发生这包括没有无声的死亡没有例外和没有冻结/崩溃

更新 更新的阅读器

try
{
    hosts[c].addRule(param[0], param[1]);
}catch (Exception e) { Console.WriteLine(e.Message); }

提供输出

1 of 2
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
2 of 2
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array

断点信息

param = {string[2]} 
    [0] = "ServerAdmin" 
    [1] = "webmaste

r@dummy-host.example.com"

4

3 回答 3

2

只是为了提供一个实际的答案:

我最初的猜测——这只是一个猜测,因为我们没有我们需要的所有信息——是在循环中的某个地方抛出了一个异常。

我能看到的最有可能的例外是以下行:

hosts[c].addRule(param[0], param[1]);

类中的 addRule 方法vhost做了一些非常时髦的事情,但同样,我们没有所有的信息,所以我不能肯定地说。

我们需要的

我们至少需要知道发生了什么。是否抛出异常?它到达哪条线?它会默默地死去吗?你有没有通过代码?

请帮助我们帮助您...

更新
所以,问题出在某处:

string[] param = line.Trim().Split(' ');                
hosts[c].addRule(param[0], param[1]);            

或者:

public void addRule(string key, string rule)
    {
        vhostRules[] currentRules = rules;
        rules = new vhostRules[currentRules.Count()];
        int counter = 0;
        for (int i = 0; i < currentRules.Count(); i++)
        {
            vhostRules Rule = currentRules[i];
            rules[i] = Rule;
            counter++;
        }
        rules[counter] = new vhostRules();
        rules[counter].key = key;
        rules[counter].value = rule;
    }

或者:

在 的构造函数中vhostRules,如以下行所示:

rules[counter] = new vhostRules();

现在,您在 中用于键值对的键是rules[]什么?

您可以尝试
更改线路:

string[] param = line.Trim().Split(' ');

到:

string[] param = line.Trim().Split(new char[] {' '}, 2);

这将允许您common在某些行的末尾保留...这可能不会导致您的主要问题,但至少可能是一个问题。

更新 2
在上面的行 ( 之后设置断点string[] param = line.Trim().Split(new char[] {' '}, 2);,看看 param 实际设置为什么。添加一个手表,看看param[0] 和 param[1]到底是什么。我感觉它们还可以,实际上是addRule方法中某处抛出异常...

因此,再次在 addRule 方法中的代码周围添加错误处理,并查看输出的内容。查看堆栈跟踪,检查行号,并准确地向我们展示其中发生了什么。

于 2011-04-05T13:58:00.557 回答
2

不能解决您的问题,但至少可以进行一些清理:更改此行:

public vhostRules[] rules = new vhostRules[1];

进入

private List<vhostRules> rules = new List<vhostRules>();

那么您不需要在每次需要添加项目时重新复制该数组,只需.Add()它。

然后你可能会改变

public vhostRules[] getRules()
{
    return rules;
}

进入

using System.Linq;
public vhostRules[] getRules()
{
    return rules.ToArray();
}
于 2011-04-05T15:30:15.307 回答
1

我想我找到了。您为每个虚拟主机定义中的每一行执行此代码:

/* get rid of whitespace and split on the space (' ')*/
string[] param = line.Trim().Split(' ');
/* provde the current vHost number and the key and value in the config file */
hosts[c].addRule(param[0], param[1]);

这假定每行至少包含 2 个空格分隔的值。除了最后一个之外,所有这些都是如此: </VirtualHost>.

我希望你得到一个ArrayIndexOutOfBoundsException(或任何在.NET 中调用的),但似乎有些东西会吞下它。

于 2011-04-05T14:48:28.663 回答