У нас есть приложение PHP, зашифрованное с помощью IonCube. Это приложение вызывает XML-файл, хранящийся в том же каталоге, чтобы получить его параметры конфигурации.
Лицензия на программное обеспечение позволяет нам использовать его на любом количестве имеющихся у нас доменов, но из-за шифрования нам потребуется установить скрипт на каждый отдельный домен, который у нас есть (у нас их несколько тысяч). Мы хотим, чтобы все домены указывали в одно и то же место на одном сервере и просто установили приложение за один раз. Когда приложение пытается прочитать файл настроек конфигурации XML, мы хотим предоставить ему другую версию информации конфигурации в зависимости от домена, из которого пользователь просматривает. Данные конфигурации будут храниться в базе данных, которую мы создадим.
Поскольку приложение зашифровано, мы не можем сделать файл конфигурации переменной или указать его на другой тип файла, который мог бы выполнять некоторую логику, и мы не можем изменить способ обработки файла конфигурации.
Есть идеи, как это можно сделать в рамках указанных выше ограничений?
Единственное, что я придумал до сих пор, - это использовать файловую систему пользовательского пространства (возможно, основанную на FUSE) для этого ... но я надеюсь, что есть другой способ. Мы запускаем это на платформе LAMP.
Мне кажется, ваша проблема разбивается на две области ... первая - это способ заставить программу передавать информацию о конфигурации вашему веб-приложению, а вторая - способ заставить эту программу что-то знать о том, кто называя это, чтобы он мог передать право config.
Первую проблему можно решить с помощью именованного канала. Сделайте файл конфигурации (скажем, config.xml) именованным каналом или FIFO, затем настройте программу, которая записывает в этот именованный канал.
Вторая проблема более сложная, поскольку программа, которая пишет в именованный канал, на самом деле ничего не знает о том, кто находится на другом конце канала. Вы можете решить эту проблему с помощью некоторого творческого подхода к lsof. Как только вы узнаете, кто вам звонит, вы можете попытаться найти полезную информацию в их среде, которая поможет вам узнать, какой сайт на самом деле посещается.
Вот довольно хитрый perl, который пытается решить обе проблемы. Вы, несомненно, захотите настроить это в соответствии со своей средой, но, надеюсь, это немного поможет.
#! /usr/bin/perl
use strict;
use POSIX qw(mkfifo);
my $f = "the_config.txt";
unlink $f if -e $f;
mkfifo($f, 0644) or die "mkfifo $f failed: $!\n";
while (1) {
my ($interesting_command, $interesting_pid);
unless (-p $f) {
unlink $f;
mkfifo($f, 0700) or die "mkfifo $f failed: $!\n";
}
# the open blocks until someone else tries to read the pipe
open(FIFO, "> $f") or die "can't write $f: $!\n";
# figure out who is on the other end?
open(LSOF, "lsof $f |") or die "can't run lsof: $!\n";
while (<LSOF>) {
chomp;
my ($command, $pid, $user, $fd) = split(m/\s+/, $_);
next unless $fd =~ m/\d+r$/; # we are only interested in the reader
$interesting_command = $command;
$interesting_pid = $pid;
}
close LSOF;
if (!defined($interesting_pid)) {
print "couldn't find the corresponding pid, :-(\n";
close FIFO;
sleep 2;
next;
}
print FIFO "I see you process $interesting_pid ($interesting_command)\n"
or die "couldn't print to $f: $!\n";
my $the_site = get_site($interesting_pid);
print FIFO "looks like your server name was $the_site\n"
or die "couldn't print to $f: $!\n";
close FIFO or die "couldn't close $f: $!\n";
sleep 2;
print "looping\n";
}
sub get_site {
my $pid = shift;
my $server_name;
# extract data from his environment...
local($/) = "\0";
open(PE, "/proc/$pid/environ") or die "can't open environ for pid $pid\n";
while (<PE>) {
my ($key, $val) = split(m/=/, $_);
next unless $key eq 'SERVER_NAME';
$server_name = $val;
}
close(PE);
if ($server_name eq '') {
return "not found, :-(\n";
}
return $server_name;
}
Я проверил это, настроив простой сценарий CGI для чтения файла:
#! /usr/bin/perl
print "Content-type: text/html\n\n";
print "<html><head></head><body><pre>\n";
open(F, "/full_path_to_the_named_pipe/the_config.txt");
while (<F>) {
print;
}
close(F);
print "</pre></body></html>\n";
При нажатии на нее с моего личного сайта печатается доменное имя, которое использовалось для этого.
Очевидно, вам нужно будет убедиться, что пользователь, выполняющий сценарий, имеет разрешение на выполнение lsof и чтение среды веб-сервера, иначе он не сможет извлечь имя сервера. Вам также необходимо убедиться, что скрипт, который пишет в именованный канал, всегда работает, иначе ваше приложение php заблокируется навсегда. Вероятно, есть и другие предостережения, но, надеюсь, этого будет достаточно, чтобы вы начали.