| Index: compiled/subscription/Subscription.cpp | 
| =================================================================== | 
| --- a/compiled/subscription/Subscription.cpp | 
| +++ b/compiled/subscription/Subscription.cpp | 
| @@ -34,16 +34,33 @@ Subscription::Subscription(Type type, co | 
| annotate_address(this, "Subscription"); | 
| } | 
|  | 
| Subscription::~Subscription() | 
| { | 
| knownSubscriptions.erase(mID); | 
| } | 
|  | 
| +Filter* Subscription::FilterAt(unsigned index) | 
| +{ | 
| +  if (index >= mFilters.size()) | 
| +    return nullptr; | 
| + | 
| +  FilterPtr result(mFilters[index]); | 
| +  return result.release(); | 
| +} | 
| + | 
| +int Subscription::IndexOfFilter(Filter* filter) | 
| +{ | 
| +  for (unsigned i = 0; i < mFilters.size(); i++) | 
| +    if (mFilters[i] == filter) | 
| +      return i; | 
| +  return -1; | 
| +} | 
| + | 
| OwnedString Subscription::Serialize() const | 
| { | 
| OwnedString result(u"[Subscription]\nurl="_str); | 
| result.append(mID); | 
| result.append(u'\n'); | 
| if (!mTitle.empty()) | 
| { | 
| result.append(u"title="_str); | 
| @@ -53,18 +70,27 @@ OwnedString Subscription::Serialize() co | 
| if (mDisabled) | 
| result.append(u"disabled=true\n"_str); | 
|  | 
| return result; | 
| } | 
|  | 
| OwnedString Subscription::SerializeFilters() const | 
| { | 
| -  // TODO | 
| -  return OwnedString(); | 
| +  if (!mFilters.size()) | 
| +    return OwnedString(); | 
| + | 
| +  OwnedString result(u"[Subscription filters]\n"_str); | 
| +  for (const auto& filter : mFilters) | 
| +  { | 
| +    // TODO: Escape [ characters | 
| +    result.append(filter->GetText()); | 
| +    result.append(u'\n'); | 
| +  } | 
| +  return result; | 
| } | 
|  | 
| Subscription* Subscription::FromID(const String& id) | 
| { | 
| if (id.empty()) | 
| { | 
| // Generate a new random ID | 
| unsigned seed = knownSubscriptions.size(); | 
| @@ -85,19 +111,19 @@ Subscription* Subscription::FromID(const | 
| if (knownSubscription) | 
| { | 
| knownSubscription->second->AddRef(); | 
| return knownSubscription->second; | 
| } | 
|  | 
| SubscriptionPtr subscription; | 
| if (!id.empty() && id[0] == '~') | 
| -    subscription = new UserDefinedSubscription(id); | 
| +    subscription = SubscriptionPtr(new UserDefinedSubscription(id), false); | 
| else | 
| -    subscription = new DownloadableSubscription(id); | 
| +    subscription = SubscriptionPtr(new DownloadableSubscription(id), false); | 
|  | 
| // This is a hack: we looked up the entry using id but create it using | 
| // subscription->mID. This works because both are equal at this point. | 
| // However, id refers to a temporary buffer which will go away. | 
| enter_context("Adding to known subscriptions"); | 
| knownSubscription.assign(subscription->mID, subscription.get()); | 
| exit_context(); | 
|  | 
|  |