NSURL sorgu özelliğini ayrıştır


82

Gibi bir URL’im var myApp://action/1?parameter=2&secondparameter=3

Mülk sorgusu ile, URL

parameter=2&secondparameter=3

Bunu a NSDictionaryveya a'ya koymanın kolay bir yolu var mı Array?

Çok teşekkürler

Yanıtlar:


54

Bunun gibi bir şey:

NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
for (NSString *param in [url componentsSeparatedByString:@"&"]) {
  NSArray *elts = [param componentsSeparatedByString:@"="];
  if([elts count] < 2) continue;
  [params setObject:[elts lastObject] forKey:[elts firstObject]];
}

Not : Bu örnek koddur. Tüm hata durumları yönetilmez.


2
Hatalı biçimlendirilmiş bir sorgu olması durumunda bu kod çökecektir. Aşağıdaki güvenli çözüme bakın.
BadPirate

2
Tamam, sadece dizi boyutuna bir kontrol ekleyin! Bu kod sadece bir başlangıçtı (her zaman olduğu gibi SO'da). Tüm URL ile uyumlu olmak istiyorsanız, kaçış dizelerini, parçayı (sonunda # kısım) ele almak için daha fazla çalışmanız var ...
Benoît

Sizin için bir düzenleme yapın. Sadece yanıtla soruna dikkatinizi çekmek için oy verdiler. Düzenleme tamamlandıktan sonra onu geri getirebileceğim.
BadPirate

1
Bu kod, özel karakter içermeyen en basit durum değerleri dışında düzeltmeye yakın bile değildir.
Nick Snyder

Bunun yerine son ve ilk nesneyi kullanmalısınız: [params setObject:[elts lastObject] forKey:[elts firstObject]];daha güvenli
Laszlo

148

Sen kullanabilirsiniz queryItemsiçinde URLComponents.

Bu özelliğin değerini aldığınızda, NSURLComponents sınıfı sorgu dizesini ayrıştırır ve orijinal sorgu dizesinde göründükleri sırayla her biri tek bir anahtar / değer çiftini temsil eden bir NSURLQueryItem nesneleri dizisi döndürür.

Swift

let url = "http://example.com?param1=value1&param2=param2"
let queryItems = URLComponents(string: url)?.queryItems
let param1 = queryItems?.filter({$0.name == "param1"}).first
print(param1?.value)

Alternatif olarak, işleri kolaylaştırmak için URL'ye bir uzantı ekleyebilirsiniz.

extension URL {
    var queryParameters: QueryParameters { return QueryParameters(url: self) }
}

class QueryParameters {
    let queryItems: [URLQueryItem]
    init(url: URL?) {
        queryItems = URLComponents(string: url?.absoluteString ?? "")?.queryItems ?? []
        print(queryItems)
    }
    subscript(name: String) -> String? {
        return queryItems.first(where: { $0.name == name })?.value
    }
}

Daha sonra parametreye adıyla erişebilirsiniz.

let url = "http://example.com?param1=value1&param2=param2"
print(url.queryParameters["param1"])

11
iOS7'den beri sorgu. iOS8'den beri queryItems.
Onato

Bu cevap için teşekkürler. Buna ek olarak, NSURLComponents hakkında daha fazla bilgi edinmek için aşağıdaki makaleyi çok yararlı buldum: nshipster.com/nsurl
xaphod

Mükemmel cevap. Teşekkürler!
dpigera

Garip bir şekilde, NSURLComponents, URL'de # karakter varsa çalışmaz. Like http://example.com/abc#abc?param1=value1&param2=param2 queryItems is nil
Pedro

Bunun nedeni, parçanın (#abc) sona ait olmasıdır.
Onato

55

Bu davranış için kullanışlı olabilecek bazı uzantılar yazmak için nedenim vardı. Önce başlık:

#import <Foundation/Foundation.h>

@interface NSString (XQueryComponents)
- (NSString *)stringByDecodingURLFormat;
- (NSString *)stringByEncodingURLFormat;
- (NSMutableDictionary *)dictionaryFromQueryComponents;
@end

@interface NSURL (XQueryComponents)
- (NSMutableDictionary *)queryComponents;
@end

@interface NSDictionary (XQueryComponents)
- (NSString *)stringFromQueryComponents;
@end

Bu yöntemler NSString, NSURL ve NSDictionary'yi genişleterek, sonuçları içeren sorgu bileşenleri dizelerine ve sözlük nesnelerine dönüştürmenize izin verir.

Şimdi ilgili .m kodu:

#import "XQueryComponents.h"

@implementation NSString (XQueryComponents)
- (NSString *)stringByDecodingURLFormat
{
    NSString *result = [self stringByReplacingOccurrencesOfString:@"+" withString:@" "];
    result = [result stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    return result;
}

- (NSString *)stringByEncodingURLFormat
{
    NSString *result = [self stringByReplacingOccurrencesOfString:@" " withString:@"+"];
    result = [result stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    return result;
}

- (NSMutableDictionary *)dictionaryFromQueryComponents
{
    NSMutableDictionary *queryComponents = [NSMutableDictionary dictionary];
    for(NSString *keyValuePairString in [self componentsSeparatedByString:@"&"])
    {
        NSArray *keyValuePairArray = [keyValuePairString componentsSeparatedByString:@"="];
        if ([keyValuePairArray count] < 2) continue; // Verify that there is at least one key, and at least one value.  Ignore extra = signs
        NSString *key = [[keyValuePairArray objectAtIndex:0] stringByDecodingURLFormat];
        NSString *value = [[keyValuePairArray objectAtIndex:1] stringByDecodingURLFormat];
        NSMutableArray *results = [queryComponents objectForKey:key]; // URL spec says that multiple values are allowed per key
        if(!results) // First object
        {
            results = [NSMutableArray arrayWithCapacity:1];
            [queryComponents setObject:results forKey:key];
        }
        [results addObject:value];
    }
    return queryComponents;
}
@end

@implementation NSURL (XQueryComponents)
- (NSMutableDictionary *)queryComponents
{
    return [[self query] dictionaryFromQueryComponents];
}
@end

@implementation NSDictionary (XQueryComponents)
- (NSString *)stringFromQueryComponents
{
    NSString *result = nil;
    for(__strong NSString *key in [self allKeys])
    {
        key = [key stringByEncodingURLFormat];
        NSArray *allValues = [self objectForKey:key];
        if([allValues isKindOfClass:[NSArray class]])
            for(__strong NSString *value in allValues)
            {
                value = [[value description] stringByEncodingURLFormat];
                if(!result)
                    result = [NSString stringWithFormat:@"%@=%@",key,value];
                else 
                    result = [result stringByAppendingFormat:@"&%@=%@",key,value];
            }
        else {
            NSString *value = [[allValues description] stringByEncodingURLFormat];
            if(!result)
                result = [NSString stringWithFormat:@"%@=%@",key,value];
            else 
                result = [result stringByAppendingFormat:@"&%@=%@",key,value];
        }
    }
    return result;
}
@end

iki problem: 1) sözlüğe kaydetmeden önce hem anahtarı hem de değeri URL olarak çözmeniz gerekir ve 2) URL kurallarına göre, aynı anahtarı birden çok kez belirtmenize izin verilir. IOW, tek bir değere değil, bir değerler dizisine eşlenmiş bir anahtar olmalıdır.
Dave DeLong

Tamam, sadece dizi boyutuna bir kontrol ekleyin (bu, cevabıma olumsuz bir oylama gerektiriyor mu?) Bu kod sadece bir başlangıçtı (her zaman olduğu gibi SO'da). Tüm URL ile uyumlu olmak istiyorsanız, kaçış dizelerini, parçayı (sonunda # kısım) ele almak için daha fazla çalışmanız var ...
Benoît

Dave - İyi noktalar. İhtiyaçlarım için gerekli değildi, ancak bu yaygın sorunu ziyaret eden herkes için işe yarayacak bir cevap vermeye çalıştığım için söz konusu işlevselliği ekledim ... Benoit - Sadece cevabınızla konuya dikkatinizi çekiyorum, Bir düzenleme gönderdim. Muhtemelen iyi cevaplarda küçük sorunlara dikkat çekmek için kullanılabilecek en iyi form değil, gelecekte bunu yapmaktan kaçınacağım .. Yine de bir düzenleme tamamlanana kadar
olumsuz

StringByDecodingURLFormat'ta, 'sonuç' türü NSString * olmalıdır.
ThomasW

Sadece başka bir sorun fark ettim. Anahtar ve değer karışıyor, anahtar objectAtIndex: 0 ve objectAtIndex: 1 değeri olmalıdır.
ThomasW

13

Bunu dene ;)!

NSString *query = @"parameter=2&secondparameter=3"; // replace this with [url query];
NSArray *components = [query componentsSeparatedByString:@"&"];
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
for (NSString *component in components) {
    NSArray *subcomponents = [component componentsSeparatedByString:@"="];
    [parameters setObject:[[subcomponents objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
                   forKey:[[subcomponents objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}

1
Ayrıca - BadPirate tarafından belirtilen kilitlenme sorununun ötesinde - (1) sözlük anahtar / değerlerinin tersine çevrildiğini; (2) anahtar / değerler hala kodlanmıştır, bu nedenle stringByDecodingURLFormat
dpjanes

Bunu yapmanın gerçekten güzel bir yolu
Burf2000

9

Önceki tüm gönderiler url kodlamasını düzgün yapmıyor. Aşağıdaki yöntemleri öneririm:

+(NSString*)concatenateQuery:(NSDictionary*)parameters {
    if([parameters count]==0) return nil;
    NSMutableString* query = [NSMutableString string];
    for(NSString* parameter in [parameters allKeys])
        [query appendFormat:@"&%@=%@",[parameter stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet],[[parameters objectForKey:parameter] stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet]];
    return [[query substringFromIndex:1] copy];
}
+(NSDictionary*)splitQuery:(NSString*)query {
    if([query length]==0) return nil;
    NSMutableDictionary* parameters = [NSMutableDictionary dictionary];
    for(NSString* parameter in [query componentsSeparatedByString:@"&"]) {
        NSRange range = [parameter rangeOfString:@"="];
        if(range.location!=NSNotFound)
            [parameters setObject:[[parameter substringFromIndex:range.location+range.length] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] forKey:[[parameter substringToIndex:range.location] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
        else [parameters setObject:[[NSString alloc] init] forKey:[parameter stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    }
    return [parameters copy];
}

if(!query||[query length] == 0)gereksizdir. Uzunluğu aramaya çalışırsanız değerini döndürecek if([query length] == 0)durumda olduğu gibi güvenle kontrol edebilirsiniz . query == nil0
JRG-Developer

Bu, valueorkey değil, objectForKey kullanmamalı mı?
slf

Güzel kod. Tüm karakter kümelerini desteklemek için NSUTF8StringEncodingin kullanılmasını öneririm splitQuery:) Ayrıca, [string stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet]kodlamanın daha yeni bir yoludur concatenateQuery.
William Denniss

Değişmez bir örnek döndürmenin iyi bir uygulama olduğunu düşünüyorum, bu yüzden belki de son satırı [parametreler kopyası] döndürmek için değiştirmelisiniz;
Glenn Howes

Teşekkürler. Kodu yorumlarınıza göre uyarladım!
Kristian Kraljic

7

İşte swift'teki uzantı:

extension NSURL{
        func queryParams() -> [String:AnyObject] {
            var info : [String:AnyObject] = [String:AnyObject]()
            if let queryString = self.query{
                for parameter in queryString.componentsSeparatedByString("&"){
                    let parts = parameter.componentsSeparatedByString("=")
                    if parts.count > 1{
                        let key = (parts[0] as String).stringByReplacingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
                        let value = (parts[1] as String).stringByReplacingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
                        if key != nil && value != nil{
                            info[key!] = value
                        }
                    }
                }
            }
            return info
        }
    }

7

Onato'nun zaten çok net cevabına göre, Swift'de NSURL için şöyle bir sorgu parametresi alabileceğiniz bir uzantı yazdım:

örneğin, URL param = bir_değer çiftini içerir

let queryItem = url.queryItemForKey("param")
let value = queryItem.value // would get String "someValue"

Uzantı şuna benzer:

extension NSURL {

  var allQueryItems: [NSURLQueryItem] {
      get {
          let components = NSURLComponents(URL: self, resolvingAgainstBaseURL: false)!
          let allQueryItems = components.queryItems!
          return allQueryItems as [NSURLQueryItem]
      }
  }

  func queryItemForKey(key: String) -> NSURLQueryItem? {

      let predicate = NSPredicate(format: "name=%@", key)!
      return (allQueryItems as NSArray).filteredArrayUsingPredicate(predicate).first as? NSURLQueryItem

  }
}

Bu en iyi cevap! API belgelerini neden kontrol etmediler?
Jamin Zhang

5

Bolts Framework kullananlar için şunları kullanabilirsiniz:

NSDictionary *parameters = [BFURL URLWithURL:yourURL].inputQueryParameters;

İçeri aktarmayı unutmayın:

#import <Bolts/BFURL.h>

Eğer varsa işte cevabım Facebook SDK projenizde, ayrıca var Cıvata . Facebook bu çerçeveyi bağımlılık olarak kullanıyor.


Cıvatalarla Swift'de:BFURL(url: url)?.inputQueryParameters?["myKey"] as? String
JAL

4

URL'lerle başa çıkmanın tercih edilen yolu artık NSURLComponents. Özellikle queryItemsbir NSArrayparametresi döndüren özellik .

Parametreleri a'da istiyorsanız NSDictionary, işte bir yöntem:

+(NSDictionary<NSString *, NSString *>*)queryParamsFromURL:(NSURL*)url
{
    NSURLComponents* urlComponents = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO];

    NSMutableDictionary<NSString *, NSString *>* queryParams = [NSMutableDictionary<NSString *, NSString *> new];
    for (NSURLQueryItem* queryItem in [urlComponents queryItems])
    {
        if (queryItem.value == nil)
        {
            continue;
        }
        [queryParams setObject:queryItem.value forKey:queryItem.name];
    }
    return queryParams;
}

Uyarı: URL'lerde tekrarlanan parametreler olabilir, ancak sözlük yalnızca yinelenen herhangi bir parametrenin son değerini içerecektir. Bu istenmeyen bir durumsa, queryItemsdoğrudan diziyi kullanın.


3

Swift 2.1

Oneliner:

"p1=v1&p2=v2".componentsSeparatedByString("&").map {
    $0.componentsSeparatedByString("=") 
}.reduce([:]) {
    (var dict: [String:String], p) in
    dict[p[0]] = p[1]
    return dict
}

// ["p1": "v1", "p2": "v2"]

NSURL'de bir uzantı olarak kullanılır:

extension NSURL {

    /**
     * URL query string as dictionary. Empty dictionary if query string is nil.
     */
    public var queryValues : [String:String] {
        get {
            if let q = self.query {
                return q.componentsSeparatedByString("&").map {
                    $0.componentsSeparatedByString("=") 
                }.reduce([:]) {
                    (var dict: [String:String], p) in
                    dict[p[0]] = p[1]
                    return dict
                }
            } else {
                return [:]
            }
        }
    }

}

Misal:

let url = NSURL(string: "http://example.com?p1=v1&p2=v2")!
let queryDict = url.queryValues

// ["p1": "v1", "p2": "v2"]

OS X 10.10 veya iOS 8 (veya üstü) kullanıyorsanız NSURLComponents, queryItemsözelliği kullanmak ve sözlüğü NSURLQueryItemsdoğrudan.

İşte NSURLComponentstemelli bir NSURLuzantı çözümü:

extension NSURL {

    /// URL query string as a dictionary. Empty dictionary if query string is nil.
    public var queryValues : [String:String] {
        get {
            guard let components = NSURLComponents(URL: self, resolvingAgainstBaseURL: false) else {
                return [:]
            }

            guard let queryItems = components.queryItems else {
                return [:]
            }

            var result:[String:String] = [:]
            for q in queryItems {
                result[q.name] = q.value
            }
            return result
        }
    }

}

NSURL uzantısına ilişkin bir dipnot, Swift'de mülke varolan dize özelliği ile aynı adı vermenin aslında mümkün olduğudur query. Bunu deneyene kadar bilmiyordum, ancak Swift'deki polimorfizm sadece dönüş türünde farklılık göstermenize izin veriyor. Yani, genişletilmiş NSURL özelliği ise public var query: [String:String]çalışır. Bunu örnekte biraz çılgınca bulduğum için kullanmadım ama işe yarıyor ...


2

MIT altında işi yapan basit bir sınıf yayınladım:

https://github.com/anegmawad/URLQueryToCocoa

Bununla birlikte, sorguda toplanan ve birbirine yapıştırılmış diziler ve nesnelere sahip olabilirsiniz.

Örneğin

users[0][firstName]=Amin&users[0][lastName]=Negm&name=Devs&users[1][lastName]=Kienle&users[1][firstName]=Christian

Olacak:

@{
   name : @"Devs",
   users :
   @[
      @{
         firstName = @"Amin",
         lastName = @"Negm"
      },
      @{
         firstName = @"Christian",
         lastName = @"Kienle"
      }
   ]
 }

Bunu bir URL sorgusu muadili olarak düşünebilirsiniz NSJSONSerializer.


harika iş. Bu tek doğru cevap gibi görünüyor (dizi ve dikte değerlerini hesaba katan).
Anton Tropashko

2

Başka bir iOS uygulamasından gelen verileri işlemek için kullandığınız görülüyor. Eğer öyleyse, aynı amaç için kullandığım şey budur.

İlk arama (örneğin harici uygulamada):

UIApplication *application = [UIApplication sharedApplication];
NSURL *url = [NSURL URLWithString:@"myApp://action/1?parameter=2&secondparameter=3"];
if ([application canOpenURL:url]) {
    [application openURL:url];
    NSLog(@"myApp is installed");
} else {
    NSLog(@"myApp is not installed");
}

NSURL'den QueryString verilerini çıkarma ve NSDictionary olarak kaydetme yöntemi:

-(NSDictionary *) getNSDictionaryFromQueryString:(NSURL *)url {
   NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
   NSRange needle = [url.absoluteString rangeOfString:@"?" options:NSCaseInsensitiveSearch];
   NSString *data = nil;

   if(needle.location != NSNotFound) {
       NSUInteger start = needle.location + 1;
       NSUInteger end = [url.absoluteString length] - start;
       data = [url.absoluteString substringWithRange:NSMakeRange(start, end)];
   }

   for (NSString *param in [data componentsSeparatedByString:@"&"]) {
       NSArray *keyvalue = [param componentsSeparatedByString:@"="];
       if([keyvalue count] == 2){
           [result setObject:[keyvalue objectAtIndex:1] forKey:[keyvalue objectAtIndex:0]];
       }
   }

  return result;
}

Kullanım:

NSDictionary *result = [self getNSDictionaryFromQueryString:url];

0

Bu sınıf, url ayrıştırması için güzel bir çözümdür.

.h dosyası

@interface URLParser : NSObject {
    NSArray *variables;
}

@property (nonatomic, retain) NSArray *variables;

- (id)initWithURLString:(NSString *)url;
- (NSString *)valueForVariable:(NSString *)varName;

@end

.m dosyası

#import "URLParser.h"

@implementation URLParser
@synthesize variables;

- (id) initWithURLString:(NSString *)url{
    self = [super init];
    if (self != nil) {
        NSString *string = url;
        NSScanner *scanner = [NSScanner scannerWithString:string];
        [scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:@"&?"]];
        NSString *tempString;
        NSMutableArray *vars = [NSMutableArray new];
        [scanner scanUpToString:@"?" intoString:nil];       //ignore the beginning of the string and skip to the vars
        while ([scanner scanUpToString:@"&" intoString:&tempString]) {
            [vars addObject:[tempString copy]];
        }
        self.variables = vars;
    }
    return self;
}

- (NSString *)valueForVariable:(NSString *)varName {
    for (NSString *var in self.variables) {
        if ([var length] > [varName length]+1 && [[var substringWithRange:NSMakeRange(0, [varName length]+1)] isEqualToString:[varName stringByAppendingString:@"="]]) {
            NSString *varValue = [var substringFromIndex:[varName length]+1];
            return varValue;
        }
    }
    return nil;
}

@end

0

Hendrik bu soruda genişletme için güzel bir örnek yazdı, ancak objektif-c kütüphane yöntemlerini kullanmamak için yeniden yazmak zorunda kaldım. NSArrayHızlı kullanmak doğru bir yaklaşım değildir.

Sonuç bu, hepsi hızlı ve biraz daha güvenli. Kullanım örneği, Swift 1.2 ile daha az kod satırı olacaktır.

public extension NSURL {
    /*
    Set an array with all the query items
    */
    var allQueryItems: [NSURLQueryItem] {
        get {
            let components = NSURLComponents(URL: self, resolvingAgainstBaseURL: false)!
            if let allQueryItems = components.queryItems {
                return allQueryItems as [NSURLQueryItem]
            } else {
                return []
            }
        }
    }

    /**
    Get a query item form the URL query

    :param: key The parameter to fetch from the URL query

    :returns: `NSURLQueryItem` the query item
    */
    public func queryItemForKey(key: String) -> NSURLQueryItem? {
        let filteredArray = filter(allQueryItems) { $0.name == key }

        if filteredArray.count > 0 {
            return filteredArray.first
        } else {
            return nil
        }
    }
}

Kullanım:

let queryItem = url.queryItemForKey("myItem")

Veya daha ayrıntılı kullanım:

if let url = NSURL(string: "http://www.domain.com/?myItem=something") {
    if let queryItem = url.queryItemForKey("myItem") {
        if let value = queryItem.value {
            println("The value of 'myItem' is: \(value)")
        }
    }
}

0

bunu dene:

-(NSDictionary *)getUrlParameters:(NSString *)url{
    NSArray *justParamsArr = [url componentsSeparatedByString:@"?"];
    url = [justParamsArr lastObject];
    NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
    for (NSString *param in [url componentsSeparatedByString:@"&"]) {
        NSArray *elts = [param componentsSeparatedByString:@"="];
        if([elts count] < 2) continue;
        [params setObject:[elts lastObject] forKey:[elts firstObject]];
    }
    return params;
}

0

Oldukça kompakt yaklaşım:

    func stringParamsToDict(query: String) -> [String: String] {
        let params = query.components(separatedBy: "&").map {
            $0.components(separatedBy: "=")
        }.reduce(into: [String: String]()) { dict, pair in
            if pair.count == 2 {
                dict[pair[0]] = pair[1]
            }
        }
        return params
    }

-5

Web uygulamasından telefona veri aktarmak için bir URL kullanıyorsanız ve dizileri, sayıları, dizeleri vb. Aktarmak istiyorsanız en sağlam çözüm ...

JSON, nesnenizi PHP'de kodlar

header("Location: myAppAction://".urlencode(json_encode($YOUROBJECT)));

Ve JSON, sonucu iOS'ta çözer

NSData *data = [[[request URL] host] dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *packed = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

1
bu berbat bir fikir. Bir URL'nin, içinde JSON'u seri hale getiriyorsanız kolayca aşılabilecek bir uzunluk sınırı vardır.
Michael Baldry

yaklaşık 2000 karakter
Michael Baldry
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.