Как преобразовать относительный URL в абсолютный?

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
ReMAG
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 54
Зарегистрирован: 02.10.2005 (Вс) 4:01
Откуда: Киев

Как преобразовать относительный URL в абсолютный?

Сообщение ReMAG » 06.02.2006 (Пн) 23:03

:?:
Без использования WinInet, можно?
Никогда не говори "никогда"...

vvs_adm
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1492
Зарегистрирован: 03.02.2005 (Чт) 3:45
Откуда: оттуда ;)

Сообщение vvs_adm » 07.02.2006 (Вт) 0:15

Относительный URL описывает положение ресурса, на который указывает ссылка, относительно URL текущего документа => Абсолютный URL = URL текущего документа + Относительный URL

P.S.: если приглядеться повнимательнее, то можно заметить, что ни про какой WinInet при этом не говорится ни слова :lol:
Никогда не откладывай на завтра то, что можно ... отложить на послезавтра!

ReMAG
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 54
Зарегистрирован: 02.10.2005 (Вс) 4:01
Откуда: Киев

Сообщение ReMAG » 07.02.2006 (Вт) 1:15

vvs_adm писал(а):Относительный URL описывает положение ресурса, на который указывает ссылка, относительно URL текущего документа => Абсолютный URL = URL текущего документа + Относительный URL


Простой пример:
URL текущего документа: http://mysite.com/first/index.htm
Относительный URL: ../secoond/index2.htm

Что в данно случае должна Означать операция "+" между ними?

P.S. Если присмотреться повнимательнее, то можно заметить, что в цитате нет ни слова о преобразовании URL'ов.
Никогда не говори "никогда"...

skiperski
Идеолог
Идеолог
Аватара пользователя
 
Сообщения: 1386
Зарегистрирован: 25.06.2002 (Вт) 15:52

Сообщение skiperski » 07.02.2006 (Вт) 2:08

В общем случае, если нужнен только собственно сам URL и без разницы как он выглядит, то можно просто конкатинировать текущий URL (без имени страницы и со слэшем справа) с относительным адресом. Браузер сам разберётся куда надо обратиться.

Т.е. такие адреса валидны:
http://www.vbstreets.ru/VBA/default.aspx
http://www.vbstreets.ru/VBA/Sources/../default.aspx
http://www.vbstreets.ru/VBA/Sources/../../default.aspx
http://www.vbstreets.ru/VBA/Sources/./default.aspx

Если же нужен чистый адрес, то в случае не использования сторонних компонент нужно самому разбирать локальный адрес. В принципе довольно просто:
1. ../ - переход в родительский уровнь
2. / - переход в корневой уровень
3. символ или ./ - от текущего уровня

Для правильного преобразования необходимо также разобрать и текущий адрес для выделения собственно имени хоста и определения наличия слэша справа и, возможно, устраненеия переходов в верхние уровни. Потом формировать адрес исходя из правил описанных выше.

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 07.02.2006 (Вт) 6:23

MS рекомендует не заниматься сращиванием путей самостоятельно.

http://msdn.microsoft.com/library/en-us ... ombine.asp
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

ReMAG
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 54
Зарегистрирован: 02.10.2005 (Вс) 4:01
Откуда: Киев

Сообщение ReMAG » 07.02.2006 (Вт) 20:52

skiperski писал(а):В общем случае, если нужнен только собственно сам URL и без разницы как он выглядит, то можно просто конкатинировать текущий URL (без имени страницы и со слэшем справа) с относительным адресом. Браузер сам разберётся куда надо обратиться.


Пойдет, спасибо )
Никогда не говори "никогда"...

ANDLL
Великий гастроном
Великий гастроном
Аватара пользователя
 
Сообщения: 3450
Зарегистрирован: 29.06.2003 (Вс) 18:55

Сообщение ANDLL » 07.02.2006 (Вт) 23:03

skiperski писал(а):В общем случае, если нужнен только собственно сам URL и без разницы как он выглядит, то можно просто конкатинировать текущий URL (без имени страницы и со слэшем справа) с относительным адресом. Браузер сам разберётся куда надо обратиться.

Нельзя...
Ну например, http://aaa.com/A/page.html, относительно него задаем /hh.htm
Конкотенируем, и что видим? http://aaa.com/A/page.html/hh.htm ? Ну или не худой конец http://aaa.com//hh.htm
В любом случае совершенно не верно. Короче, слушайте непотребного GSerg'а.... Обычно это бывает полезно...
Гастрономия - наука о пище, о ее приготовлении, употреблении, переварении и испражнении.
Блог

vvs_adm
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1492
Зарегистрирован: 03.02.2005 (Чт) 3:45
Откуда: оттуда ;)

Сообщение vvs_adm » 11.02.2006 (Сб) 17:40

ANDLL писал(а):
skiperski писал(а):В общем случае, если нужнен только собственно сам URL и без разницы как он выглядит, то можно просто конкатинировать текущий URL (без имени страницы и со слэшем справа) с относительным адресом. Браузер сам разберётся куда надо обратиться.

Нельзя...
Ну например, http://aaa.com/A/page.html, относительно него задаем /hh.htm
Конкотенируем, и что видим? http://aaa.com/A/page.html/hh.htm ?
skiperski писал(а):В общем случае, если нужнен только собственно сам URL и без разницы как он выглядит, то можно просто конкатинировать текущий URL (без имени страницы и со слэшем справа) с относительным адресом. Браузер сам разберётся куда надо обратиться.

Т.е. такие адреса валидны:
http://www.vbstreets.ru/VBA/default.aspx
http://www.vbstreets.ru/VBA/Sources/../default.aspx
http://www.vbstreets.ru/VBA/Sources/../../default.aspx
http://www.vbstreets.ru/VBA/Sources/./default.aspx
Никогда не откладывай на завтра то, что можно ... отложить на послезавтра!

ANDLL
Великий гастроном
Великий гастроном
Аватара пользователя
 
Сообщения: 3450
Зарегистрирован: 29.06.2003 (Вс) 18:55

Сообщение ANDLL » 11.02.2006 (Сб) 17:59

Перечитаем еще раз мой топик. Особенно про худой конец.
Гастрономия - наука о пище, о ее приготовлении, употреблении, переварении и испражнении.
Блог

vvs_adm
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1492
Зарегистрирован: 03.02.2005 (Чт) 3:45
Откуда: оттуда ;)

Сообщение vvs_adm » 11.02.2006 (Сб) 18:12

ANDLL писал(а):Особенно про худой конец.
Согласен, что там немного неправильно, но нельзя там тоже не подходит. Относительные ссылки могут быть и без первого слеша. Достаточно лишь проверить его наличие\отсутствие. Да и кроме непривычного вида, чем тебе http://aaa.com//hh.htm еще не нравится?
Никогда не откладывай на завтра то, что можно ... отложить на послезавтра!

Alexanbar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1727
Зарегистрирован: 13.04.2004 (Вт) 23:04
Откуда: Волгоградская обл.

Сообщение Alexanbar » 11.02.2006 (Сб) 19:04

По-моему, в urlmon.dll есть нужные функции. Только я , по незнанию, писал свои.

ANDLL
Великий гастроном
Великий гастроном
Аватара пользователя
 
Сообщения: 3450
Зарегистрирован: 29.06.2003 (Вс) 18:55

Сообщение ANDLL » 13.02.2006 (Пн) 9:10

vvs_adm писал(а):
ANDLL писал(а):Особенно про худой конец.
Согласен, что там немного неправильно, но нельзя там тоже не подходит. Относительные ссылки могут быть и без первого слеша. Достаточно лишь проверить его наличие\отсутствие. Да и кроме непривычного вида, чем тебе http://aaa.com//hh.htm еще не нравится?

Тем что это неправильно.
Дам справку.
http://aaa.com/aaa/bbb.htm относительно него ук. /ccc.htm, имеется ввиду
http://aaa.com/ccc.htm а не http://aaa.com/aaa/ccc.htm как ты думаеш.
Иными словами наличие и отсутствие слыша перед именем файла имеет принципиальное значение, а не просто для крсоты там.
Кроме того, это просто пример, там ведь еще нюансы есть :wink:
Не будь похожим на http://bbs.vbstreets.ru/viewtopic.php?p=6585214#6585214
если чтото сработало в ограниченном числе случаев, не значит еще что это правильно :wink:
Гастрономия - наука о пище, о ее приготовлении, употреблении, переварении и испражнении.
Блог

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 13.02.2006 (Пн) 9:21

ANDLL писал(а):Иными словами наличие и отсутствие слыша перед именем файла имеет принципиальное значение, а не просто для крсоты там.

Да, причем дальнейшее поведение web-сервера зависит от его настроек касательно этого финального слэша.
Lasciate ogni speranza, voi ch'entrate.

vvs_adm
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1492
Зарегистрирован: 03.02.2005 (Чт) 3:45
Откуда: оттуда ;)

Сообщение vvs_adm » 13.02.2006 (Пн) 20:03

ANDLL
Ой, извиняюсь. Перечитал внимательнее пост Skipersky, более того то, что сам же красным и выделил. Стормозил, это действительно в корне неверно. :oops:
ANDLL писал(а):Дам справку.
http://aaa.com/aaa/bbb.htm относительно него ук. /ccc.htm, имеется ввиду
http://aaa.com/ccc.htm а не http://aaa.com/aaa/ccc.htm как ты думаеш.
Да я так и не думал никогда :)
Никогда не откладывай на завтра то, что можно ... отложить на послезавтра!

skiperski
Идеолог
Идеолог
Аватара пользователя
 
Сообщения: 1386
Зарегистрирован: 25.06.2002 (Вт) 15:52

Сообщение skiperski » 15.02.2006 (Ср) 17:56

Подождите пинать! Дайте оправдаться! :)

Если писать какую-нибудь универсальную вещь, то, несомненно, лучше пользоваться по совету GSerg'а уже готовой и отлаженой функцией, но... Бывают простейшие ситуации, когда, например, исходный URL известен и все ссылки относительные и не от корня, и смущает только непрезентабельный вид получаемых конкатенацией ссылок, и лень парсить и т.д. А ситуацию с двумя слэшами я просто недосмотрел. Предложением выше я уже поставил ещё одно ограничение (и не от корня) на рамки использования метода :).

По поводу слэша справа: это, несомненно, существенно для сервера, но вопрос в том откуда мы получаем в результате исходный URL? Если исходный - это URL введённый в строку поиска браузера, то задача изначально не имеет универсального решения, т.к. с помощью внутреннего редиректа мы можем оказаться где угодно и исходный URL нам никак не поможет. В случае, если мы получаем URL из какого-либо объекта, читающий заголовки HTTP, то он уже, по идее, должен быть полным, т.е. с именем конкретной выводимой страницы (даже, кажется, есть что-то вроде BaseURL с уже обрезанным именем страницы и присобаченным справа слэшем), и тогда справедливо всё изложенное выше.

skiperski
Идеолог
Идеолог
Аватара пользователя
 
Сообщения: 1386
Зарегистрирован: 25.06.2002 (Вт) 15:52

Сообщение skiperski » 15.02.2006 (Ср) 19:33

Кстати, кто-то может объяснить такое загадочное поведение функции от MS?

Декларация
Код: Выделить всё
Option Explicit

Public Declare Function UrlCombineA _
Lib "shlwapi.dll" ( _
        ByVal pszBase As String, _
        ByVal pszRelative As String, _
        ByRef pszCombined As String, _
        ByRef pcchCombined As Integer, _
        ByVal dwFlags As Integer _
    ) As Long

Обёртка
Код: Выделить всё
Public Function UrlCombine(ByVal Base As String, ByVal Relative As String) As String
   
    Dim s As String
    Dim sLen As Integer
    Dim res As Long
   
    s = String$(100, Chr$(0))
    sLen = Len(s)
   
    res = UrlCombineA(Base, Relative, ByVal s, sLen, 0)
    Debug.Print res, sLen,
   
    UrlCombine = Left$(s, sLen)
   
End Function

Тестовый вызов
Код: Выделить всё
Function test()
    Debug.Print UrlCombine("http://aaa", "bbb")
End Function

Immediate
Код: Выделить всё
0             14           http://aaa/bbb
-2147024809    15                         
-2147024809    15                         
0             14           http://aaa/bbb
0             14           http://aaa/bbb
0             14           http://aaa/bbb
0             14           http://aaa/bbb
0             14           http://aaa/bbb
0             14           http://aaa/bbb
0             14           http://aaa/bbb
0             14           http://aaa/bbb
-2147024809    15                         
-2147024809    15                         
-2147024809    15                         
0             14           http://aaa/bbb
0             14           http://aaa/bbb
0             14           http://aaa/bbb
0             14           http://aaa/bbb
0             14           http://aaa/bbb
0             14           http://aaa/bbb
0             14           http://aaa/bbb
-2147024809    15                         
-2147024809    15                         
-2147024809    15                         
-2147024809    15                         
-2147024809    15                         
-2147024809    15                         
-2147024809    15                         
-2147024809    15                         
-2147024809    15                         
-2147024809    15                         
-2147024809    15                         
0             14           http://aaa/bbb
0             14           http://aaa/bbb
0             14           http://aaa/bbb
0             14           http://aaa/bbb
0             14           http://aaa/bbb
0             14           http://aaa/bbb
0             14           http://aaa/bbb

И как это понимать? Она работает когда хочет! Или чего-то не так задекларировал? В чём дело? Никаких изменений в коде, просто последовательный вызов функции test(). Никакой закономерности я не наблюдаю.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 15.02.2006 (Ср) 19:45

"ByRef pszCombined As String" вызывает большие сомнения.
Изображение

skiperski
Идеолог
Идеолог
Аватара пользователя
 
Сообщения: 1386
Зарегистрирован: 25.06.2002 (Вт) 15:52

Сообщение skiperski » 15.02.2006 (Ср) 19:50

В данном случае это не важно, т.к. замена на ByVal ничего не меняет :(

Кстати, если в test() воткнуть цикл, например в 50 повторений, то обнаруживается какая-то закономерность: 8 раз срабатывает, потом 8 раз нет. После 3-го запуска test()'а VB просто сваливается.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 15.02.2006 (Ср) 19:58

Только что потестил: работает стабильно.
Так что "дибаж сибя!" (с)
Изображение

skiperski
Идеолог
Идеолог
Аватара пользователя
 
Сообщения: 1386
Зарегистрирован: 25.06.2002 (Вт) 15:52

Сообщение skiperski » 15.02.2006 (Ср) 20:04

Каким образом? :shock: Код-то одинаковый! Что можно дебажить?

ЗЫ: VB валится на 126-ом вызове. Жаль, что не 127-ом. Можно было бы предположить, что переполняется какой-то счётчик.

ЗЫ2: Это всё было верно для длины не в 100, а в 2083 символа. Видимо где-то что-то переполнялось. При длине буфера в 100 символов VB не падает и положительный результат достигается чаще, но тоже не всегда.

ЗЫ3: tyomitch, проверь, пожалуйста в цикле, скажем раз 200.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 15.02.2006 (Ср) 20:24

Проверил. Результат всегда правильный.
В районе 130-го раза (каждый раз по-новому) -- вылетает.
"-2147024809 15" не приходит никогда.
Изображение

skiperski
Идеолог
Идеолог
Аватара пользователя
 
Сообщения: 1386
Зарегистрирован: 25.06.2002 (Вт) 15:52

Сообщение skiperski » 15.02.2006 (Ср) 22:31

Странно и не понятно всё это. У кого будут идеи - отзовитесь. Особенно уповаю на GSerg'а как подвигшего меня на это исследование.

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 16.02.2006 (Чт) 6:33

Код: Выделить всё
Private Sub Form_Load()
  Dim i As Long
  Dim s1 As String, s2 As String, out As String
 
  s1 = "http://aaa"
  s2 = "bbb"
 
  out = String$(INTERNET_MAX_PATH_LENGTH, 0)
 
  For i = 1 To 10000
    If UrlCombine(s1, s2, out, Len(out), 0) <> 0 Then
      Debug.Print "!!!"
    End If
  Next
End Sub


Работает на 100%. При любом значении INTERNET_MAX_PATH_LENGTH.


ЗЫ. Integer -> Long
ЗЗЫ. -2147024809 = 0x80070057 = E_INVALIDARG.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

skiperski
Идеолог
Идеолог
Аватара пользователя
 
Сообщения: 1386
Зарегистрирован: 25.06.2002 (Вт) 15:52

Сообщение skiperski » 16.02.2006 (Чт) 14:44

GSerg писал(а):Работает на 100%.

И как это понимать? У меня и у tyomitch'а VB вылится, а у тебя всё нормально. :shock: Получается с такой работоспособностью эту функцию использовать нельзя. Или всё же где-то она не правильно задекларирована?

GSerg писал(а):При любом значении INTERNET_MAX_PATH_LENGTH.

Кстати, какое значение у этой константы? Я нашел такие декларации

Код: Выделить всё
Const INTERNET_MAX_HOST_NAME_LENGTH As Integer = 256
Const INTERNET_MAX_USER_NAME_LENGTH As Integer = 128
Const INTERNET_MAX_PASSWORD_LENGTH As Integer = 128
Const INTERNET_MAX_PATH_LENGTH As Integer = 2048
Const INTERNET_MAX_SCHEME_LENGTH As Integer = 32      ' This value is the longest protocol name length.
Const INTERNET_MAX_URL_LENGTH As Integer = INTERNET_MAX_SCHEME_LENGTH + 3 + INTERNET_MAX_PATH_LENGTH

Получается 2083 символа.

GSerg писал(а):ЗЫ. Integer -> Long

Это к чему? Привёл бы лучше свою декларацию функции. Может там где-то у меня ошибка.

GSerg писал(а):ЗЗЫ. -2147024809 = 0x80070057 = E_INVALIDARG.

Описание ошибки я нашел, но прикол в том, что функция вызывается каждый раз с одними и теми же аргументами. Но работает через раз.

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 16.02.2006 (Чт) 15:52

skiperski писал(а):Или всё же где-то она не правильно задекларирована?

Угу.

skiperski писал(а):
GSerg писал(а):ЗЫ. Integer -> Long

Это к чему? Привёл бы лучше свою декларацию функции. Может там где-то у меня ошибка.


Твоя.
Код: Выделить всё
Public Declare Function UrlCombineA _
Lib "shlwapi.dll" ( _
        ByVal pszBase As String, _
        ByVal pszRelative As String, _
        ByRef pszCombined As String, _
        ByRef pcchCombined As Integer, _
        ByVal dwFlags As Integer _
    ) As Long


Моя.
Код: Выделить всё
Public Declare Function UrlCombineA _
Lib "shlwapi.dll" ( _
        ByVal pszBase As String, _
        ByVal pszRelative As String, _
        ByVal pszCombined As String, _
        ByRef pcchCombined As Long, _
        ByVal dwFlags As Long _
    ) As Long


Указатель на integer и указатель на long - две большие разницы.
dwFlags-то ладно, при передаче в стек VB дополнит нулями (хотя...).
А вот указатель уж увольте...
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

skiperski
Идеолог
Идеолог
Аватара пользователя
 
Сообщения: 1386
Зарегистрирован: 25.06.2002 (Вт) 15:52

Сообщение skiperski » 16.02.2006 (Чт) 16:18

Что за чудеса?!! У меня при подборе типа параметров заработало только с Integer. Я вначале написал точно как в твоём варианте, только pszCombined как ByRef - вылетало с ошибкой -2147467261 Invalid Pointer. The application is using arguments that are of the wrong type, are out of acceptable range, or are in conflict with one another

А теперь всё пучком :?. Странно всё это. И спасибо.

ЗЫ: а что с INTERNET_MAX_PATH_LENGTH? Найденные декларации верны?

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 16.02.2006 (Чт) 17:35

Угу.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: AhrefsBot и гости: 62

    TopList