Skip to content

Fix: improve encoder functions according to RFC#8

Merged
lohanidamodar merged 12 commits intomainfrom
fix-txt-records-handling
Jul 28, 2025
Merged

Fix: improve encoder functions according to RFC#8
lohanidamodar merged 12 commits intomainfrom
fix-txt-records-handling

Conversation

@lohanidamodar
Copy link
Contributor

@lohanidamodar lohanidamodar commented Jul 27, 2025

  • Improve encoder functions
  • Improve zone export/import handling

Summary by CodeRabbit

  • Bug Fixes
    • Improved DNS record encoding for IPv4, IPv6, domain, TXT, MX, SRV, and CAA types with enhanced validation and RFC compliance.
    • Enhanced DNS zone file parsing and tokenization to properly handle quoted strings, escape sequences, and comment stripping, especially for TXT records.
    • Refined TXT record parsing to handle empty chunks and concatenate text without extra spaces.
  • Tests
    • Updated TXT record tests to include additional DMARC policy validation for improved coverage.
    • Added new tests for importing and exporting TXT records with special characters and quoted strings.
  • Chores
    • Added new TXT DNS record with DMARC policy to the memory resolver for extended test scenarios.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 27, 2025

"""

Walkthrough

This change refactors and enhances DNS record encoding in the Server class by introducing new protected methods for encoding different record types according to RFC specifications. Additionally, the tokenize method in Zone is improved to accurately parse quoted strings and escape sequences in DNS zone files. TXT record handling in import/export is refined to preserve semicolons and properly escape characters. Tests and in-memory DNS records are updated to include a new TXT record with a DMARC policy. The TXT record parsing in the client is also refined for improved formatting.

Changes

File(s) Change Summary
src/DNS/Server.php Added protected methods for RFC-compliant encoding of IP, IPv6, domain, TXT, MX, SRV, and CAA records with validation and TTL/length packing. Introduced constants for DNS limits. No public API changes.
src/DNS/Zone.php Rewrote tokenize to handle quoted strings and escapes per RFC 1035; updated stripTrailingComment to respect quoted semicolons and conditionally strip comments for TXT records; refined TXT import/export to preserve semicolons and escape quotes/backslashes; adjusted import to detect TXT records and handle comments accordingly.
src/DNS/Client.php Modified TXT record parsing to check chunk length before extraction and changed concatenation of TXT chunks from space-separated to direct join without delimiter.
tests/DNS/ClientTest.php, tests/DNS/ServerMemory.php Added a new TXT DNS record with a DMARC policy for dev2.appwrite.io and updated tests to verify its presence and correctness.
tests/DNS/ZoneTest.php Added tests verifying import and export of TXT records containing special characters, including semicolon-separated key-value pairs and escaped quotes/backslashes.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Server
    participant Zone

    Client->>Server: Send DNS query
    Server->>Zone: (if needed) Parse zone file line (tokenize)
    Zone-->>Server: Return parsed tokens
    Server->>Server: Encode answer using encodeIP/encodeIPv6/encodeDomain/encodeText/encodeMx/encodeSrv/encodeCAA
    Server-->>Client: Send DNS response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes

Possibly related PRs

  • Fix: encoding decoding of CAA records #7: Adds encoding and decoding support for the CAA DNS record type in the Server class, similar to this PR's addition of encoding methods for other DNS record types.

Suggested reviewers

  • vermakhushboo
  • Meldiron

Poem

🐇 In burrows deep where DNS plays,
Encoding hops through byte arrays.
Quotes and semis now well tamed,
TXT records rightly framed.
With new methods neat and tight,
This bunny’s code shines bright tonight! ✨
📡🐰
"""


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7650f28 and d806436.

📒 Files selected for processing (1)
  • src/DNS/Server.php (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/DNS/Server.php
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-txt-records-handling

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/DNS/Zone.php (1)

363-410: Enhanced tokenization implementation looks solid and RFC 1035 compliant.

The new implementation correctly handles quoted strings and escape sequences as specified in RFC 1035. The state machine approach with $inQuote and $escape flags properly manages the parsing logic.

However, consider adding validation for edge cases:

 protected function tokenize(string $line): array
 {
     $tokens = [];
     $current = '';
     $inQuote = false;
     $escape = false;
     for ($i = 0, $len = strlen($line); $i < $len; $i++) {
         $c = $line[$i];
         if ($escape) {
             $current .= $c;
             $escape = false;
             continue;
         }
         if ($c === '\\') {
             $escape = true;
             continue;
         }
         if ($inQuote) {
             if ($c === '"') {
                 $inQuote = false;
                 $tokens[] = $current;
                 $current = '';
             } else {
                 $current .= $c;
             }
         } else {
             if ($c === '"') {
                 $inQuote = true;
             } elseif ($c === ' ' || $c === "\t") {
                 if ($current !== '') {
                     $tokens[] = $current;
                     $current = '';
                 }
             } else {
                 $current .= $c;
             }
         }
     }
+    // Validate state at end of parsing
+    if ($inQuote) {
+        throw new \InvalidArgumentException('Unterminated quoted string in line');
+    }
+    if ($escape) {
+        throw new \InvalidArgumentException('Escape character at end of line');
+    }
     if ($current !== '') {
         $tokens[] = $current;
     }
     return $tokens;
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3d1afe1 and be5f654.

📒 Files selected for processing (2)
  • src/DNS/Server.php (1 hunks)
  • src/DNS/Zone.php (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Unit & E2E
🔇 Additional comments (4)
src/DNS/Server.php (4)

340-348: IPv4 encoding implementation is correct and RFC 1035 compliant.

The method properly validates the binary IP address length and uses the correct packing format with TTL and data length.


357-365: IPv6 encoding implementation is correct and RFC 3596 compliant.

The method properly validates the 16-byte IPv6 address length and follows the same pattern as IPv4 encoding.


400-411: TXT record encoding implementation is RFC 1035 compliant.

The method correctly handles text chunking into 255-byte segments with proper length prefixes. This follows the TXT record format specification.


283-293: Record type encoding integration looks well-structured.

The match expression properly maps each record type to its corresponding encoding method, and the method signatures align correctly with the usage patterns.

@lohanidamodar lohanidamodar requested a review from stnguyen90 July 27, 2025 03:45
@lohanidamodar lohanidamodar requested a review from eldadfux July 27, 2025 04:15
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
tests/DNS/ZoneTest.php (2)

341-352: Fix indentation inconsistency.

The method uses 5-space indentation while the rest of the file consistently uses 4-space indentation.

-     public function testImportTxtWithSpecialChars()
-     {
-         $zone = new Zone();
-         $zonefile = <<<ZONE
+    public function testImportTxtWithSpecialChars()
+    {
+        $zone = new Zone();
+        $zonefile = <<<ZONE
 @ 3600 IN TXT "v=DMARC1; p=none; rua=mailto:jon@snow.got; ruf=mailto:jon@snow.got; fo=1;"
 ZONE;
-         $records = $zone->import('example.com', $zonefile);
-         $this->assertCount(1, $records);
-         $rec = $records[0];
-         $this->assertEquals('TXT', $rec->getTypeName());
-         $this->assertEquals('v=DMARC1; p=none; rua=mailto:jon@snow.got; ruf=mailto:jon@snow.got; fo=1;', trim($rec->getRdata(), '"'));
-     }
+        $records = $zone->import('example.com', $zonefile);
+        $this->assertCount(1, $records);
+        $rec = $records[0];
+        $this->assertEquals('TXT', $rec->getTypeName());
+        $this->assertEquals('v=DMARC1; p=none; rua=mailto:jon@snow.got; ruf=mailto:jon@snow.got; fo=1;', trim($rec->getRdata(), '"'));
+    }

344-346: Consider testing additional edge cases for comprehensive coverage.

While the current test covers DMARC policy strings well, consider adding test cases for other TXT record edge cases to ensure the improved tokenization handles all scenarios mentioned in the RFC improvements.

Additional test cases could include:

  • TXT records with escaped quotes: "some \"quoted\" text"
  • Multiple quoted strings: "first part" "second part"
  • Mixed quoted and unquoted content
  • TXT records with backslash escapes

Would you like me to generate additional test methods for these edge cases?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 614b63d and 957e01e.

📒 Files selected for processing (2)
  • src/DNS/Zone.php (2 hunks)
  • tests/DNS/ZoneTest.php (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/DNS/Zone.php
🔇 Additional comments (1)
tests/DNS/ZoneTest.php (1)

341-352: Excellent test coverage for TXT record parsing improvements.

This test effectively validates the enhanced tokenization of quoted TXT records containing special characters like semicolons, colons, equals signs, and email addresses. The test logic correctly verifies both the record type and the RDATA content with proper quote handling.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🔭 Outside diff range comments (1)
src/DNS/Zone.php (1)

404-447: Handle incomplete escape sequences at end of line.

The tokenizer correctly implements RFC 1035 quoted string parsing, but doesn't handle the edge case where a backslash appears at the end of the line without a following character to escape.

Consider adding validation for incomplete escape sequences:

         }
         if ($current !== '') {
             $tokens[] = $current;
         }
+        // Handle incomplete escape at end of line
+        if ($escape) {
+            // Log warning or throw exception for malformed input
+        }
         return $tokens;

Otherwise, the implementation correctly handles quoted strings and escape sequences per RFC 1035.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 957e01e and 23ff429.

📒 Files selected for processing (2)
  • src/DNS/Zone.php (6 hunks)
  • tests/DNS/ZoneTest.php (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/DNS/ZoneTest.php
🔇 Additional comments (3)
src/DNS/Zone.php (3)

232-239: LGTM: Correct TXT record data handling per RFC 1035.

The concatenation without spaces for TXT records is correct according to RFC 1035, which specifies that multiple character strings in TXT records should be concatenated together.


285-289: LGTM: Proper TXT record encoding with correct escape sequence.

The escaping order (backslashes first, then quotes) is correct to prevent double-escaping, and wrapping in quotes follows DNS zone file standards.


293-300: LGTM: Improved output formatting for consistency.

The logic correctly removes trailing empty lines and ensures exactly one newline at the end, improving the consistency of exported zone files.

@lohanidamodar lohanidamodar requested a review from Meldiron July 28, 2025 01:01
@lohanidamodar lohanidamodar requested a review from abnegate July 28, 2025 07:58
@lohanidamodar lohanidamodar merged commit 55caf0e into main Jul 28, 2025
4 checks passed
@lohanidamodar lohanidamodar deleted the fix-txt-records-handling branch July 28, 2025 08:20
@coderabbitai coderabbitai bot mentioned this pull request Sep 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants