Skip to end of metadata
Go to start of metadata

<ac:macro ac:name="note"><ac:parameter ac:name="title">Under Construction</ac:parameter><ac:rich-text-body>
<p>Proposal withdrawn.</p></ac:rich-text-body></ac:macro>

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Oct 31, 2007

    <p>I have a tracker component lying around but right now it's not generic enough to fit in the Zend Framework. The tracker could maybe be added to this component at a later time as Zend_Bittorrent_Tracker...</p>

  2. Oct 31, 2007

    <p>I'm not that familiarly with Bittorrent development, so I really want to know what is the deal with this class.</p>

    <p>This is not a critic! <ac:emoticon ac:name="smile" /></p>

    <p>Thank you</p>

    1. Oct 31, 2007

      <p>The most common usage would be to decode torrent files to get information about the files that are included in the torrent. All sites that offer .torrent files most likely use some sort of library to fetch this info from the torrent files, and I thought it would be nice to have this in the framework. </p>

      <p>As I wrote in the first comment here I have a bittorrent tracker written in PHP that can be added later that would make the component more complete.</p>

  3. Nov 02, 2007

    <p>Apart from being able to <strong>read</strong> from files, I also would like to see either a separate function (akin to simplexml_load_string and simplexml_load_file) to load the torrent file data from a string. I have seen many implementations that always assume one wants a file and never give this option.</p>

    1. Nov 02, 2007

      <p>What do you mean? That one wants to give the decode method the content of the torrent file instead of the path to the file?</p>

      <p>If that is what you mean you can just do a Zend_Bittorrent::decode(file_get_contents('/path/to/file)); since torrent files are just an encoded associative array.</p>

      1. Nov 02, 2007

        <p>My apologies, I was still a bit tired after getting up and reading up on some buffer of notifications. I'm personally looking forward for this class finalized and included in the framework.</p>

  4. Nov 05, 2007

    <p>I just updated the proposal with information about the Zend_Bittorrent_Torrent class that can be used to generate .torrent files.</p>

  5. Dec 01, 2007

    <p>I have added the code to the laboratory at <a href="http://framework.zend.com/svn/laboratory/library/Zend/">http://framework.zend.com/svn/laboratory/library/Zend/</a>. Feel free to play around with it. <ac:emoticon ac:name="smile" /></p>

  6. Dec 06, 2007

    <p>Hi Christer,</p>

    <p>Looks interesting. Note that it would be Zend_BitTorrent, with a capital T.</p>

    <p>You might also try to split up the Zend_BitTorrent_Torrent::buildFromPath() method into a couple other methods, because it's pretty long at the moment.</p>

    <p>-Matt</p>

    1. Dec 06, 2007

      <p>Thats my bad. I'll fix the capitalization tomorrow.</p>

      <p>I'll be leaving for a week's vacation on saturday, so I'll get to the buildFromPath method as soon as I get back.</p>

  7. Dec 07, 2007

    <p>This looks like a promising component, and I'd very much like to see it in Zend Framework. Following are the results from my initial review for consideration:</p>

    <p>The prolific use of static methods irks me a bit, as we might be better served by having instance methods, but perhaps it can be shown that static methods will not be a problem.</p>
    <ul>
    <li>How might the component support caching?</li>
    <li>How to support instances having different behaviors (e.g., caching, logging)?</li>
    <li>What about extending the classes for custom behavior? (e.g., <code>Zend_BitTorrent_Encoder::encodeList()</code> uses <code>self</code>)</li>
    </ul>

    <p>I would recommend different placement of the <code>require_once</code> statements for lazy-loading classes, especially those for exceptions.</p>

    <p>There is no need to use <code>Zend_Loader::loadClass()</code> within this component. Just use <code>require_once</code>.</p>

    <p>What about having exception classes inherit from <code>Zend_BitTorrent_Exception</code>?</p>

    <p>Don't forget to use the one true brace convention, with method and class opening braces on the next line.</p>

    <p>Per-class suggestions:<br />
    <code>Zend_BitTorrent</code></p>
    <ul>
    <li><code>decode()</code>
    <ul>
    <li>Recommend removal of "<code>=== true</code>"</li>
    <li>Enumerate the types that encode()/decode() accept/return (e.g., <code>integer|string|array</code>)</li>
    </ul>
    </li>
    </ul>

    <p><code>Zend_BitTorrent_Encoder</code></p>
    <ul>
    <li><code>encode()</code>
    <ul>
    <li>Recommend use of <code>switch(gettype($var))</code> instead of <code>if...else if...</code></li>
    </ul>
    </li>
    <li><code>encodeInteger(), encodeString(), encodeList(), encodeDictionary()</code>
    <ul>
    <li>Use <code>gettype()</code> once, no need for <code>is...()</code> functions</li>
    </ul>
    </li>
    </ul>

    <p><code>Zend_BitTorrent_Decoder</code></p>
    <ul>
    <li><code>decodeFile()</code>
    <ul>
    <li>Recommend removal of "<code>=== true</code>"</li>
    </ul>
    </li>
    <li><code>decode()</code>
    <ul>
    <li>Recommend different regular expression <code>preg_match('/^\d+:/', $string)</code></li>
    </ul>
    </li>
    <li><code>decodeInteger(), decodeString()</code>
    <ul>
    <li>Recommend different exception messages for different exception cases</li>
    </ul>
    </li>
    <li><code>decodeList(), decodeDictionary()</code>
    <ul>
    <li>Is there really a need to re-encode some parts? Why not just strlen() the encoded part before decoding it?</li>
    </ul>
    </li>
    </ul>

    <p><code>Zend_BitTorrent_Torrent</code></p>
    <ul>
    <li>What benefits does the static factory method have over the "<code>new</code>" operator?
    <ul>
    <li>What about extending the class?</li>
    </ul>
    </li>
    <li>On what basis have the values of the class constants been selected?</li>
    <li>Protected variable names should begin with underscores (e.g., <code>$_protectedMember</code>)</li>
    <li>Does <code>isReadyToBeBuilt()</code> return <code>true</code> even if the object has already been built?</li>
    </ul>

    1. Dec 07, 2007

      <p>Thanks for the comment. I'll try to answer everything (I'm a bit short on time, traveling to Spain tomorrow for a week of climbing).</p>

      <p>The component might be better off without the static methods and having instances of the classes instead so users can more easily extend the classes.</p>

      <p>I'm not sure how other components in ZF deal with caching. I suppose there is not too much hassle to have caching functionality in the component and just let the user enable/disable it. What do you think would be the best option? To implement it in the component or having users extend the classes?</p>

      <p>When having instances I can also drop the is*() function calls in the methods that require variables of specific types. If I skip that function call and keep the methods static I would have to make them protected and force the user to only use the generic encode() method. That way I know the input to the protected methods are correct. That would probably work just fine. It does not produce that much overhead. But if we have an instance we could just check the input in the constructor and use that information to skip the is*() calls and have all methods public. Personally I tend to like to be able to call encodeString() if I know my data is a string and not a generic encode() method.</p>

      <p>When you say "different placement of the require_once statements for lazy-loading classes" I'm not sure I understand correctly. Would you want them in the code where the exceptions are thrown instead of calls to Zend_Loader? If so, I agree.</p>

      <p>The main reason for reencoding data in the decoder is because of how strings are handled. Lets say we want to decode "3:foobar". The decoder will give you (string) "foo" and just discard the rest of the input since the prefix of the encoded string is 3 (the length of the original string). Because of that we can't do a strlen($str) since that would return 6, and not 3 which is the correct length. This might be one good reason for implementing caching in the component instead of having users do it themselves.</p>

      <blockquote>
      <p>What benefits does the static factory method have over the "new" operator?</p></blockquote>

      <p>Not much really. I know some users think it's easier to use factory methods because if often results in fewer lines of code and less possibilities for errors. Personally I think it's a bit cleaner to have a factory method but I'm not saying it's better or worse than having a public constructor.</p>

      <blockquote>
      <p>What about extending the class?</p></blockquote>
      <p>Seems like ditching the factory method and sticking with __construct might be a better idea, yes.</p>

      <blockquote><p>On what basis have the values of the class constants been selected?</p></blockquote>
      <p>On no basis at all actually. There were just the first that came to my mind. I just read the part about class constants in the Coding Standard document and saw how it should be done. I could just change them to "TORRENT_CREATE_FROM_FILE" and so on. Would that be better?</p>

      <blockquote><p>Does isReadyToBeBuilt() return true even if the object has already been built?</p></blockquote>
      <p>Seems like it. I could just see if it was already built and if so, return false. That might be more logical since there is no reason for building the torrent twice.</p>

      <p>If I have skipped a questions it's just because I agree and have nothing more to add. <ac:emoticon ac:name="smile" /></p>

      <p>I will get to the changes when I get back from my vacation.</p>

      <p>Don't hesitate to add more comments if something is unclear.</p>

      <p>Thanks</p>

      1. Dec 11, 2007

        <p>With respect to caching, I think that we can find candidates for caching opportunities during incubation (development in <code>trunk/incubator</code>). We should probably not spend much time on premature optimization at this point. Just something to keep in mind. <ac:emoticon ac:name="smile" /></p>

        <p>I don't see any need to drop the type-specific <code>encode...()</code> methods such as <code>encodeString()</code> from the public interface. As you noted, it will likely be desirable to call these methods directly when working with known types.</p>

        <p>Regarding the use of <code>require_once</code>, yes, I mean to suggest that these statements be located immediately prior to the use of such classes, as in "lazy loading". For example, in a method that throws an exception:</p>

        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        public function someMethod()
        {
        ...
        if (!$someCondition)

        Unknown macro: { /** @see Zend_Exception */ require_once 'Zend/Exception.php'; throw new Zend_Exception(...); }

        ...
        }
        ]]></ac:plain-text-body></ac:macro>

        <p>Regarding constants, we have both names and values. I recommend that names begin with the general and end with the specific (e.g., PATH_CONFIG, LOCATION_COUNTRY). I don't see much problem with the names of the constants you have selected. I was wondering more about the <em>values</em> of these constants, and how these have been chosen.</p>

        <p>Have a great vacation, and I look forward to your return! <ac:emoticon ac:name="smile" /></p>

  8. Dec 16, 2007

    <p>Christer, is it your intention to get this in to core for the 1.5 release? If so, let us know as soon as the proposal is ready for core team review and we'll turn it around as quickly as possible so you can get it in incubator and the hands of our users. The other possibility is to have it in incubator during 1.5, where it will likely benefit from the general attention we'll be getting around the release.</p>

    1. Dec 17, 2007

      <p>It's probably better to let it stay in incubator during 1.5 as you say. I currently don't have too much time to spend on this. Since we use ZF at the place I work I might be able to convince my boss to let me work on ZF related stuff during my work hours though, but anyways I think it might be better to not rush with the component.</p>

  9. Dec 20, 2007

    <p>I have updated the proposal a bit. It now includes all source code of the component. The component is in the laboratory as well.</p>

    <p>There are some changes that are not in svn yet because of some issues with my laptop. One of the changes I can remember is that I have prefixed the protected properties in the Zend_BitTorrent_Torrent class with an underscore. There are some other minor changes but I can't access my laptop now to see what it is as of now.</p>

    1. Dec 20, 2007

      <p>Thanks for this, Christer! <ac:emoticon ac:name="smile" /></p>

      <p>I had another comment and a question I wanted to share:</p>

      <p>We should consider moving this component to the <code>Zend_Service_*</code> "namespace", especially as this component could be used in affiliation with remote services (e.g., a torrent tracker). What do you think about contributing the tracker component you've written? The API and/or implementation can be improved during its lifetime in the laboratory and/or incubator, if you're concerned about that.</p>

      1. Dec 21, 2007

        <p>I have actually started making the tracker I have more generic, but it's going to take some effort from the users wanting to use a tracker component to make it fit in with their database setup regarding users and storage of the torrent files and such. I can try to patch things up a bit and make something presentable and make a separate proposal for it. Does that sound ok? I would think that finishing up the tracker would take a bit more time than the rest of the BitTorrent stuff I am working on though.</p>

        <p>I am not sure if I agree with putting this in Zend_Service_* though. I thought that was more suited for web services and not a "server" component like a tracker? Maybe I'm just missing out on something here (which is usually the case <ac:emoticon ac:name="cheeky" />)</p>

        1. Dec 21, 2007

          <p>Sounds good to me.</p>

  10. Jan 03, 2008

    <ac:macro ac:name="note"><ac:parameter ac:name="title">Zend Comments</ac:parameter><ac:rich-text-body>
    <p>This proposal exposes a nice API for working with torrent files. The provided functionality appears to be quite useful, but we're unsure about how much demand exists for the functionality among framework users. We can gauge this demand as the component is made available through the laboratory, and the community has time to understand and use it where appropriate. We suggest that adding a torrent tracker would add value to the component and may help increase adoption. The proposed component is at this time approved for continued development in the laboratory.</p></ac:rich-text-body></ac:macro>

  11. Dec 30, 2008

    <ac:macro ac:name="note"><ac:parameter ac:name="title">Zend Official Response</ac:parameter><ac:rich-text-body>

    <p>We have tentatively accepted this proposal for laboratory development provided this proposal can be rounded out and more information on this component "will not" intend to do (specifically with regards to the portions of bittorent implementation that this component will not touch).</p>

    <p>Currently, our comments from before still exist. I have read up on the bittorrent technology and have a few areas where your comments and expertise are needed any our concerns met:</p>
    <ul>
    <li>Is it possible that there are more "server capabilities" can be expanded?
    <ul>
    <li>currently, it seems as though this proposal is centered around the torrent meta info file.. but can it be expanded to include additional tracker, super-seeder, or some client functionality to bring more "value added" to the table?</li>
    </ul>
    </li>
    <li>Once that concern is met, we can discuss the API. Generally, we are out to achieve a heterogeneous yet intuitive API. By this, I mean is it possible that for the torrent file, the object is the same yet the encoding and decoding is part of the same object's api. For example, to create a new Zend_Bittorrent(), the to be able to call write() on that object to produce a file. We can discuss this more either here or via other communication mediums to flesh out these details.</li>
    </ul>

    <p>-ralph</p>
    </ac:rich-text-body></ac:macro>

    1. Feb 17, 2009

      <p>First, sorry about my late reply!</p>

      <p>I would love to discuss this proposal further. It should be mentioned that there is a separate proposal here about a Zend_BitTorrent_Tracker component over at <a class="external-link" href="http://framework.zend.com/wiki/display/ZFPROP/Zend_BitTorrent_Tracker+-+Christer+Edvartsen">http://framework.zend.com/wiki/display/ZFPROP/Zend_BitTorrent_Tracker+-+Christer+Edvartsen</a>.</p>

      <p>Feel free to send me a mail as it's probably easier to discuss it via mail instead of comments here.</p>

    2. Feb 26, 2010

      <p>I have finally found some time to do some work on this subject. I have updated the other proposal I have here regarding a tracker component to Zend Framework (<a class="external-link" href="http://framework.zend.com/wiki/display/ZFPROP/Zend_BitTorrent_Tracker+-+Christer+Edvartsen">http://framework.zend.com/wiki/display/ZFPROP/Zend_BitTorrent_Tracker+-+Christer+Edvartsen</a>). We should probably merge that one with this instead of having two separate proposals.</p>

  12. Nov 22, 2010

    <p>I discovered a bug in decoding and encoding on 32bit systems. The integer fields in the torrent for individual file lengths or the overall torrent length can be greater than the PHP limit of 2GiB but the decoder casts them to (int) which causes integer overflow. </p>

    <p>In this situation there are no exceptions thrown but the decoded file lengths are incorrect.</p>

    <p>A partial solution may be to cast the value as (float) in decodeInteger(), and treat (float) type the same as (int) in encode().</p>