Ostatnio bawię się odpytywaniem Active Directory o użytkowników, grupy i jednostki organizacyjne i natrafiłem na kilka dość ciekawych przypadków kiedy to znaki specjalne nie są zamieniane, albo zamienione nie działają poprawnie :) co jest trochę… dziwne ale tak bywa :)
Ogólny problem ze znakami specjalnymi w AD jest taki, iż w niektórych przypadkach można zastosować backslash w celu określenia, że kolejny znak po nim ma być traktowany tak jak został zapisany a nie jako znak specjalny, a w niektórych nie. Czyli na przykład nazwa grupy USERS/POWER USERS powinna zostać zamieniona na USERS/POWER USERS ale w zależności od kontekstu znak / musi zostać zamieniony na inny.
- Mianowicie, kiedy my odpytujemy się AD o dany obiekt zawierający znak specjalny to my musimy zadbać o konwersję znaków na poprawne.
- Kiedy pobieramy wynik zapytania w postaci ścieżki (SearchResult.Path), .NET Framework zadba o konwersję znaków specjalnych na poprawne escape characters oraz dodatkowo doda nam protokół LDAP:// do początku Distinguished Name od obiektu, którego znaleźliśmy.
- Kiedy pobieramy własność Distinguished Name obiektu z DirecotryEntry to dostaniemy ciąg znaków bez zamienionych znaków specjalnych oraz bez protokołu LDAP://.
Różnica pomiędzy 2 i 3 jest taka, że SearchResult.Path zwraca własność ADsPath zaś Distinguished Name jest trochę inną wartością, jednakże za pomocą obydwóch wartości możemy obiekt DirectoryEntry, który zwróci nam odpowiedni obiekt z AD.
Żeby było zabawniej kiedy wyszukujemy musimy wykonać inną podmianę niż w przypadku 2 i 3 :)
Dla elementów, które wyszukujemy musimy podmienić wszystkie zwykłe nawiasy (), Slash, gwiazdkę, backslash, i tak zwany character return/NULL ( ), zaś w Distinguished Name musi zapewnić by przecinki były dobrze odbierane jak i slash – znaków jest więcej a można do nich zaliczyć <>, „”, przecinek, +, =, ; i spację.
Sprawę pierwszą z wyszukiwaniem, możemy rozwiązać za pomocą Extension Method:
/// <summary> /// Replaces special characters in search string. /// </summary> /// <param name="source">The search string.</param> /// <param name="escapeWildcards">if set to <c>true</c> escape wildcards.</param> /// <returns>String with proper characters.</returns> /// <remarks> /// All characters are replaced, please see the full list: /// http://msdn.microsoft.com/en-us/library/aa746475%28VS.85%29.aspx /// </remarks> public static string ReplaceSpecialCharsInSearch(this string source, bool escapeWildcards) { source = source.Replace("\", "\5c").Replace("/", "\2f");; source = source.Replace("(", "\28").Replace(")", "\29"); source = source.Replace("